diff --git a/MAINTAINERS b/MAINTAINERS index 3827e5e190c26af71cd913f36d401821e3752c03..f9de0420841fd95a166bf5d5c284ff44daf3b6ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9718,6 +9718,11 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/gpd-pocket-fan.c +GPIB DRIVERS +M: Dave Penkler <dpenkler@gmail.com> +S: Maintained +F: drivers/staging/gpib/ + GPIO ACPI SUPPORT M: Mika Westerberg <mika.westerberg@linux.intel.com> M: Andy Shevchenko <andriy.shevchenko@linux.intel.com> @@ -22135,17 +22140,6 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/staging/media/atomisp/ -STAGING - FIELDBUS SUBSYSTEM -M: Sven Van Asbroeck <TheSven73@gmail.com> -S: Maintained -F: drivers/staging/fieldbus/* -F: drivers/staging/fieldbus/Documentation/ - -STAGING - HMS ANYBUS-S BUS -M: Sven Van Asbroeck <TheSven73@gmail.com> -S: Maintained -F: drivers/staging/fieldbus/anybuss/ - STAGING - INDUSTRIAL IO M: Jonathan Cameron <jic23@kernel.org> L: linux-iio@vger.kernel.org @@ -22160,18 +22154,6 @@ L: linux-tegra@vger.kernel.org S: Maintained F: drivers/staging/nvec/ -STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON) -M: Jens Frederich <jfrederich@gmail.com> -M: Jon Nettleton <jon.nettleton@gmail.com> -S: Maintained -W: http://wiki.laptop.org/go/DCON -F: drivers/staging/olpc_dcon/ - -STAGING - REALTEK RTL8712U DRIVERS -M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>. -S: Odd Fixes -F: drivers/staging/rtl8712/ - STAGING - SEPS525 LCD CONTROLLER DRIVERS M: Michael Hennerich <michael.hennerich@analog.com> L: linux-fbdev@vger.kernel.org @@ -22187,11 +22169,6 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/staging/sm750fb/ -STAGING - VIA VT665X DRIVERS -M: Philipp Hortmann <philipp.g.hortmann@gmail.com> -S: Odd Fixes -F: drivers/staging/vt665?/ - STAGING SUBSYSTEM M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> L: linux-staging@lists.linux.dev diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index fcdd559a8acfd7841b1b134a73705f4e4157d859..075e775d3868b3449922a25df1f79dec5a83a42d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -24,20 +24,10 @@ menuconfig STAGING if STAGING -source "drivers/staging/olpc_dcon/Kconfig" - source "drivers/staging/rtl8723bs/Kconfig" -source "drivers/staging/rtl8712/Kconfig" - -source "drivers/staging/rts5208/Kconfig" - source "drivers/staging/octeon/Kconfig" -source "drivers/staging/vt6655/Kconfig" - -source "drivers/staging/vt6656/Kconfig" - source "drivers/staging/iio/Kconfig" source "drivers/staging/sm750fb/Kconfig" @@ -46,8 +36,6 @@ source "drivers/staging/nvec/Kconfig" source "drivers/staging/media/Kconfig" -source "drivers/staging/gdm724x/Kconfig" - source "drivers/staging/fbtft/Kconfig" source "drivers/staging/most/Kconfig" @@ -58,8 +46,8 @@ source "drivers/staging/vc04_services/Kconfig" source "drivers/staging/axis-fifo/Kconfig" -source "drivers/staging/fieldbus/Kconfig" - source "drivers/staging/vme_user/Kconfig" +source "drivers/staging/gpib/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 4a84c4848664a439399cc8accd0d94fb74c39289..e681e403509ce271d388a5b0e70b296c41474f40 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -2,21 +2,15 @@ # Makefile for staging directory obj-y += media/ -obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ obj-$(CONFIG_RTL8723BS) += rtl8723bs/ -obj-$(CONFIG_R8712U) += rtl8712/ -obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ -obj-$(CONFIG_VT6655) += vt6655/ -obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme_user/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_FB_SM750) += sm750fb/ obj-$(CONFIG_MFD_NVEC) += nvec/ -obj-$(CONFIG_LTE_GDM724X) += gdm724x/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ -obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ +obj-$(CONFIG_GPIB) += gpib/ diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c index 1bbb9a6db5979aff0ed1a17ed2aa955e2bfbf487..7540c20090c78b817c1fb825a2fe340912e4b9a4 100644 --- a/drivers/staging/axis-fifo/axis-fifo.c +++ b/drivers/staging/axis-fifo/axis-fifo.c @@ -919,7 +919,7 @@ static struct platform_driver axis_fifo_driver = { .of_match_table = axis_fifo_of_match, }, .probe = axis_fifo_probe, - .remove_new = axis_fifo_remove, + .remove = axis_fifo_remove, }; static int __init axis_fifo_init(void) diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index 3e00a26a29d5c346734ec3189380a1c66bf89f80..317be17b95c1672404fc6aecda24d0a1f563685d 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -330,7 +330,7 @@ static struct platform_driver fbtft_driver_platform_driver = { \ .of_match_table = dt_ids, \ }, \ .probe = fbtft_driver_probe_pdev, \ - .remove_new = fbtft_driver_remove_pdev, \ + .remove = fbtft_driver_remove_pdev, \ }; \ \ static int __init fbtft_driver_module_init(void) \ diff --git a/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev b/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev deleted file mode 100644 index 45f631ea32a60c9cc60baed6e6cbd4c0dc8019e5..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev +++ /dev/null @@ -1,31 +0,0 @@ -What: /dev/fieldbus_devX -Date: December 2018 -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - The cdev interface to drivers for Fieldbus Device Memory - (aka. Process Memory). - - The following file operations are supported: - - open(2) - Create an I/O context associated with the file descriptor. - - read(2) - Read from Process Memory's "read area". - Clears POLLERR | POLLPRI from the file descriptor. - - write(2) - Write to Process Memory's "write area". - - poll(2), select(2), epoll_wait(2) etc. - When a "Process Memory Read Area Changed" event occurs, - POLLERR | POLLPRI will be set on the file descriptor. - Note that POLLIN | POLLOUT events are always set, because the - process memory area is always readable and writable. - - close(2) - Free up the I/O context that was associated - with the file descriptor. - -Users: TBD diff --git a/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev b/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev deleted file mode 100644 index 439f14d33c3bfb90c001a6093af13224a353999b..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev +++ /dev/null @@ -1,62 +0,0 @@ -What: /sys/class/fieldbus_dev/fieldbus_devX/card_name -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - Human-readable name of the Fieldbus Device. - -What: /sys/class/fieldbus_dev/fieldbus_devX/fieldbus_type -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - The type of fieldbus implemented by this device. - Possible values: - 'unknown' - 'profinet' - -What: /sys/class/fieldbus_dev/fieldbus_devX/fieldbus_id -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - The unique fieldbus id associated with this device. - The exact format of this id is fieldbus type dependent, e.g. - a mac address for profinet. - -What: /sys/class/fieldbus_dev/fieldbus_devX/read_area_size -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - The size, in bytes, of the Process Memory read area. - Note: this area is accessible by reading from the associated - character device (/dev/fieldbus_devX). - -What: /sys/class/fieldbus_dev/fieldbus_devX/write_area_size -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - The size, in bytes, of the Process Memory write area. - Note: this area is accessible by writing to the associated - character device (/dev/fieldbus_devX) - -What: /sys/class/fieldbus_dev/fieldbus_devX/online -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - Whether the fieldbus is online or offline. - Possible values: - '1' meaning 'online' - '0' meaning 'offline' - Note: an uevent is generated when this property changes. - -What: /sys/class/fieldbus_dev/fieldbus_devX/enabled -KernelVersion: 5.1 (staging) -Contact: Sven Van Asbroeck <TheSven73@gmail.com> -Description: - Whether the device is enabled (power on) or - disabled (power off). - Possible values: - '1' meaning enabled - '0' meaning disabled - Normally a r/o property, but optionally r/w: - Writing '1' enables the device (power on) with default - settings. - Writing '0' disables the card (power off). diff --git a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt deleted file mode 100644 index f34a95611645bd5d889384dfa547a4a47bd1b36d..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt +++ /dev/null @@ -1,71 +0,0 @@ -* Arcx Anybus-S controller - -This chip communicates with the SoC over a parallel bus. It is -expected that its Device Tree node is specified as the child of a node -corresponding to the parallel bus used for communication. - -Required properties: --------------------- - - - compatible : The following chip-specific string: - "arcx,anybus-controller" - - - reg : three areas: - index 0: bus memory area where the cpld registers are located. - index 1: bus memory area of the first host's dual-port ram. - index 2: bus memory area of the second host's dual-port ram. - - - reset-gpios : the GPIO pin connected to the reset line of the controller. - - - interrupts : two interrupts: - index 0: interrupt connected to the first host - index 1: interrupt connected to the second host - Generic interrupt client node bindings are described in - interrupt-controller/interrupts.txt - -Optional: use of subnodes -------------------------- - -The card connected to a host may need additional properties. These can be -specified in subnodes to the controller node. - -The subnodes are identified by the standard 'reg' property. Which information -exactly can be specified depends on the bindings for the function driver -for the subnode. - -Required controller node properties when using subnodes: -- #address-cells: should be one. -- #size-cells: should be zero. - -Required subnode properties: -- reg: Must contain the host index of the card this subnode describes: - <0> for the first host on the controller - <1> for the second host on the controller - Note that only a single card can be plugged into a host, so the host - index uniquely describes the card location. - -Example of usage: ------------------ - -This example places the bridge on top of the i.MX WEIM parallel bus, see: -Documentation/devicetree/bindings/memory-controllers/fsl/fsl,imx-weim.yaml - -&weim { - controller@0,0 { - compatible = "arcx,anybus-controller"; - reg = <0 0 0x100>, <0 0x400000 0x800>, <1 0x400000 0x800>; - reset-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; - interrupt-parent = <&gpio1>; - interrupts = <1 IRQ_TYPE_LEVEL_LOW>, <5 IRQ_TYPE_LEVEL_LOW>; - /* fsl,weim-cs-timing is a i.MX WEIM bus specific property */ - fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100 - 0x00000000 0xa0000240 0x00000000>; - /* optional subnode for a card plugged into the first host */ - #address-cells = <1>; - #size-cells = <0>; - card@0 { - reg = <0>; - /* card specific properties go here */ - }; - }; -}; diff --git a/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt b/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt deleted file mode 100644 index 89fb8e14676f998224d02aeea7e400285374b6a9..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt +++ /dev/null @@ -1,66 +0,0 @@ - Fieldbus-Device Subsystem - ============================================ - -Part 0 - What is a Fieldbus Device ? ------------------------------------- - -Fieldbus is the name of a family of industrial computer network protocols used -for real-time distributed control, standardized as IEC 61158. - -A complex automated industrial system -- such as manufacturing assembly line -- -usually needs a distributed control system -- an organized hierarchy of -controller systems -- to function. In this hierarchy, there is usually a -Human Machine Interface (HMI) at the top, where an operator can monitor or -operate the system. This is typically linked to a middle layer of programmable -logic controllers (PLC) via a non-time-critical communications system -(e.g. Ethernet). At the bottom of the control chain is the fieldbus that links -the PLCs to the components that actually do the work, such as sensors, -actuators, electric motors, console lights, switches, valves and contactors. - -(Source: Wikipedia) - -A "Fieldbus Device" is such an actuator, motor, console light, switch, ... -controlled via the Fieldbus by a PLC aka "Fieldbus Controller". - -Communication between PLC and device typically happens via process data memory, -separated into input and output areas. The Fieldbus then cyclically transfers -the PLC's output area to the device's input area, and vice versa. - -Part I - Why do we need this subsystem? ---------------------------------------- - -Fieldbus device (client) adapters are commercially available. They allow data -exchange with a PLC aka "Fieldbus Controller" via process data memory. - -They are typically used when a Linux device wants to expose itself as an -actuator, motor, console light, switch, etc. over the fieldbus. - -The purpose of this subsystem is: -a) present a general, standardized, extensible API/ABI to userspace; and -b) present a convenient interface to drivers. - -Part II - How can drivers use the subsystem? --------------------------------------------- - -Any driver that wants to register as a Fieldbus Device should allocate and -populate a 'struct fieldbus_dev' (from include/linux/fieldbus_dev.h). -Registration then happens by calling fieldbus_dev_register(). - -Part III - How can userspace use the subsystem? ------------------------------------------------ - -Fieldbus protocols and adapters are diverse and varied. However, they share -a limited few common behaviours and properties. This allows us to define -a simple interface consisting of a character device and a set of sysfs files: - -See: -drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev -drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev - -Note that this simple interface does not provide a way to modify adapter -configuration settings. It is therefore useful only for adapters that get their -configuration settings some other way, e.g. non-volatile memory on the adapter, -through the network, ... - -At a later phase, this simple interface can easily co-exist with a future -(netlink-based ?) configuration settings interface. diff --git a/drivers/staging/fieldbus/Kconfig b/drivers/staging/fieldbus/Kconfig deleted file mode 100644 index b0b865acccfbc0177780d01fc2a3c6806b3301b1..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menuconfig FIELDBUS_DEV - tristate "Fieldbus Device Support" - help - Support for Fieldbus Device Adapters. - - Fieldbus device (client) adapters allow data exchange with a PLC aka. - "Fieldbus Controller" over a fieldbus (Profinet, FLNet, etc.) - - They are typically used when a Linux device wants to expose itself - as an actuator, motor, console light, switch, etc. over the fieldbus. - - This framework is designed to provide a generic interface to Fieldbus - Devices from both the Linux Kernel and the userspace. - - If unsure, say no. - -source "drivers/staging/fieldbus/anybuss/Kconfig" - diff --git a/drivers/staging/fieldbus/Makefile b/drivers/staging/fieldbus/Makefile deleted file mode 100644 index bdf645d41344d6cccb8c0795a084565b4c70c7f1..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for fieldbus_dev drivers. -# - -obj-$(CONFIG_FIELDBUS_DEV) += fieldbus_dev.o anybuss/ -fieldbus_dev-y := dev_core.o diff --git a/drivers/staging/fieldbus/TODO b/drivers/staging/fieldbus/TODO deleted file mode 100644 index 6d6626af4ec7de4b09620239fc443c50723a2776..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/TODO +++ /dev/null @@ -1,5 +0,0 @@ -TODO: --Get more people/drivers to use the Fieldbus userspace ABI. It requires - verification/sign-off by multiple users. - -Contact: Sven Van Asbroeck <TheSven73@gmail.com> diff --git a/drivers/staging/fieldbus/anybuss/Kconfig b/drivers/staging/fieldbus/anybuss/Kconfig deleted file mode 100644 index 635a0a7b7dd29b66a010a7d767ea946b6ac865ab..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/Kconfig +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config HMS_ANYBUSS_BUS - tristate "HMS Anybus-S Bus Support" - select REGMAP - depends on OF && FIELDBUS_DEV - help - Driver for the HMS Industrial Networks Anybus-S bus. - You can attach a single Anybus-S compatible card to it, which - typically provides fieldbus and industrial ethernet - functionality. - -if HMS_ANYBUSS_BUS - -config ARCX_ANYBUS_CONTROLLER - tristate "Arcx Anybus-S Controller" - depends on OF && GPIOLIB && HAS_IOMEM && REGULATOR - select REGMAP_MMIO - help - Select this to get support for the Arcx Anybus controller. - It connects to the SoC via a parallel memory bus, and - embeds up to two Anybus-S buses (slots). - There is also a CAN power readout, unrelated to the Anybus, - modelled as a regulator. - -config HMS_PROFINET - tristate "HMS Profinet IRT Controller (Anybus-S)" - depends on FIELDBUS_DEV && HMS_ANYBUSS_BUS - help - If you say yes here you get support for the HMS Industrial - Networks Profinet IRT Controller. - - It will be registered with the kernel as a fieldbus_dev, - so userspace can interact with it via the fieldbus_dev userspace - interface(s). - - This driver can also be built as a module. If so, the module - will be called hms-profinet. - - If unsure, say N. - -endif diff --git a/drivers/staging/fieldbus/anybuss/Makefile b/drivers/staging/fieldbus/anybuss/Makefile deleted file mode 100644 index 3ad3dcc6be56bd68a4624237cd4b739e1c630640..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for anybuss drivers. -# - -obj-$(CONFIG_HMS_ANYBUSS_BUS) += anybuss_core.o -anybuss_core-y += host.o - -obj-$(CONFIG_ARCX_ANYBUS_CONTROLLER) += arcx-anybus.o -obj-$(CONFIG_HMS_PROFINET) += hms-profinet.o diff --git a/drivers/staging/fieldbus/anybuss/anybuss-client.h b/drivers/staging/fieldbus/anybuss/anybuss-client.h deleted file mode 100644 index c21c4bebfb845763d9f12eb4ad8a8311197fcf33..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/anybuss-client.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Anybus-S client adapter definitions - * - * Copyright 2018 Arcx Inc - */ - -#ifndef __LINUX_ANYBUSS_CLIENT_H__ -#define __LINUX_ANYBUSS_CLIENT_H__ - -#include <linux/device.h> -#include <linux/types.h> -#include <linux/poll.h> - -/* move to <linux/fieldbus_dev.h> when taking this out of staging */ -#include "../fieldbus_dev.h" - -struct anybuss_host; - -struct anybuss_client { - struct device dev; - struct anybuss_host *host; - __be16 anybus_id; - /* - * these can be optionally set by the client to receive event - * notifications from the host. - */ - void (*on_area_updated)(struct anybuss_client *client); - void (*on_online_changed)(struct anybuss_client *client, bool online); -}; - -struct anybuss_client_driver { - struct device_driver driver; - int (*probe)(struct anybuss_client *adev); - void (*remove)(struct anybuss_client *adev); - u16 anybus_id; -}; - -int anybuss_client_driver_register(struct anybuss_client_driver *drv); -void anybuss_client_driver_unregister(struct anybuss_client_driver *drv); - -static inline struct anybuss_client *to_anybuss_client(struct device *dev) -{ - return container_of(dev, struct anybuss_client, dev); -} - -#define to_anybuss_client_driver(__drv) container_of_const(__drv, struct anybuss_client_driver, driver) - -static inline void * -anybuss_get_drvdata(const struct anybuss_client *client) -{ - return dev_get_drvdata(&client->dev); -} - -static inline void -anybuss_set_drvdata(struct anybuss_client *client, void *data) -{ - dev_set_drvdata(&client->dev, data); -} - -int anybuss_set_power(struct anybuss_client *client, bool power_on); - -struct anybuss_memcfg { - u16 input_io; - u16 input_dpram; - u16 input_total; - - u16 output_io; - u16 output_dpram; - u16 output_total; - - enum fieldbus_dev_offl_mode offl_mode; -}; - -int anybuss_start_init(struct anybuss_client *client, - const struct anybuss_memcfg *cfg); -int anybuss_finish_init(struct anybuss_client *client); -int anybuss_read_fbctrl(struct anybuss_client *client, u16 addr, - void *buf, size_t count); -int anybuss_send_msg(struct anybuss_client *client, u16 cmd_num, - const void *buf, size_t count); -int anybuss_send_ext(struct anybuss_client *client, u16 cmd_num, - const void *buf, size_t count); -int anybuss_recv_msg(struct anybuss_client *client, u16 cmd_num, - void *buf, size_t count); - -/* these help clients make a struct file_operations */ -int anybuss_write_input(struct anybuss_client *client, - const char __user *buf, size_t size, - loff_t *offset); -int anybuss_read_output(struct anybuss_client *client, - char __user *buf, size_t size, - loff_t *offset); - -#endif /* __LINUX_ANYBUSS_CLIENT_H__ */ diff --git a/drivers/staging/fieldbus/anybuss/anybuss-controller.h b/drivers/staging/fieldbus/anybuss/anybuss-controller.h deleted file mode 100644 index 02fa0749043bd91270107d196488d690284b8f00..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/anybuss-controller.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Anybus-S controller definitions - * - * Copyright 2018 Arcx Inc - */ - -#ifndef __LINUX_ANYBUSS_CONTROLLER_H__ -#define __LINUX_ANYBUSS_CONTROLLER_H__ - -#include <linux/device.h> -#include <linux/regmap.h> - -/* - * To instantiate an Anybus-S host, a controller should provide the following: - * - a reset function which resets the attached card; - * - a regmap which provides access to the attached card's dpram; - * - the irq of the attached card - */ -/** - * struct anybuss_ops - Controller resources to instantiate an Anybus-S host - * - * @reset: asserts/deasserts the anybus card's reset line. - * @regmap: provides access to the card's dual-port RAM area. - * @irq: number of the interrupt connected to the card's interrupt line. - * @host_idx: for multi-host controllers, the host index: - * 0 for the first host on the controller, 1 for the second, etc. - */ -struct anybuss_ops { - void (*reset)(struct device *dev, bool assert); - struct regmap *regmap; - int irq; - int host_idx; -}; - -struct anybuss_host; - -struct anybuss_host * __must_check -anybuss_host_common_probe(struct device *dev, - const struct anybuss_ops *ops); -void anybuss_host_common_remove(struct anybuss_host *host); - -struct anybuss_host * __must_check -devm_anybuss_host_common_probe(struct device *dev, - const struct anybuss_ops *ops); - -#endif /* __LINUX_ANYBUSS_CONTROLLER_H__ */ diff --git a/drivers/staging/fieldbus/anybuss/arcx-anybus.c b/drivers/staging/fieldbus/anybuss/arcx-anybus.c deleted file mode 100644 index fcd3e3722ae017f7714e7bac786e48b48eb2b33c..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/arcx-anybus.c +++ /dev/null @@ -1,379 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Arcx Anybus-S Controller driver - * - * Copyright (C) 2018 Arcx Inc - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/gpio/consumer.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/delay.h> -#include <linux/idr.h> -#include <linux/mutex.h> -#include <linux/regulator/driver.h> -#include <linux/regulator/machine.h> -#include <linux/regmap.h> - -/* move to <linux/anybuss-controller.h> when taking this out of staging */ -#include "anybuss-controller.h" - -#define CPLD_STATUS1 0x80 -#define CPLD_CONTROL 0x80 -#define CPLD_CONTROL_CRST 0x40 -#define CPLD_CONTROL_RST1 0x04 -#define CPLD_CONTROL_RST2 0x80 -#define CPLD_STATUS1_AB 0x02 -#define CPLD_STATUS1_CAN_POWER 0x01 -#define CPLD_DESIGN_LO 0x81 -#define CPLD_DESIGN_HI 0x82 -#define CPLD_CAP 0x83 -#define CPLD_CAP_COMPAT 0x01 -#define CPLD_CAP_SEP_RESETS 0x02 - -struct controller_priv { - struct device *class_dev; - bool common_reset; - struct gpio_desc *reset_gpiod; - void __iomem *cpld_base; - struct mutex ctrl_lock; /* protects CONTROL register */ - u8 control_reg; - char version[3]; - u16 design_no; -}; - -static void do_reset(struct controller_priv *cd, u8 rst_bit, bool reset) -{ - mutex_lock(&cd->ctrl_lock); - /* - * CPLD_CONTROL is write-only, so cache its value in - * cd->control_reg - */ - if (reset) - cd->control_reg &= ~rst_bit; - else - cd->control_reg |= rst_bit; - writeb(cd->control_reg, cd->cpld_base + CPLD_CONTROL); - /* - * h/w work-around: - * the hardware is 'too fast', so a reset followed by an immediate - * not-reset will _not_ change the anybus reset line in any way, - * losing the reset. to prevent this from happening, introduce - * a minimum reset duration. - * Verified minimum safe duration required using a scope - * on 14-June-2018: 100 us. - */ - if (reset) - usleep_range(100, 200); - mutex_unlock(&cd->ctrl_lock); -} - -static int anybuss_reset(struct controller_priv *cd, - unsigned long id, bool reset) -{ - if (id >= 2) - return -EINVAL; - if (cd->common_reset) - do_reset(cd, CPLD_CONTROL_CRST, reset); - else - do_reset(cd, id ? CPLD_CONTROL_RST2 : CPLD_CONTROL_RST1, reset); - return 0; -} - -static void export_reset_0(struct device *dev, bool assert) -{ - struct controller_priv *cd = dev_get_drvdata(dev); - - anybuss_reset(cd, 0, assert); -} - -static void export_reset_1(struct device *dev, bool assert) -{ - struct controller_priv *cd = dev_get_drvdata(dev); - - anybuss_reset(cd, 1, assert); -} - -/* - * parallel bus limitation: - * - * the anybus is 8-bit wide. we can't assume that the hardware will translate - * word accesses on the parallel bus to multiple byte-accesses on the anybus. - * - * the imx WEIM bus does not provide this type of translation. - * - * to be safe, we will limit parallel bus accesses to a single byte - * at a time for now. - */ - -static const struct regmap_config arcx_regmap_cfg = { - .reg_bits = 16, - .val_bits = 8, - .max_register = 0x7ff, - .use_single_read = true, - .use_single_write = true, - /* - * single-byte parallel bus accesses are atomic, so don't - * require any synchronization. - */ - .disable_locking = true, -}; - -static struct regmap *create_parallel_regmap(struct platform_device *pdev, - int idx) -{ - void __iomem *base; - struct device *dev = &pdev->dev; - - base = devm_platform_ioremap_resource(pdev, idx + 1); - if (IS_ERR(base)) - return ERR_CAST(base); - return devm_regmap_init_mmio(dev, base, &arcx_regmap_cfg); -} - -static struct anybuss_host * -create_anybus_host(struct platform_device *pdev, int idx) -{ - struct anybuss_ops ops = {}; - - switch (idx) { - case 0: - ops.reset = export_reset_0; - break; - case 1: - ops.reset = export_reset_1; - break; - default: - return ERR_PTR(-EINVAL); - } - ops.host_idx = idx; - ops.regmap = create_parallel_regmap(pdev, idx); - if (IS_ERR(ops.regmap)) - return ERR_CAST(ops.regmap); - ops.irq = platform_get_irq(pdev, idx); - if (ops.irq < 0) - return ERR_PTR(ops.irq); - return devm_anybuss_host_common_probe(&pdev->dev, &ops); -} - -static ssize_t version_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct controller_priv *cd = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", cd->version); -} -static DEVICE_ATTR_RO(version); - -static ssize_t design_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct controller_priv *cd = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", cd->design_no); -} -static DEVICE_ATTR_RO(design_number); - -static struct attribute *controller_attributes[] = { - &dev_attr_version.attr, - &dev_attr_design_number.attr, - NULL, -}; - -static const struct attribute_group controller_attribute_group = { - .attrs = controller_attributes, -}; - -static const struct attribute_group *controller_attribute_groups[] = { - &controller_attribute_group, - NULL, -}; - -static void controller_device_release(struct device *dev) -{ - kfree(dev); -} - -static int can_power_is_enabled(struct regulator_dev *rdev) -{ - struct controller_priv *cd = rdev_get_drvdata(rdev); - - return !(readb(cd->cpld_base + CPLD_STATUS1) & CPLD_STATUS1_CAN_POWER); -} - -static const struct regulator_ops can_power_ops = { - .is_enabled = can_power_is_enabled, -}; - -static const struct regulator_desc can_power_desc = { - .name = "regulator-can-power", - .id = -1, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - .ops = &can_power_ops, -}; - -static const struct class controller_class = { - .name = "arcx_anybus_controller", -}; - -static DEFINE_IDA(controller_index_ida); - -static int controller_probe(struct platform_device *pdev) -{ - struct controller_priv *cd; - struct device *dev = &pdev->dev; - struct regulator_config config = { }; - struct regulator_dev *regulator; - int err, id; - struct anybuss_host *host; - u8 status1, cap; - - cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL); - if (!cd) - return -ENOMEM; - dev_set_drvdata(dev, cd); - mutex_init(&cd->ctrl_lock); - cd->reset_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(cd->reset_gpiod)) - return PTR_ERR(cd->reset_gpiod); - - /* CPLD control memory, sits at index 0 */ - cd->cpld_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(cd->cpld_base)) { - dev_err(dev, - "failed to map cpld base address\n"); - err = PTR_ERR(cd->cpld_base); - goto out_reset; - } - - /* identify cpld */ - status1 = readb(cd->cpld_base + CPLD_STATUS1); - cd->design_no = (readb(cd->cpld_base + CPLD_DESIGN_HI) << 8) | - readb(cd->cpld_base + CPLD_DESIGN_LO); - snprintf(cd->version, sizeof(cd->version), "%c%d", - 'A' + ((status1 >> 5) & 0x7), - (status1 >> 2) & 0x7); - dev_info(dev, "design number %d, revision %s\n", - cd->design_no, - cd->version); - cap = readb(cd->cpld_base + CPLD_CAP); - if (!(cap & CPLD_CAP_COMPAT)) { - dev_err(dev, "unsupported controller [cap=0x%02X]", cap); - err = -ENODEV; - goto out_reset; - } - - if (status1 & CPLD_STATUS1_AB) { - dev_info(dev, "has anybus-S slot(s)"); - cd->common_reset = !(cap & CPLD_CAP_SEP_RESETS); - dev_info(dev, "supports %s", cd->common_reset ? - "a common reset" : "separate resets"); - for (id = 0; id < 2; id++) { - host = create_anybus_host(pdev, id); - if (!IS_ERR(host)) - continue; - err = PTR_ERR(host); - /* -ENODEV is fine, it just means no card detected */ - if (err != -ENODEV) - goto out_reset; - } - } - - id = ida_alloc(&controller_index_ida, GFP_KERNEL); - if (id < 0) { - err = id; - goto out_reset; - } - /* export can power readout as a regulator */ - config.dev = dev; - config.driver_data = cd; - regulator = devm_regulator_register(dev, &can_power_desc, &config); - if (IS_ERR(regulator)) { - err = PTR_ERR(regulator); - goto out_ida; - } - /* make controller info visible to userspace */ - cd->class_dev = kzalloc(sizeof(*cd->class_dev), GFP_KERNEL); - if (!cd->class_dev) { - err = -ENOMEM; - goto out_ida; - } - cd->class_dev->class = &controller_class; - cd->class_dev->groups = controller_attribute_groups; - cd->class_dev->parent = dev; - cd->class_dev->id = id; - cd->class_dev->release = controller_device_release; - dev_set_name(cd->class_dev, "%d", cd->class_dev->id); - dev_set_drvdata(cd->class_dev, cd); - err = device_register(cd->class_dev); - if (err) - goto out_dev; - return 0; -out_dev: - put_device(cd->class_dev); -out_ida: - ida_free(&controller_index_ida, id); -out_reset: - gpiod_set_value_cansleep(cd->reset_gpiod, 1); - return err; -} - -static void controller_remove(struct platform_device *pdev) -{ - struct controller_priv *cd = platform_get_drvdata(pdev); - int id = cd->class_dev->id; - - device_unregister(cd->class_dev); - ida_free(&controller_index_ida, id); - gpiod_set_value_cansleep(cd->reset_gpiod, 1); -} - -static const struct of_device_id controller_of_match[] = { - { .compatible = "arcx,anybus-controller" }, - { } -}; - -MODULE_DEVICE_TABLE(of, controller_of_match); - -static struct platform_driver controller_driver = { - .probe = controller_probe, - .remove_new = controller_remove, - .driver = { - .name = "arcx-anybus-controller", - .of_match_table = controller_of_match, - }, -}; - -static int __init controller_init(void) -{ - int err; - - err = class_register(&controller_class); - if (err) - return err; - err = platform_driver_register(&controller_driver); - if (err) - class_unregister(&controller_class); - - return err; -} - -static void __exit controller_exit(void) -{ - platform_driver_unregister(&controller_driver); - class_unregister(&controller_class); - ida_destroy(&controller_index_ida); -} - -module_init(controller_init); -module_exit(controller_exit); - -MODULE_DESCRIPTION("Arcx Anybus-S Controller driver"); -MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/fieldbus/anybuss/hms-profinet.c b/drivers/staging/fieldbus/anybuss/hms-profinet.c deleted file mode 100644 index e691736a53f178349db87b64dcca476a55f97a3f..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/hms-profinet.c +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * HMS Profinet Client Driver - * - * Copyright (C) 2018 Arcx Inc - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> - -/* move to <linux/fieldbus_dev.h> when taking this out of staging */ -#include "../fieldbus_dev.h" - -/* move to <linux/anybuss-client.h> when taking this out of staging */ -#include "anybuss-client.h" - -#define PROFI_DPRAM_SIZE 512 - -/* - * --------------------------------------------------------------- - * Anybus Profinet mailbox messages - definitions - * --------------------------------------------------------------- - * note that we're depending on the layout of these structures being - * exactly as advertised. - */ - -struct msg_mac_addr { - u8 addr[6]; -}; - -struct profi_priv { - struct fieldbus_dev fbdev; - struct anybuss_client *client; - struct mutex enable_lock; /* serializes card enable */ - bool power_on; -}; - -static ssize_t -profi_read_area(struct fieldbus_dev *fbdev, char __user *buf, size_t size, - loff_t *offset) -{ - struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev); - - return anybuss_read_output(priv->client, buf, size, offset); -} - -static ssize_t -profi_write_area(struct fieldbus_dev *fbdev, const char __user *buf, - size_t size, loff_t *offset) -{ - struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev); - - return anybuss_write_input(priv->client, buf, size, offset); -} - -static int profi_id_get(struct fieldbus_dev *fbdev, char *buf, - size_t max_size) -{ - struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev); - struct msg_mac_addr response; - int ret; - - ret = anybuss_recv_msg(priv->client, 0x0010, &response, - sizeof(response)); - if (ret < 0) - return ret; - return snprintf(buf, max_size, "%pM\n", response.addr); -} - -static bool profi_enable_get(struct fieldbus_dev *fbdev) -{ - struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev); - bool power_on; - - mutex_lock(&priv->enable_lock); - power_on = priv->power_on; - mutex_unlock(&priv->enable_lock); - - return power_on; -} - -static int __profi_enable(struct profi_priv *priv) -{ - int ret; - struct anybuss_client *client = priv->client; - /* Initialization Sequence, Generic Anybus Mode */ - const struct anybuss_memcfg mem_cfg = { - .input_io = 220, - .input_dpram = PROFI_DPRAM_SIZE, - .input_total = PROFI_DPRAM_SIZE, - .output_io = 220, - .output_dpram = PROFI_DPRAM_SIZE, - .output_total = PROFI_DPRAM_SIZE, - .offl_mode = FIELDBUS_DEV_OFFL_MODE_CLEAR, - }; - - /* - * switch anybus off then on, this ensures we can do a complete - * configuration cycle in case anybus was already on. - */ - anybuss_set_power(client, false); - ret = anybuss_set_power(client, true); - if (ret) - goto err; - ret = anybuss_start_init(client, &mem_cfg); - if (ret) - goto err; - ret = anybuss_finish_init(client); - if (ret) - goto err; - priv->power_on = true; - return 0; - -err: - anybuss_set_power(client, false); - priv->power_on = false; - return ret; -} - -static int __profi_disable(struct profi_priv *priv) -{ - struct anybuss_client *client = priv->client; - - anybuss_set_power(client, false); - priv->power_on = false; - return 0; -} - -static int profi_simple_enable(struct fieldbus_dev *fbdev, bool enable) -{ - int ret; - struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev); - - mutex_lock(&priv->enable_lock); - if (enable) - ret = __profi_enable(priv); - else - ret = __profi_disable(priv); - mutex_unlock(&priv->enable_lock); - - return ret; -} - -static void profi_on_area_updated(struct anybuss_client *client) -{ - struct profi_priv *priv = anybuss_get_drvdata(client); - - fieldbus_dev_area_updated(&priv->fbdev); -} - -static void profi_on_online_changed(struct anybuss_client *client, bool online) -{ - struct profi_priv *priv = anybuss_get_drvdata(client); - - fieldbus_dev_online_changed(&priv->fbdev, online); -} - -static int profinet_probe(struct anybuss_client *client) -{ - struct profi_priv *priv; - struct device *dev = &client->dev; - int err; - - client->on_area_updated = profi_on_area_updated; - client->on_online_changed = profi_on_online_changed; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - mutex_init(&priv->enable_lock); - priv->client = client; - priv->fbdev.read_area_sz = PROFI_DPRAM_SIZE; - priv->fbdev.write_area_sz = PROFI_DPRAM_SIZE; - priv->fbdev.card_name = "HMS Profinet IRT (Anybus-S)"; - priv->fbdev.fieldbus_type = FIELDBUS_DEV_TYPE_PROFINET; - priv->fbdev.read_area = profi_read_area; - priv->fbdev.write_area = profi_write_area; - priv->fbdev.fieldbus_id_get = profi_id_get; - priv->fbdev.enable_get = profi_enable_get; - priv->fbdev.simple_enable_set = profi_simple_enable; - priv->fbdev.parent = dev; - err = fieldbus_dev_register(&priv->fbdev); - if (err < 0) - return err; - dev_info(dev, "card detected, registered as %s", - dev_name(priv->fbdev.dev)); - anybuss_set_drvdata(client, priv); - - return 0; -} - -static void profinet_remove(struct anybuss_client *client) -{ - struct profi_priv *priv = anybuss_get_drvdata(client); - - fieldbus_dev_unregister(&priv->fbdev); -} - -static struct anybuss_client_driver profinet_driver = { - .probe = profinet_probe, - .remove = profinet_remove, - .driver = { - .name = "hms-profinet", - .owner = THIS_MODULE, - }, - .anybus_id = 0x0089, -}; - -static int __init profinet_init(void) -{ - return anybuss_client_driver_register(&profinet_driver); -} -module_init(profinet_init); - -static void __exit profinet_exit(void) -{ - return anybuss_client_driver_unregister(&profinet_driver); -} -module_exit(profinet_exit); - -MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>"); -MODULE_DESCRIPTION("HMS Profinet IRT Driver (Anybus-S)"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c deleted file mode 100644 index 4f2b2fce92eec44f34620a344eb2d3165334cd65..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/anybuss/host.c +++ /dev/null @@ -1,1452 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * HMS Anybus-S Host Driver - * - * Copyright (C) 2018 Arcx Inc - */ - -/* - * Architecture Overview - * ===================== - * This driver (running on the CPU/SoC) and the Anybus-S card communicate - * by reading and writing data to/from the Anybus-S Dual-Port RAM (dpram). - * This is memory connected to both the SoC and Anybus-S card, which both sides - * can access freely and concurrently. - * - * Synchronization happens by means of two registers located in the dpram: - * IND_AB: written exclusively by the Anybus card; and - * IND_AP: written exclusively by this driver. - * - * Communication happens using one of the following mechanisms: - * 1. reserve, read/write, release dpram memory areas: - * using an IND_AB/IND_AP protocol, the driver is able to reserve certain - * memory areas. no dpram memory can be read or written except if reserved. - * (with a few limited exceptions) - * 2. send and receive data structures via a shared mailbox: - * using an IND_AB/IND_AP protocol, the driver and Anybus card are able to - * exchange commands and responses using a shared mailbox. - * 3. receive software interrupts: - * using an IND_AB/IND_AP protocol, the Anybus card is able to notify the - * driver of certain events such as: bus online/offline, data available. - * note that software interrupt event bits are located in a memory area - * which must be reserved before it can be accessed. - * - * The manual[1] is silent on whether these mechanisms can happen concurrently, - * or how they should be synchronized. However, section 13 (Driver Example) - * provides the following suggestion for developing a driver: - * a) an interrupt handler which updates global variables; - * b) a continuously-running task handling area requests (1 above) - * c) a continuously-running task handling mailbox requests (2 above) - * The example conspicuously leaves out software interrupts (3 above), which - * is the thorniest issue to get right (see below). - * - * The naive, straightforward way to implement this would be: - * - create an isr which updates shared variables; - * - create a work_struct which handles software interrupts on a queue; - * - create a function which does reserve/update/unlock in a loop; - * - create a function which does mailbox send/receive in a loop; - * - call the above functions from the driver's read/write/ioctl; - * - synchronize using mutexes/spinlocks: - * + only one area request at a time - * + only one mailbox request at a time - * + protect AB_IND, AB_IND against data hazards (e.g. read-after-write) - * - * Unfortunately, the presence of the software interrupt causes subtle yet - * considerable synchronization issues; especially problematic is the - * requirement to reserve/release the area which contains the status bits. - * - * The driver architecture presented here sidesteps these synchronization issues - * by accessing the dpram from a single kernel thread only. User-space throws - * "tasks" (i.e. 1, 2 above) into a task queue, waits for their completion, - * and the kernel thread runs them to completion. - * - * Each task has a task_function, which is called/run by the queue thread. - * That function communicates with the Anybus card, and returns either - * 0 (OK), a negative error code (error), or -EINPROGRESS (waiting). - * On OK or error, the queue thread completes and dequeues the task, - * which also releases the user space thread which may still be waiting for it. - * On -EINPROGRESS (waiting), the queue thread will leave the task on the queue, - * and revisit (call again) whenever an interrupt event comes in. - * - * Each task has a state machine, which is run by calling its task_function. - * It ensures that the task will go through its various stages over time, - * returning -EINPROGRESS if it wants to wait for an event to happen. - * - * Note that according to the manual's driver example, the following operations - * may run independent of each other: - * - area reserve/read/write/release (point 1 above) - * - mailbox operations (point 2 above) - * - switching power on/off - * - * To allow them to run independently, each operation class gets its own queue. - * - * Userspace processes A, B, C, D post tasks to the appropriate queue, - * and wait for task completion: - * - * process A B C D - * | | | | - * v v v v - * |<----- ======================================== - * | | | | - * | v v v-------<-------+ - * | +--------------------------------------+ | - * | | power q | mbox q | area q | | - * | |------------|------------|------------| | - * | | task | task | task | | - * | | task | task | task | | - * | | task wait | task wait | task wait | | - * | +--------------------------------------+ | - * | ^ ^ ^ | - * | | | | ^ - * | +--------------------------------------+ | - * | | queue thread | | - * | |--------------------------------------| | - * | | single-threaded: | | - * | | loop: | | - * v | for each queue: | | - * | | run task state machine | | - * | | if task waiting: | | - * | | leave on queue | | - * | | if task done: | | - * | | complete task, remove from q | | - * | | if software irq event bits set: | | - * | | notify userspace | | - * | | post clear event bits task------>|>-------+ - * | | wait for IND_AB changed event OR | - * | | task added event OR | - * | | timeout | - * | | end loop | - * | +--------------------------------------+ - * | + wake up + - * | +--------------------------------------+ - * | ^ ^ - * | | | - * +-------->------- | - * | - * +--------------------------------------+ - * | interrupt service routine | - * |--------------------------------------| - * | wake up queue thread on IND_AB change| - * +--------------------------------------+ - * - * Note that the Anybus interrupt is dual-purpose: - * - after a reset, triggered when the card becomes ready; - * - during normal operation, triggered when AB_IND changes. - * This is why the interrupt service routine doesn't just wake up the - * queue thread, but also completes the card_boot completion. - * - * [1] https://www.anybus.com/docs/librariesprovider7/default-document-library/ - * manuals-design-guides/hms-hmsi-27-275.pdf - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/atomic.h> -#include <linux/kthread.h> -#include <linux/kfifo.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> -#include <linux/regmap.h> -#include <linux/of.h> -#include <linux/random.h> -#include <linux/kref.h> -#include <linux/of_address.h> - -/* move to <linux/anybuss-*.h> when taking this out of staging */ -#include "anybuss-client.h" -#include "anybuss-controller.h" - -#define DPRAM_SIZE 0x800 -#define MAX_MBOX_MSG_SZ 0x0FF -#define TIMEOUT (HZ * 2) -#define MAX_DATA_AREA_SZ 0x200 -#define MAX_FBCTRL_AREA_SZ 0x1BE - -#define REG_BOOTLOADER_V 0x7C0 -#define REG_API_V 0x7C2 -#define REG_FIELDBUS_V 0x7C4 -#define REG_SERIAL_NO 0x7C6 -#define REG_FIELDBUS_TYPE 0x7CC -#define REG_MODULE_SW_V 0x7CE -#define REG_IND_AB 0x7FF -#define REG_IND_AP 0x7FE -#define REG_EVENT_CAUSE 0x7ED -#define MBOX_IN_AREA 0x400 -#define MBOX_OUT_AREA 0x520 -#define DATA_IN_AREA 0x000 -#define DATA_OUT_AREA 0x200 -#define FBCTRL_AREA 0x640 - -#define EVENT_CAUSE_DC 0x01 -#define EVENT_CAUSE_FBOF 0x02 -#define EVENT_CAUSE_FBON 0x04 - -#define IND_AB_UPDATED 0x08 -#define IND_AX_MIN 0x80 -#define IND_AX_MOUT 0x40 -#define IND_AX_IN 0x04 -#define IND_AX_OUT 0x02 -#define IND_AX_FBCTRL 0x01 -#define IND_AP_LOCK 0x08 -#define IND_AP_ACTION 0x10 -#define IND_AX_EVNT 0x20 -#define IND_AP_ABITS (IND_AX_IN | IND_AX_OUT | \ - IND_AX_FBCTRL | \ - IND_AP_ACTION | IND_AP_LOCK) - -#define INFO_TYPE_FB 0x0002 -#define INFO_TYPE_APP 0x0001 -#define INFO_COMMAND 0x4000 - -#define OP_MODE_FBFC 0x0002 -#define OP_MODE_FBS 0x0004 -#define OP_MODE_CD 0x0200 - -#define CMD_START_INIT 0x0001 -#define CMD_ANYBUS_INIT 0x0002 -#define CMD_END_INIT 0x0003 - -/* - * --------------------------------------------------------------- - * Anybus mailbox messages - definitions - * --------------------------------------------------------------- - * note that we're depending on the layout of these structures being - * exactly as advertised. - */ - -struct anybus_mbox_hdr { - __be16 id; - __be16 info; - __be16 cmd_num; - __be16 data_size; - __be16 frame_count; - __be16 frame_num; - __be16 offset_high; - __be16 offset_low; - __be16 extended[8]; -}; - -struct msg_anybus_init { - __be16 input_io_len; - __be16 input_dpram_len; - __be16 input_total_len; - __be16 output_io_len; - __be16 output_dpram_len; - __be16 output_total_len; - __be16 op_mode; - __be16 notif_config; - __be16 wd_val; -}; - -/* ------------- ref counted tasks ------------- */ - -struct ab_task; -typedef int (*ab_task_fn_t)(struct anybuss_host *cd, - struct ab_task *t); -typedef void (*ab_done_fn_t)(struct anybuss_host *cd); - -struct area_priv { - bool is_write; - u16 flags; - u16 addr; - size_t count; - u8 buf[MAX_DATA_AREA_SZ]; -}; - -struct mbox_priv { - struct anybus_mbox_hdr hdr; - size_t msg_out_sz; - size_t msg_in_sz; - u8 msg[MAX_MBOX_MSG_SZ]; -}; - -struct ab_task { - struct kmem_cache *cache; - struct kref refcount; - ab_task_fn_t task_fn; - ab_done_fn_t done_fn; - int result; - struct completion done; - unsigned long start_jiffies; - union { - struct area_priv area_pd; - struct mbox_priv mbox_pd; - }; -}; - -static struct ab_task *ab_task_create_get(struct kmem_cache *cache, - ab_task_fn_t task_fn) -{ - struct ab_task *t; - - t = kmem_cache_alloc(cache, GFP_KERNEL); - if (!t) - return NULL; - t->cache = cache; - kref_init(&t->refcount); - t->task_fn = task_fn; - t->done_fn = NULL; - t->result = 0; - init_completion(&t->done); - return t; -} - -static void __ab_task_destroy(struct kref *refcount) -{ - struct ab_task *t = container_of(refcount, struct ab_task, refcount); - struct kmem_cache *cache = t->cache; - - kmem_cache_free(cache, t); -} - -static void ab_task_put(struct ab_task *t) -{ - kref_put(&t->refcount, __ab_task_destroy); -} - -static struct ab_task *__ab_task_get(struct ab_task *t) -{ - kref_get(&t->refcount); - return t; -} - -static void __ab_task_finish(struct ab_task *t, struct anybuss_host *cd) -{ - if (t->done_fn) - t->done_fn(cd); - complete(&t->done); -} - -static void -ab_task_dequeue_finish_put(struct kfifo *q, struct anybuss_host *cd) -{ - int ret; - struct ab_task *t; - - ret = kfifo_out(q, &t, sizeof(t)); - WARN_ON(!ret); - __ab_task_finish(t, cd); - ab_task_put(t); -} - -static int -ab_task_enqueue(struct ab_task *t, struct kfifo *q, spinlock_t *slock, - wait_queue_head_t *wq) -{ - int ret; - - t->start_jiffies = jiffies; - __ab_task_get(t); - ret = kfifo_in_spinlocked(q, &t, sizeof(t), slock); - if (!ret) { - ab_task_put(t); - return -ENOMEM; - } - wake_up(wq); - return 0; -} - -static int -ab_task_enqueue_wait(struct ab_task *t, struct kfifo *q, spinlock_t *slock, - wait_queue_head_t *wq) -{ - int ret; - - ret = ab_task_enqueue(t, q, slock, wq); - if (ret) - return ret; - ret = wait_for_completion_interruptible(&t->done); - if (ret) - return ret; - return t->result; -} - -/* ------------------------ anybus hardware ------------------------ */ - -struct anybuss_host { - struct device *dev; - struct anybuss_client *client; - void (*reset)(struct device *dev, bool assert); - struct regmap *regmap; - int irq; - int host_idx; - struct task_struct *qthread; - wait_queue_head_t wq; - struct completion card_boot; - atomic_t ind_ab; - spinlock_t qlock; /* protects IN side of powerq, mboxq, areaq */ - struct kmem_cache *qcache; - struct kfifo qs[3]; - struct kfifo *powerq; - struct kfifo *mboxq; - struct kfifo *areaq; - bool power_on; - bool softint_pending; -}; - -static void reset_assert(struct anybuss_host *cd) -{ - cd->reset(cd->dev, true); -} - -static void reset_deassert(struct anybuss_host *cd) -{ - cd->reset(cd->dev, false); -} - -static int test_dpram(struct regmap *regmap) -{ - int i; - unsigned int val; - - for (i = 0; i < DPRAM_SIZE; i++) - regmap_write(regmap, i, (u8)i); - for (i = 0; i < DPRAM_SIZE; i++) { - regmap_read(regmap, i, &val); - if ((u8)val != (u8)i) - return -EIO; - } - return 0; -} - -static int read_ind_ab(struct regmap *regmap) -{ - unsigned long timeout = jiffies + HZ / 2; - unsigned int a, b, i = 0; - - while (time_before_eq(jiffies, timeout)) { - regmap_read(regmap, REG_IND_AB, &a); - regmap_read(regmap, REG_IND_AB, &b); - if (likely(a == b)) - return (int)a; - if (i < 10) { - cpu_relax(); - i++; - } else { - usleep_range(500, 1000); - } - } - WARN(1, "IND_AB register not stable"); - return -ETIMEDOUT; -} - -static int write_ind_ap(struct regmap *regmap, unsigned int ind_ap) -{ - unsigned long timeout = jiffies + HZ / 2; - unsigned int v, i = 0; - - while (time_before_eq(jiffies, timeout)) { - regmap_write(regmap, REG_IND_AP, ind_ap); - regmap_read(regmap, REG_IND_AP, &v); - if (likely(ind_ap == v)) - return 0; - if (i < 10) { - cpu_relax(); - i++; - } else { - usleep_range(500, 1000); - } - } - WARN(1, "IND_AP register not stable"); - return -ETIMEDOUT; -} - -static irqreturn_t irq_handler(int irq, void *data) -{ - struct anybuss_host *cd = data; - int ind_ab; - - /* - * irq handler needs exclusive access to the IND_AB register, - * because the act of reading the register acks the interrupt. - * - * store the register value in cd->ind_ab (an atomic_t), so that the - * queue thread is able to read it without causing an interrupt ack - * side-effect (and without spuriously acking an interrupt). - */ - ind_ab = read_ind_ab(cd->regmap); - if (ind_ab < 0) - return IRQ_NONE; - atomic_set(&cd->ind_ab, ind_ab); - complete(&cd->card_boot); - wake_up(&cd->wq); - return IRQ_HANDLED; -} - -/* ------------------------ power on/off tasks --------------------- */ - -static int task_fn_power_off(struct anybuss_host *cd, - struct ab_task *t) -{ - struct anybuss_client *client = cd->client; - - if (!cd->power_on) - return 0; - disable_irq(cd->irq); - reset_assert(cd); - atomic_set(&cd->ind_ab, IND_AB_UPDATED); - if (client->on_online_changed) - client->on_online_changed(client, false); - cd->power_on = false; - return 0; -} - -static int task_fn_power_on_2(struct anybuss_host *cd, - struct ab_task *t) -{ - if (completion_done(&cd->card_boot)) { - cd->power_on = true; - return 0; - } - if (time_after(jiffies, t->start_jiffies + TIMEOUT)) { - disable_irq(cd->irq); - reset_assert(cd); - dev_err(cd->dev, "power on timed out"); - return -ETIMEDOUT; - } - return -EINPROGRESS; -} - -static int task_fn_power_on(struct anybuss_host *cd, - struct ab_task *t) -{ - unsigned int dummy; - - if (cd->power_on) - return 0; - /* - * anybus docs: prevent false 'init done' interrupt by - * doing a dummy read of IND_AB register while in reset. - */ - regmap_read(cd->regmap, REG_IND_AB, &dummy); - reinit_completion(&cd->card_boot); - enable_irq(cd->irq); - reset_deassert(cd); - t->task_fn = task_fn_power_on_2; - return -EINPROGRESS; -} - -int anybuss_set_power(struct anybuss_client *client, bool power_on) -{ - struct anybuss_host *cd = client->host; - struct ab_task *t; - int err; - - t = ab_task_create_get(cd->qcache, power_on ? - task_fn_power_on : task_fn_power_off); - if (!t) - return -ENOMEM; - err = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq); - ab_task_put(t); - return err; -} -EXPORT_SYMBOL_GPL(anybuss_set_power); - -/* ---------------------------- area tasks ------------------------ */ - -static int task_fn_area_3(struct anybuss_host *cd, struct ab_task *t) -{ - struct area_priv *pd = &t->area_pd; - - if (!cd->power_on) - return -EIO; - if (atomic_read(&cd->ind_ab) & pd->flags) { - /* area not released yet */ - if (time_after(jiffies, t->start_jiffies + TIMEOUT)) - return -ETIMEDOUT; - return -EINPROGRESS; - } - return 0; -} - -static int task_fn_area_2(struct anybuss_host *cd, struct ab_task *t) -{ - struct area_priv *pd = &t->area_pd; - unsigned int ind_ap; - int ret; - - if (!cd->power_on) - return -EIO; - regmap_read(cd->regmap, REG_IND_AP, &ind_ap); - if (!(atomic_read(&cd->ind_ab) & pd->flags)) { - /* we don't own the area yet */ - if (time_after(jiffies, t->start_jiffies + TIMEOUT)) { - dev_warn(cd->dev, "timeout waiting for area"); - dump_stack(); - return -ETIMEDOUT; - } - return -EINPROGRESS; - } - /* we own the area, do what we're here to do */ - if (pd->is_write) - regmap_bulk_write(cd->regmap, pd->addr, pd->buf, - pd->count); - else - regmap_bulk_read(cd->regmap, pd->addr, pd->buf, - pd->count); - /* ask to release the area, must use unlocked release */ - ind_ap &= ~IND_AP_ABITS; - ind_ap |= pd->flags; - ret = write_ind_ap(cd->regmap, ind_ap); - if (ret) - return ret; - t->task_fn = task_fn_area_3; - return -EINPROGRESS; -} - -static int task_fn_area(struct anybuss_host *cd, struct ab_task *t) -{ - struct area_priv *pd = &t->area_pd; - unsigned int ind_ap; - int ret; - - if (!cd->power_on) - return -EIO; - regmap_read(cd->regmap, REG_IND_AP, &ind_ap); - /* ask to take the area */ - ind_ap &= ~IND_AP_ABITS; - ind_ap |= pd->flags | IND_AP_ACTION | IND_AP_LOCK; - ret = write_ind_ap(cd->regmap, ind_ap); - if (ret) - return ret; - t->task_fn = task_fn_area_2; - return -EINPROGRESS; -} - -static struct ab_task * -create_area_reader(struct kmem_cache *qcache, u16 flags, u16 addr, - size_t count) -{ - struct ab_task *t; - struct area_priv *ap; - - t = ab_task_create_get(qcache, task_fn_area); - if (!t) - return NULL; - ap = &t->area_pd; - ap->flags = flags; - ap->addr = addr; - ap->is_write = false; - ap->count = count; - return t; -} - -static struct ab_task * -create_area_writer(struct kmem_cache *qcache, u16 flags, u16 addr, - const void *buf, size_t count) -{ - struct ab_task *t; - struct area_priv *ap; - - t = ab_task_create_get(qcache, task_fn_area); - if (!t) - return NULL; - ap = &t->area_pd; - ap->flags = flags; - ap->addr = addr; - ap->is_write = true; - ap->count = count; - memcpy(ap->buf, buf, count); - return t; -} - -static struct ab_task * -create_area_user_writer(struct kmem_cache *qcache, u16 flags, u16 addr, - const void __user *buf, size_t count) -{ - struct ab_task *t; - struct area_priv *ap; - - t = ab_task_create_get(qcache, task_fn_area); - if (!t) - return ERR_PTR(-ENOMEM); - ap = &t->area_pd; - ap->flags = flags; - ap->addr = addr; - ap->is_write = true; - ap->count = count; - if (copy_from_user(ap->buf, buf, count)) { - ab_task_put(t); - return ERR_PTR(-EFAULT); - } - return t; -} - -static bool area_range_ok(u16 addr, size_t count, u16 area_start, - size_t area_sz) -{ - u16 area_end_ex = area_start + area_sz; - u16 addr_end_ex; - - if (addr < area_start) - return false; - if (addr >= area_end_ex) - return false; - addr_end_ex = addr + count; - if (addr_end_ex > area_end_ex) - return false; - return true; -} - -/* -------------------------- mailbox tasks ----------------------- */ - -static int task_fn_mbox_2(struct anybuss_host *cd, struct ab_task *t) -{ - struct mbox_priv *pd = &t->mbox_pd; - unsigned int ind_ap; - - if (!cd->power_on) - return -EIO; - regmap_read(cd->regmap, REG_IND_AP, &ind_ap); - if (((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_MOUT) == 0) { - /* output message not here */ - if (time_after(jiffies, t->start_jiffies + TIMEOUT)) - return -ETIMEDOUT; - return -EINPROGRESS; - } - /* grab the returned header and msg */ - regmap_bulk_read(cd->regmap, MBOX_OUT_AREA, &pd->hdr, - sizeof(pd->hdr)); - regmap_bulk_read(cd->regmap, MBOX_OUT_AREA + sizeof(pd->hdr), - pd->msg, pd->msg_in_sz); - /* tell anybus we've consumed the message */ - ind_ap ^= IND_AX_MOUT; - return write_ind_ap(cd->regmap, ind_ap); -} - -static int task_fn_mbox(struct anybuss_host *cd, struct ab_task *t) -{ - struct mbox_priv *pd = &t->mbox_pd; - unsigned int ind_ap; - int ret; - - if (!cd->power_on) - return -EIO; - regmap_read(cd->regmap, REG_IND_AP, &ind_ap); - if ((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_MIN) { - /* mbox input area busy */ - if (time_after(jiffies, t->start_jiffies + TIMEOUT)) - return -ETIMEDOUT; - return -EINPROGRESS; - } - /* write the header and msg to input area */ - regmap_bulk_write(cd->regmap, MBOX_IN_AREA, &pd->hdr, - sizeof(pd->hdr)); - regmap_bulk_write(cd->regmap, MBOX_IN_AREA + sizeof(pd->hdr), - pd->msg, pd->msg_out_sz); - /* tell anybus we gave it a message */ - ind_ap ^= IND_AX_MIN; - ret = write_ind_ap(cd->regmap, ind_ap); - if (ret) - return ret; - t->start_jiffies = jiffies; - t->task_fn = task_fn_mbox_2; - return -EINPROGRESS; -} - -static void log_invalid_other(struct device *dev, - struct anybus_mbox_hdr *hdr) -{ - size_t ext_offs = ARRAY_SIZE(hdr->extended) - 1; - u16 code = be16_to_cpu(hdr->extended[ext_offs]); - - dev_err(dev, " Invalid other: [0x%02X]", code); -} - -static const char * const EMSGS[] = { - "Invalid Message ID", - "Invalid Message Type", - "Invalid Command", - "Invalid Data Size", - "Message Header Malformed (offset 008h)", - "Message Header Malformed (offset 00Ah)", - "Message Header Malformed (offset 00Ch - 00Dh)", - "Invalid Address", - "Invalid Response", - "Flash Config Error", -}; - -static int mbox_cmd_err(struct device *dev, struct mbox_priv *mpriv) -{ - int i; - u8 ecode; - struct anybus_mbox_hdr *hdr = &mpriv->hdr; - u16 info = be16_to_cpu(hdr->info); - u8 *phdr = (u8 *)hdr; - u8 *pmsg = mpriv->msg; - - if (!(info & 0x8000)) - return 0; - ecode = (info >> 8) & 0x0F; - dev_err(dev, "mailbox command failed:"); - if (ecode == 0x0F) - log_invalid_other(dev, hdr); - else if (ecode < ARRAY_SIZE(EMSGS)) - dev_err(dev, " Error code: %s (0x%02X)", - EMSGS[ecode], ecode); - else - dev_err(dev, " Error code: 0x%02X\n", ecode); - dev_err(dev, "Failed command:"); - dev_err(dev, "Message Header:"); - for (i = 0; i < sizeof(mpriv->hdr); i += 2) - dev_err(dev, "%02X%02X", phdr[i], phdr[i + 1]); - dev_err(dev, "Message Data:"); - for (i = 0; i < mpriv->msg_in_sz; i += 2) - dev_err(dev, "%02X%02X", pmsg[i], pmsg[i + 1]); - dev_err(dev, "Stack dump:"); - dump_stack(); - return -EIO; -} - -static int _anybus_mbox_cmd(struct anybuss_host *cd, - u16 cmd_num, bool is_fb_cmd, - const void *msg_out, size_t msg_out_sz, - void *msg_in, size_t msg_in_sz, - const void *ext, size_t ext_sz) -{ - struct ab_task *t; - struct mbox_priv *pd; - struct anybus_mbox_hdr *h; - size_t msg_sz = max(msg_in_sz, msg_out_sz); - u16 info; - int err; - - if (msg_sz > MAX_MBOX_MSG_SZ) - return -EINVAL; - if (ext && ext_sz > sizeof(h->extended)) - return -EINVAL; - t = ab_task_create_get(cd->qcache, task_fn_mbox); - if (!t) - return -ENOMEM; - pd = &t->mbox_pd; - h = &pd->hdr; - info = is_fb_cmd ? INFO_TYPE_FB : INFO_TYPE_APP; - /* - * prevent uninitialized memory in the header from being sent - * across the anybus - */ - memset(h, 0, sizeof(*h)); - h->info = cpu_to_be16(info | INFO_COMMAND); - h->cmd_num = cpu_to_be16(cmd_num); - h->data_size = cpu_to_be16(msg_out_sz); - h->frame_count = cpu_to_be16(1); - h->frame_num = cpu_to_be16(1); - h->offset_high = cpu_to_be16(0); - h->offset_low = cpu_to_be16(0); - if (ext) - memcpy(h->extended, ext, ext_sz); - memcpy(pd->msg, msg_out, msg_out_sz); - pd->msg_out_sz = msg_out_sz; - pd->msg_in_sz = msg_in_sz; - err = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq); - if (err) - goto out; - /* - * mailbox mechanism worked ok, but maybe the mbox response - * contains an error ? - */ - err = mbox_cmd_err(cd->dev, pd); - if (err) - goto out; - memcpy(msg_in, pd->msg, msg_in_sz); -out: - ab_task_put(t); - return err; -} - -/* ------------------------ anybus queues ------------------------ */ - -static void process_q(struct anybuss_host *cd, struct kfifo *q) -{ - struct ab_task *t; - int ret; - - ret = kfifo_out_peek(q, &t, sizeof(t)); - if (!ret) - return; - t->result = t->task_fn(cd, t); - if (t->result != -EINPROGRESS) - ab_task_dequeue_finish_put(q, cd); -} - -static bool qs_have_work(struct kfifo *qs, size_t num) -{ - size_t i; - struct ab_task *t; - int ret; - - for (i = 0; i < num; i++, qs++) { - ret = kfifo_out_peek(qs, &t, sizeof(t)); - if (ret && (t->result != -EINPROGRESS)) - return true; - } - return false; -} - -static void process_qs(struct anybuss_host *cd) -{ - size_t i; - struct kfifo *qs = cd->qs; - size_t nqs = ARRAY_SIZE(cd->qs); - - for (i = 0; i < nqs; i++, qs++) - process_q(cd, qs); -} - -static void softint_ack(struct anybuss_host *cd) -{ - unsigned int ind_ap; - - cd->softint_pending = false; - if (!cd->power_on) - return; - regmap_read(cd->regmap, REG_IND_AP, &ind_ap); - ind_ap &= ~IND_AX_EVNT; - ind_ap |= atomic_read(&cd->ind_ab) & IND_AX_EVNT; - write_ind_ap(cd->regmap, ind_ap); -} - -static void process_softint(struct anybuss_host *cd) -{ - struct anybuss_client *client = cd->client; - static const u8 zero; - int ret; - unsigned int ind_ap, ev; - struct ab_task *t; - - if (!cd->power_on) - return; - if (cd->softint_pending) - return; - regmap_read(cd->regmap, REG_IND_AP, &ind_ap); - if (!((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_EVNT)) - return; - /* process software interrupt */ - regmap_read(cd->regmap, REG_EVENT_CAUSE, &ev); - if (ev & EVENT_CAUSE_FBON) { - if (client->on_online_changed) - client->on_online_changed(client, true); - dev_dbg(cd->dev, "Fieldbus ON"); - } - if (ev & EVENT_CAUSE_FBOF) { - if (client->on_online_changed) - client->on_online_changed(client, false); - dev_dbg(cd->dev, "Fieldbus OFF"); - } - if (ev & EVENT_CAUSE_DC) { - if (client->on_area_updated) - client->on_area_updated(client); - dev_dbg(cd->dev, "Fieldbus data changed"); - } - /* - * reset the event cause bits. - * this must be done while owning the fbctrl area, so we'll - * enqueue a task to do that. - */ - t = create_area_writer(cd->qcache, IND_AX_FBCTRL, - REG_EVENT_CAUSE, &zero, sizeof(zero)); - if (!t) { - ret = -ENOMEM; - goto out; - } - t->done_fn = softint_ack; - ret = ab_task_enqueue(t, cd->powerq, &cd->qlock, &cd->wq); - ab_task_put(t); - cd->softint_pending = true; -out: - WARN_ON(ret); - if (ret) - softint_ack(cd); -} - -static int qthread_fn(void *data) -{ - struct anybuss_host *cd = data; - struct kfifo *qs = cd->qs; - size_t nqs = ARRAY_SIZE(cd->qs); - unsigned int ind_ab; - - /* - * this kernel thread has exclusive access to the anybus's memory. - * only exception: the IND_AB register, which is accessed exclusively - * by the interrupt service routine (ISR). This thread must not touch - * the IND_AB register, but it does require access to its value. - * - * the interrupt service routine stores the register's value in - * cd->ind_ab (an atomic_t), where we may safely access it, with the - * understanding that it can be modified by the ISR at any time. - */ - - while (!kthread_should_stop()) { - /* - * make a local copy of IND_AB, so we can go around the loop - * again in case it changed while processing queues and softint. - */ - ind_ab = atomic_read(&cd->ind_ab); - process_qs(cd); - process_softint(cd); - wait_event_timeout(cd->wq, - (atomic_read(&cd->ind_ab) != ind_ab) || - qs_have_work(qs, nqs) || - kthread_should_stop(), - HZ); - /* - * time out so even 'stuck' tasks will run eventually, - * and can time out. - */ - } - - return 0; -} - -/* ------------------------ anybus exports ------------------------ */ - -int anybuss_start_init(struct anybuss_client *client, - const struct anybuss_memcfg *cfg) -{ - int ret; - u16 op_mode; - struct anybuss_host *cd = client->host; - struct msg_anybus_init msg = { - .input_io_len = cpu_to_be16(cfg->input_io), - .input_dpram_len = cpu_to_be16(cfg->input_dpram), - .input_total_len = cpu_to_be16(cfg->input_total), - .output_io_len = cpu_to_be16(cfg->output_io), - .output_dpram_len = cpu_to_be16(cfg->output_dpram), - .output_total_len = cpu_to_be16(cfg->output_total), - .notif_config = cpu_to_be16(0x000F), - .wd_val = cpu_to_be16(0), - }; - - switch (cfg->offl_mode) { - case FIELDBUS_DEV_OFFL_MODE_CLEAR: - op_mode = 0; - break; - case FIELDBUS_DEV_OFFL_MODE_FREEZE: - op_mode = OP_MODE_FBFC; - break; - case FIELDBUS_DEV_OFFL_MODE_SET: - op_mode = OP_MODE_FBS; - break; - default: - return -EINVAL; - } - msg.op_mode = cpu_to_be16(op_mode | OP_MODE_CD); - ret = _anybus_mbox_cmd(cd, CMD_START_INIT, false, NULL, 0, - NULL, 0, NULL, 0); - if (ret) - return ret; - return _anybus_mbox_cmd(cd, CMD_ANYBUS_INIT, false, - &msg, sizeof(msg), NULL, 0, NULL, 0); -} -EXPORT_SYMBOL_GPL(anybuss_start_init); - -int anybuss_finish_init(struct anybuss_client *client) -{ - struct anybuss_host *cd = client->host; - - return _anybus_mbox_cmd(cd, CMD_END_INIT, false, NULL, 0, - NULL, 0, NULL, 0); -} -EXPORT_SYMBOL_GPL(anybuss_finish_init); - -int anybuss_read_fbctrl(struct anybuss_client *client, u16 addr, - void *buf, size_t count) -{ - struct anybuss_host *cd = client->host; - struct ab_task *t; - int ret; - - if (count == 0) - return 0; - if (!area_range_ok(addr, count, FBCTRL_AREA, - MAX_FBCTRL_AREA_SZ)) - return -EFAULT; - t = create_area_reader(cd->qcache, IND_AX_FBCTRL, addr, count); - if (!t) - return -ENOMEM; - ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq); - if (ret) - goto out; - memcpy(buf, t->area_pd.buf, count); -out: - ab_task_put(t); - return ret; -} -EXPORT_SYMBOL_GPL(anybuss_read_fbctrl); - -int anybuss_write_input(struct anybuss_client *client, - const char __user *buf, size_t size, - loff_t *offset) -{ - ssize_t len = min_t(loff_t, MAX_DATA_AREA_SZ - *offset, size); - struct anybuss_host *cd = client->host; - struct ab_task *t; - int ret; - - if (len <= 0) - return 0; - t = create_area_user_writer(cd->qcache, IND_AX_IN, - DATA_IN_AREA + *offset, buf, len); - if (IS_ERR(t)) - return PTR_ERR(t); - ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq); - ab_task_put(t); - if (ret) - return ret; - /* success */ - *offset += len; - return len; -} -EXPORT_SYMBOL_GPL(anybuss_write_input); - -int anybuss_read_output(struct anybuss_client *client, - char __user *buf, size_t size, - loff_t *offset) -{ - ssize_t len = min_t(loff_t, MAX_DATA_AREA_SZ - *offset, size); - struct anybuss_host *cd = client->host; - struct ab_task *t; - int ret; - - if (len <= 0) - return 0; - t = create_area_reader(cd->qcache, IND_AX_OUT, - DATA_OUT_AREA + *offset, len); - if (!t) - return -ENOMEM; - ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq); - if (ret) - goto out; - if (copy_to_user(buf, t->area_pd.buf, len)) - ret = -EFAULT; -out: - ab_task_put(t); - if (ret) - return ret; - /* success */ - *offset += len; - return len; -} -EXPORT_SYMBOL_GPL(anybuss_read_output); - -int anybuss_send_msg(struct anybuss_client *client, u16 cmd_num, - const void *buf, size_t count) -{ - struct anybuss_host *cd = client->host; - - return _anybus_mbox_cmd(cd, cmd_num, true, buf, count, NULL, 0, - NULL, 0); -} -EXPORT_SYMBOL_GPL(anybuss_send_msg); - -int anybuss_send_ext(struct anybuss_client *client, u16 cmd_num, - const void *buf, size_t count) -{ - struct anybuss_host *cd = client->host; - - return _anybus_mbox_cmd(cd, cmd_num, true, NULL, 0, NULL, 0, - buf, count); -} -EXPORT_SYMBOL_GPL(anybuss_send_ext); - -int anybuss_recv_msg(struct anybuss_client *client, u16 cmd_num, - void *buf, size_t count) -{ - struct anybuss_host *cd = client->host; - - return _anybus_mbox_cmd(cd, cmd_num, true, NULL, 0, buf, count, - NULL, 0); -} -EXPORT_SYMBOL_GPL(anybuss_recv_msg); - -/* ------------------------ bus functions ------------------------ */ - -static int anybus_bus_match(struct device *dev, - const struct device_driver *drv) -{ - const struct anybuss_client_driver *adrv = - to_anybuss_client_driver(drv); - struct anybuss_client *adev = - to_anybuss_client(dev); - - return adrv->anybus_id == be16_to_cpu(adev->anybus_id); -} - -static int anybus_bus_probe(struct device *dev) -{ - struct anybuss_client_driver *adrv = - to_anybuss_client_driver(dev->driver); - struct anybuss_client *adev = - to_anybuss_client(dev); - - return adrv->probe(adev); -} - -static void anybus_bus_remove(struct device *dev) -{ - struct anybuss_client_driver *adrv = - to_anybuss_client_driver(dev->driver); - - if (adrv->remove) - adrv->remove(to_anybuss_client(dev)); -} - -static const struct bus_type anybus_bus = { - .name = "anybuss", - .match = anybus_bus_match, - .probe = anybus_bus_probe, - .remove = anybus_bus_remove, -}; - -int anybuss_client_driver_register(struct anybuss_client_driver *drv) -{ - if (!drv->probe) - return -ENODEV; - - drv->driver.bus = &anybus_bus; - return driver_register(&drv->driver); -} -EXPORT_SYMBOL_GPL(anybuss_client_driver_register); - -void anybuss_client_driver_unregister(struct anybuss_client_driver *drv) -{ - return driver_unregister(&drv->driver); -} -EXPORT_SYMBOL_GPL(anybuss_client_driver_unregister); - -static void client_device_release(struct device *dev) -{ - kfree(to_anybuss_client(dev)); -} - -static int taskq_alloc(struct device *dev, struct kfifo *q) -{ - void *buf; - size_t size = 64 * sizeof(struct ab_task *); - - buf = devm_kzalloc(dev, size, GFP_KERNEL); - if (!buf) - return -EIO; - return kfifo_init(q, buf, size); -} - -static int anybus_of_get_host_idx(struct device_node *np) -{ - const __be32 *host_idx; - - host_idx = of_get_address(np, 0, NULL, NULL); - if (!host_idx) - return -ENOENT; - return __be32_to_cpu(*host_idx); -} - -static struct device_node * -anybus_of_find_child_device(struct device *dev, int host_idx) -{ - struct device_node *node; - - if (!dev || !dev->of_node) - return NULL; - for_each_child_of_node(dev->of_node, node) { - if (anybus_of_get_host_idx(node) == host_idx) - return node; - } - return NULL; -} - -struct anybuss_host * __must_check -anybuss_host_common_probe(struct device *dev, - const struct anybuss_ops *ops) -{ - int ret, i; - u8 val[4]; - __be16 fieldbus_type; - struct anybuss_host *cd; - - cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL); - if (!cd) - return ERR_PTR(-ENOMEM); - cd->dev = dev; - cd->host_idx = ops->host_idx; - init_completion(&cd->card_boot); - init_waitqueue_head(&cd->wq); - for (i = 0; i < ARRAY_SIZE(cd->qs); i++) { - ret = taskq_alloc(dev, &cd->qs[i]); - if (ret) - return ERR_PTR(ret); - } - if (WARN_ON(ARRAY_SIZE(cd->qs) < 3)) - return ERR_PTR(-EINVAL); - cd->powerq = &cd->qs[0]; - cd->mboxq = &cd->qs[1]; - cd->areaq = &cd->qs[2]; - cd->reset = ops->reset; - if (!cd->reset) - return ERR_PTR(-EINVAL); - cd->regmap = ops->regmap; - if (!cd->regmap) - return ERR_PTR(-EINVAL); - spin_lock_init(&cd->qlock); - cd->qcache = kmem_cache_create(dev_name(dev), - sizeof(struct ab_task), 0, 0, NULL); - if (!cd->qcache) - return ERR_PTR(-ENOMEM); - cd->irq = ops->irq; - if (cd->irq <= 0) { - ret = -EINVAL; - goto err_qcache; - } - /* - * use a dpram test to check if a card is present, this is only - * possible while in reset. - */ - reset_assert(cd); - if (test_dpram(cd->regmap)) { - dev_err(dev, "no Anybus-S card in slot"); - ret = -ENODEV; - goto err_qcache; - } - ret = devm_request_threaded_irq(dev, cd->irq, NULL, irq_handler, - IRQF_ONESHOT, dev_name(dev), cd); - if (ret) { - dev_err(dev, "could not request irq"); - goto err_qcache; - } - /* - * startup sequence: - * a) perform dummy IND_AB read to prevent false 'init done' irq - * (already done by test_dpram() above) - * b) release reset - * c) wait for first interrupt - * d) interrupt came in: ready to go ! - */ - reset_deassert(cd); - if (!wait_for_completion_timeout(&cd->card_boot, TIMEOUT)) { - ret = -ETIMEDOUT; - goto err_reset; - } - /* - * according to the anybus docs, we're allowed to read these - * without handshaking / reserving the area - */ - dev_info(dev, "Anybus-S card detected"); - regmap_bulk_read(cd->regmap, REG_BOOTLOADER_V, val, 2); - dev_info(dev, "Bootloader version: %02X%02X", - val[0], val[1]); - regmap_bulk_read(cd->regmap, REG_API_V, val, 2); - dev_info(dev, "API version: %02X%02X", val[0], val[1]); - regmap_bulk_read(cd->regmap, REG_FIELDBUS_V, val, 2); - dev_info(dev, "Fieldbus version: %02X%02X", val[0], val[1]); - regmap_bulk_read(cd->regmap, REG_SERIAL_NO, val, 4); - dev_info(dev, "Serial number: %02X%02X%02X%02X", - val[0], val[1], val[2], val[3]); - add_device_randomness(&val, 4); - regmap_bulk_read(cd->regmap, REG_FIELDBUS_TYPE, &fieldbus_type, - sizeof(fieldbus_type)); - dev_info(dev, "Fieldbus type: %04X", be16_to_cpu(fieldbus_type)); - regmap_bulk_read(cd->regmap, REG_MODULE_SW_V, val, 2); - dev_info(dev, "Module SW version: %02X%02X", - val[0], val[1]); - /* put card back reset until a client driver releases it */ - disable_irq(cd->irq); - reset_assert(cd); - atomic_set(&cd->ind_ab, IND_AB_UPDATED); - /* fire up the queue thread */ - cd->qthread = kthread_run(qthread_fn, cd, dev_name(dev)); - if (IS_ERR(cd->qthread)) { - dev_err(dev, "could not create kthread"); - ret = PTR_ERR(cd->qthread); - goto err_reset; - } - /* - * now advertise that we've detected a client device (card). - * the bus infrastructure will match it to a client driver. - */ - cd->client = kzalloc(sizeof(*cd->client), GFP_KERNEL); - if (!cd->client) { - ret = -ENOMEM; - goto err_kthread; - } - cd->client->anybus_id = fieldbus_type; - cd->client->host = cd; - cd->client->dev.bus = &anybus_bus; - cd->client->dev.parent = dev; - cd->client->dev.release = client_device_release; - cd->client->dev.of_node = - anybus_of_find_child_device(dev, cd->host_idx); - dev_set_name(&cd->client->dev, "anybuss.card%d", cd->host_idx); - ret = device_register(&cd->client->dev); - if (ret) - goto err_device; - return cd; -err_device: - put_device(&cd->client->dev); -err_kthread: - kthread_stop(cd->qthread); -err_reset: - reset_assert(cd); -err_qcache: - kmem_cache_destroy(cd->qcache); - return ERR_PTR(ret); -} -EXPORT_SYMBOL_GPL(anybuss_host_common_probe); - -void anybuss_host_common_remove(struct anybuss_host *host) -{ - struct anybuss_host *cd = host; - - device_unregister(&cd->client->dev); - kthread_stop(cd->qthread); - reset_assert(cd); - kmem_cache_destroy(cd->qcache); -} -EXPORT_SYMBOL_GPL(anybuss_host_common_remove); - -static void host_release(void *res) -{ - anybuss_host_common_remove(res); -} - -struct anybuss_host * __must_check -devm_anybuss_host_common_probe(struct device *dev, - const struct anybuss_ops *ops) -{ - struct anybuss_host *host; - int ret; - - host = anybuss_host_common_probe(dev, ops); - if (IS_ERR(host)) - return host; - - ret = devm_add_action_or_reset(dev, host_release, host); - if (ret) - return ERR_PTR(ret); - - return host; -} -EXPORT_SYMBOL_GPL(devm_anybuss_host_common_probe); - -static int __init anybus_init(void) -{ - int ret; - - ret = bus_register(&anybus_bus); - if (ret) - pr_err("could not register Anybus-S bus: %d\n", ret); - return ret; -} -module_init(anybus_init); - -static void __exit anybus_exit(void) -{ - bus_unregister(&anybus_bus); -} -module_exit(anybus_exit); - -MODULE_DESCRIPTION("HMS Anybus-S Host Driver"); -MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/fieldbus/dev_core.c b/drivers/staging/fieldbus/dev_core.c deleted file mode 100644 index 0053ebd91442de3ffa1e0fbabcb3f7152f27053e..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/dev_core.c +++ /dev/null @@ -1,344 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Fieldbus Device Driver Core - * - */ - -#include <linux/mutex.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/idr.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include <linux/poll.h> - -/* move to <linux/fieldbus_dev.h> when taking this out of staging */ -#include "fieldbus_dev.h" - -/* Maximum number of fieldbus devices */ -#define MAX_FIELDBUSES 32 - -/* the dev_t structure to store the dynamically allocated fieldbus devices */ -static dev_t fieldbus_devt; -static DEFINE_IDA(fieldbus_ida); -static DEFINE_MUTEX(fieldbus_mtx); - -static ssize_t online_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%d\n", !!fb->online); -} -static DEVICE_ATTR_RO(online); - -static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - - if (!fb->enable_get) - return -EINVAL; - return sysfs_emit(buf, "%d\n", !!fb->enable_get(fb)); -} - -static ssize_t enabled_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t n) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - bool value; - int ret; - - if (!fb->simple_enable_set) - return -ENOTSUPP; - ret = kstrtobool(buf, &value); - if (ret) - return ret; - ret = fb->simple_enable_set(fb, value); - if (ret < 0) - return ret; - return n; -} -static DEVICE_ATTR_RW(enabled); - -static ssize_t card_name_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - - /* card_name was provided by child driver. */ - return sysfs_emit(buf, "%s\n", fb->card_name); -} -static DEVICE_ATTR_RO(card_name); - -static ssize_t read_area_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%zu\n", fb->read_area_sz); -} -static DEVICE_ATTR_RO(read_area_size); - -static ssize_t write_area_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - - return sysfs_emit(buf, "%zu\n", fb->write_area_sz); -} -static DEVICE_ATTR_RO(write_area_size); - -static ssize_t fieldbus_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - - return fb->fieldbus_id_get(fb, buf, PAGE_SIZE); -} -static DEVICE_ATTR_RO(fieldbus_id); - -static ssize_t fieldbus_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fieldbus_dev *fb = dev_get_drvdata(dev); - const char *t; - - switch (fb->fieldbus_type) { - case FIELDBUS_DEV_TYPE_PROFINET: - t = "profinet"; - break; - default: - t = "unknown"; - break; - } - - return sysfs_emit(buf, "%s\n", t); -} -static DEVICE_ATTR_RO(fieldbus_type); - -static struct attribute *fieldbus_attrs[] = { - &dev_attr_enabled.attr, - &dev_attr_card_name.attr, - &dev_attr_fieldbus_id.attr, - &dev_attr_read_area_size.attr, - &dev_attr_write_area_size.attr, - &dev_attr_online.attr, - &dev_attr_fieldbus_type.attr, - NULL, -}; - -static umode_t fieldbus_is_visible(struct kobject *kobj, struct attribute *attr, - int n) -{ - struct device *dev = kobj_to_dev(kobj); - struct fieldbus_dev *fb = dev_get_drvdata(dev); - umode_t mode = attr->mode; - - if (attr == &dev_attr_enabled.attr) { - mode = 0; - if (fb->enable_get) - mode |= 0444; - if (fb->simple_enable_set) - mode |= 0200; - } - - return mode; -} - -static const struct attribute_group fieldbus_group = { - .attrs = fieldbus_attrs, - .is_visible = fieldbus_is_visible, -}; -__ATTRIBUTE_GROUPS(fieldbus); - -static const struct class fieldbus_class = { - .name = "fieldbus_dev", - .dev_groups = fieldbus_groups, -}; - -struct fb_open_file { - struct fieldbus_dev *fbdev; - int dc_event; -}; - -static int fieldbus_open(struct inode *inode, struct file *filp) -{ - struct fb_open_file *of; - struct fieldbus_dev *fbdev = container_of(inode->i_cdev, - struct fieldbus_dev, - cdev); - - of = kzalloc(sizeof(*of), GFP_KERNEL); - if (!of) - return -ENOMEM; - of->fbdev = fbdev; - filp->private_data = of; - return 0; -} - -static int fieldbus_release(struct inode *node, struct file *filp) -{ - struct fb_open_file *of = filp->private_data; - - kfree(of); - return 0; -} - -static ssize_t fieldbus_read(struct file *filp, char __user *buf, size_t size, - loff_t *offset) -{ - struct fb_open_file *of = filp->private_data; - struct fieldbus_dev *fbdev = of->fbdev; - - of->dc_event = fbdev->dc_event; - return fbdev->read_area(fbdev, buf, size, offset); -} - -static ssize_t fieldbus_write(struct file *filp, const char __user *buf, - size_t size, loff_t *offset) -{ - struct fb_open_file *of = filp->private_data; - struct fieldbus_dev *fbdev = of->fbdev; - - return fbdev->write_area(fbdev, buf, size, offset); -} - -static __poll_t fieldbus_poll(struct file *filp, poll_table *wait) -{ - struct fb_open_file *of = filp->private_data; - struct fieldbus_dev *fbdev = of->fbdev; - __poll_t mask = EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM; - - poll_wait(filp, &fbdev->dc_wq, wait); - /* data changed ? */ - if (fbdev->dc_event != of->dc_event) - mask |= EPOLLPRI | EPOLLERR; - return mask; -} - -static const struct file_operations fieldbus_fops = { - .open = fieldbus_open, - .release = fieldbus_release, - .read = fieldbus_read, - .write = fieldbus_write, - .poll = fieldbus_poll, - .llseek = generic_file_llseek, - .owner = THIS_MODULE, -}; - -void fieldbus_dev_area_updated(struct fieldbus_dev *fb) -{ - fb->dc_event++; - wake_up_all(&fb->dc_wq); -} -EXPORT_SYMBOL_GPL(fieldbus_dev_area_updated); - -void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online) -{ - fb->online = online; - kobject_uevent(&fb->dev->kobj, KOBJ_CHANGE); -} -EXPORT_SYMBOL_GPL(fieldbus_dev_online_changed); - -static void __fieldbus_dev_unregister(struct fieldbus_dev *fb) -{ - if (!fb) - return; - device_destroy(&fieldbus_class, fb->cdev.dev); - cdev_del(&fb->cdev); - ida_free(&fieldbus_ida, fb->id); -} - -void fieldbus_dev_unregister(struct fieldbus_dev *fb) -{ - mutex_lock(&fieldbus_mtx); - __fieldbus_dev_unregister(fb); - mutex_unlock(&fieldbus_mtx); -} -EXPORT_SYMBOL_GPL(fieldbus_dev_unregister); - -static int __fieldbus_dev_register(struct fieldbus_dev *fb) -{ - dev_t devno; - int err; - - if (!fb) - return -EINVAL; - if (!fb->read_area || !fb->write_area || !fb->fieldbus_id_get) - return -EINVAL; - fb->id = ida_alloc_max(&fieldbus_ida, MAX_FIELDBUSES - 1, GFP_KERNEL); - if (fb->id < 0) - return fb->id; - devno = MKDEV(MAJOR(fieldbus_devt), fb->id); - init_waitqueue_head(&fb->dc_wq); - cdev_init(&fb->cdev, &fieldbus_fops); - err = cdev_add(&fb->cdev, devno, 1); - if (err) { - pr_err("fieldbus_dev%d unable to add device %d:%d\n", - fb->id, MAJOR(fieldbus_devt), fb->id); - goto err_cdev; - } - fb->dev = device_create(&fieldbus_class, fb->parent, devno, fb, - "fieldbus_dev%d", fb->id); - if (IS_ERR(fb->dev)) { - err = PTR_ERR(fb->dev); - goto err_dev_create; - } - return 0; - -err_dev_create: - cdev_del(&fb->cdev); -err_cdev: - ida_free(&fieldbus_ida, fb->id); - return err; -} - -int fieldbus_dev_register(struct fieldbus_dev *fb) -{ - int err; - - mutex_lock(&fieldbus_mtx); - err = __fieldbus_dev_register(fb); - mutex_unlock(&fieldbus_mtx); - - return err; -} -EXPORT_SYMBOL_GPL(fieldbus_dev_register); - -static int __init fieldbus_init(void) -{ - int err; - - err = class_register(&fieldbus_class); - if (err < 0) { - pr_err("fieldbus_dev: could not register class\n"); - return err; - } - err = alloc_chrdev_region(&fieldbus_devt, 0, - MAX_FIELDBUSES, "fieldbus_dev"); - if (err < 0) { - pr_err("fieldbus_dev: unable to allocate char dev region\n"); - goto err_alloc; - } - return 0; - -err_alloc: - class_unregister(&fieldbus_class); - return err; -} - -static void __exit fieldbus_exit(void) -{ - unregister_chrdev_region(fieldbus_devt, MAX_FIELDBUSES); - class_unregister(&fieldbus_class); - ida_destroy(&fieldbus_ida); -} - -subsys_initcall(fieldbus_init); -module_exit(fieldbus_exit); - -MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>"); -MODULE_AUTHOR("Jonathan Stiles <jonathans@arcx.com>"); -MODULE_DESCRIPTION("Fieldbus Device Driver Core"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/fieldbus/fieldbus_dev.h b/drivers/staging/fieldbus/fieldbus_dev.h deleted file mode 100644 index 301dca3b8d71a72cd4bd3e47bd036187124b3866..0000000000000000000000000000000000000000 --- a/drivers/staging/fieldbus/fieldbus_dev.h +++ /dev/null @@ -1,114 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Fieldbus Device Driver Core - * - */ - -#ifndef __FIELDBUS_DEV_H -#define __FIELDBUS_DEV_H - -#include <linux/cdev.h> -#include <linux/wait.h> - -enum fieldbus_dev_type { - FIELDBUS_DEV_TYPE_UNKNOWN = 0, - FIELDBUS_DEV_TYPE_PROFINET, -}; - -enum fieldbus_dev_offl_mode { - FIELDBUS_DEV_OFFL_MODE_CLEAR = 0, - FIELDBUS_DEV_OFFL_MODE_FREEZE, - FIELDBUS_DEV_OFFL_MODE_SET -}; - -/** - * struct fieldbus_dev - Fieldbus device - * @read_area: [DRIVER] function to read the process data area of the - * device. same parameters/return values as - * the read function in struct file_operations - * @write_area: [DRIVER] function to write to the process data area of - * the device. same parameters/return values as - * the write function in struct file_operations - * @write_area_sz [DRIVER] size of the writable process data area - * @read_area_sz [DRIVER] size of the readable process data area - * @card_name [DRIVER] name of the card, e.g. "ACME Inc. profinet" - * @fieldbus_type [DRIVER] fieldbus type of this device, e.g. - * FIELDBUS_DEV_TYPE_PROFINET - * @enable_get [DRIVER] function which returns true if the card - * is enabled, false otherwise - * @fieldbus_id_get [DRIVER] function to retrieve the unique fieldbus id - * by which this device can be identified; - * return value follows the snprintf convention - * @simple_enable_set [DRIVER] (optional) function to enable the device - * according to its default settings - * @parent [DRIVER] (optional) the device's parent device - */ -struct fieldbus_dev { - ssize_t (*read_area)(struct fieldbus_dev *fbdev, char __user *buf, - size_t size, loff_t *offset); - ssize_t (*write_area)(struct fieldbus_dev *fbdev, - const char __user *buf, size_t size, - loff_t *offset); - size_t write_area_sz, read_area_sz; - const char *card_name; - enum fieldbus_dev_type fieldbus_type; - bool (*enable_get)(struct fieldbus_dev *fbdev); - int (*fieldbus_id_get)(struct fieldbus_dev *fbdev, char *buf, - size_t max_size); - int (*simple_enable_set)(struct fieldbus_dev *fbdev, bool enable); - struct device *parent; - - /* private data */ - int id; - struct cdev cdev; - struct device *dev; - int dc_event; - wait_queue_head_t dc_wq; - bool online; -}; - -#if IS_ENABLED(CONFIG_FIELDBUS_DEV) - -/** - * fieldbus_dev_unregister() - * - unregister a previously registered fieldbus device - * @fb: Device structure previously registered - **/ -void fieldbus_dev_unregister(struct fieldbus_dev *fb); - -/** - * fieldbus_dev_register() - * - register a device with the fieldbus device subsystem - * @fb: Device structure filled by the device driver - **/ -int __must_check fieldbus_dev_register(struct fieldbus_dev *fb); - -/** - * fieldbus_dev_area_updated() - * - notify the subsystem that an external fieldbus controller updated - * the process data area - * @fb: Device structure - **/ -void fieldbus_dev_area_updated(struct fieldbus_dev *fb); - -/** - * fieldbus_dev_online_changed() - * - notify the subsystem that the fieldbus online status changed - * @fb: Device structure - **/ -void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online); - -#else /* IS_ENABLED(CONFIG_FIELDBUS_DEV) */ - -static inline void fieldbus_dev_unregister(struct fieldbus_dev *fb) {} -static inline int __must_check fieldbus_dev_register(struct fieldbus_dev *fb) -{ - return -ENOTSUPP; -} - -static inline void fieldbus_dev_area_updated(struct fieldbus_dev *fb) {} -static inline void fieldbus_dev_online_changed(struct fieldbus_dev *fb, - bool online) {} - -#endif /* IS_ENABLED(CONFIG_FIELDBUS_DEV) */ -#endif /* __FIELDBUS_DEV_H */ diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig deleted file mode 100644 index 1f403ecd9608b488b3677c82a8c1e896618bf252..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# GCT GDM724x LTE driver configuration -# - -config LTE_GDM724X - tristate "GCT GDM724x LTE support" - depends on NET && USB && TTY && m - help - This driver supports GCT GDM724x LTE chip based USB modem devices. - It exposes 4 network devices to be used per PDN and 2 tty devices to be - used for AT commands and DM monitoring applications. - The modules will be called gdmulte.ko and gdmtty.ko - - GCT-ATCx can be used for AT Commands - GCT-DMx can be used for LTE protocol monitoring diff --git a/drivers/staging/gdm724x/Makefile b/drivers/staging/gdm724x/Makefile deleted file mode 100644 index e61b95788c9fca0f925af2363701db2e08b32c57..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_LTE_GDM724X) := gdmulte.o -gdmulte-y += gdm_lte.o netlink_k.o -gdmulte-y += gdm_usb.o gdm_endian.o - -obj-$(CONFIG_LTE_GDM724X) += gdmtty.o -gdmtty-y := gdm_tty.o gdm_mux.o - diff --git a/drivers/staging/gdm724x/TODO b/drivers/staging/gdm724x/TODO deleted file mode 100644 index b2b571ecb063f740a332de328c187e38e3b9123a..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/TODO +++ /dev/null @@ -1,16 +0,0 @@ -TODO: -- Clean up coding style to meet kernel standard. (80 line limit, netdev_err) -- Remove test for host endian -- Remove confusing macros (endian, hci_send, sdu_send, rcv_with_cb) -- Fixes for every instances of function returning -1 -- Check for skb->len in gdm_lte_emulate_arp() -- Use ALIGN() macro for dummy_cnt in up_to_host() -- Error handling in init_usb() -- Explain reason for multiples of 512 bytes in alloc_tx_struct() -- Review use of atomic allocation for tx structs -- No error checking for alloc_tx_struct in do_tx() -- fix up static tty port allocation to be dynamic - -Patches to: - Jonathan Kim <jonathankim@gctsemi.com> - Dean ahn <deanahn@gctsemi.com> diff --git a/drivers/staging/gdm724x/gdm_endian.c b/drivers/staging/gdm724x/gdm_endian.c deleted file mode 100644 index ae39e59daf7074585607e3ffa0069c4009cad798..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_endian.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#include <linux/kernel.h> -#include "gdm_endian.h" - -__dev16 gdm_cpu_to_dev16(u8 dev_ed, u16 x) -{ - if (dev_ed == ENDIANNESS_LITTLE) - return (__force __dev16)cpu_to_le16(x); - else - return (__force __dev16)cpu_to_be16(x); -} - -u16 gdm_dev16_to_cpu(u8 dev_ed, __dev16 x) -{ - if (dev_ed == ENDIANNESS_LITTLE) - return le16_to_cpu((__force __le16)x); - else - return be16_to_cpu((__force __be16)x); -} - -__dev32 gdm_cpu_to_dev32(u8 dev_ed, u32 x) -{ - if (dev_ed == ENDIANNESS_LITTLE) - return (__force __dev32)cpu_to_le32(x); - else - return (__force __dev32)cpu_to_be32(x); -} - -u32 gdm_dev32_to_cpu(u8 dev_ed, __dev32 x) -{ - if (dev_ed == ENDIANNESS_LITTLE) - return le32_to_cpu((__force __le32)x); - else - return be32_to_cpu((__force __be32)x); -} diff --git a/drivers/staging/gdm724x/gdm_endian.h b/drivers/staging/gdm724x/gdm_endian.h deleted file mode 100644 index f373dc3a19bf3e779ad41749cd0605d52ab874a3..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_endian.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef __GDM_ENDIAN_H__ -#define __GDM_ENDIAN_H__ - -#include <linux/types.h> - -/* - * For data in "device-endian" byte order (device endianness is model - * dependent). Analogous to __leXX or __beXX. - */ -typedef __u32 __bitwise __dev32; -typedef __u16 __bitwise __dev16; - -enum { - ENDIANNESS_MIN = 0, - ENDIANNESS_UNKNOWN, - ENDIANNESS_LITTLE, - ENDIANNESS_BIG, - ENDIANNESS_MIDDLE, - ENDIANNESS_MAX -}; - -__dev16 gdm_cpu_to_dev16(u8 dev_ed, u16 x); -u16 gdm_dev16_to_cpu(u8 dev_ed, __dev16 x); -__dev32 gdm_cpu_to_dev32(u8 dev_ed, u32 x); -u32 gdm_dev32_to_cpu(u8 dev_ed, __dev32 x); - -#endif /*__GDM_ENDIAN_H__*/ diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c deleted file mode 100644 index eb754b231429be1aed1ba06052a93e0b4af9f632..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_lte.c +++ /dev/null @@ -1,937 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/etherdevice.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <linux/udp.h> -#include <linux/in.h> -#include <linux/if_arp.h> -#include <linux/if_ether.h> -#include <linux/if_vlan.h> -#include <linux/in6.h> -#include <linux/tcp.h> -#include <linux/icmp.h> -#include <linux/icmpv6.h> -#include <linux/uaccess.h> -#include <linux/errno.h> -#include <net/ndisc.h> - -#include "gdm_lte.h" -#include "netlink_k.h" -#include "hci.h" -#include "hci_packet.h" -#include "gdm_endian.h" - -/* - * Netlink protocol number - */ -#define NETLINK_LTE 30 - -/* - * Default MTU Size - */ -#define DEFAULT_MTU_SIZE 1500 - -#define IP_VERSION_4 4 -#define IP_VERSION_6 6 - -static struct { - int ref_cnt; - struct sock *sock; -} lte_event; - -static const struct device_type wwan_type = { - .name = "wwan", -}; - -static int gdm_lte_open(struct net_device *dev) -{ - netif_start_queue(dev); - return 0; -} - -static int gdm_lte_close(struct net_device *dev) -{ - netif_stop_queue(dev); - return 0; -} - -static int gdm_lte_set_config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) - return -EBUSY; - return 0; -} - -static void tx_complete(void *arg) -{ - struct nic *nic = arg; - - if (netif_queue_stopped(nic->netdev)) - netif_wake_queue(nic->netdev); -} - -static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type) -{ - int ret, len; - - len = skb->len + ETH_HLEN; - ret = netif_rx(skb); - if (ret == NET_RX_DROP) { - nic->stats.rx_dropped++; - } else { - nic->stats.rx_packets++; - nic->stats.rx_bytes += len; - } - - return 0; -} - -static int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type) -{ - struct nic *nic = netdev_priv(skb_in->dev); - struct sk_buff *skb_out; - struct ethhdr eth; - struct vlan_ethhdr vlan_eth; - struct arphdr *arp_in; - struct arphdr *arp_out; - struct arpdata { - u8 ar_sha[ETH_ALEN]; - u8 ar_sip[4]; - u8 ar_tha[ETH_ALEN]; - u8 ar_tip[4]; - }; - struct arpdata *arp_data_in; - struct arpdata *arp_data_out; - u8 arp_temp[60]; - void *mac_header_data; - u32 mac_header_len; - - /* Check for skb->len, discard if empty */ - if (skb_in->len == 0) - return -ENODATA; - - /* Format the mac header so that it can be put to skb */ - if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) { - memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr)); - mac_header_data = &vlan_eth; - mac_header_len = VLAN_ETH_HLEN; - } else { - memcpy(ð, skb_in->data, sizeof(struct ethhdr)); - mac_header_data = ð - mac_header_len = ETH_HLEN; - } - - /* Get the pointer of the original request */ - arp_in = (struct arphdr *)(skb_in->data + mac_header_len); - arp_data_in = (struct arpdata *)(skb_in->data + mac_header_len + - sizeof(struct arphdr)); - - /* Get the pointer of the outgoing response */ - arp_out = (struct arphdr *)arp_temp; - arp_data_out = (struct arpdata *)(arp_temp + sizeof(struct arphdr)); - - /* Copy the arp header */ - memcpy(arp_out, arp_in, sizeof(struct arphdr)); - arp_out->ar_op = htons(ARPOP_REPLY); - - /* Copy the arp payload: based on 2 bytes of mac and fill the IP */ - arp_data_out->ar_sha[0] = arp_data_in->ar_sha[0]; - arp_data_out->ar_sha[1] = arp_data_in->ar_sha[1]; - memcpy(&arp_data_out->ar_sha[2], &arp_data_in->ar_tip[0], 4); - memcpy(&arp_data_out->ar_sip[0], &arp_data_in->ar_tip[0], 4); - memcpy(&arp_data_out->ar_tha[0], &arp_data_in->ar_sha[0], 6); - memcpy(&arp_data_out->ar_tip[0], &arp_data_in->ar_sip[0], 4); - - /* Fill the destination mac with source mac of the received packet */ - memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN); - /* Fill the source mac with nic's source mac */ - memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN); - - /* Alloc skb and reserve align */ - skb_out = dev_alloc_skb(skb_in->len); - if (!skb_out) - return -ENOMEM; - skb_reserve(skb_out, NET_IP_ALIGN); - - skb_put_data(skb_out, mac_header_data, mac_header_len); - skb_put_data(skb_out, arp_out, sizeof(struct arphdr)); - skb_put_data(skb_out, arp_data_out, sizeof(struct arpdata)); - - skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto; - skb_out->dev = skb_in->dev; - skb_reset_mac_header(skb_out); - skb_pull(skb_out, ETH_HLEN); - - gdm_lte_rx(skb_out, nic, nic_type); - - return 0; -} - -static __sum16 icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len) -{ - unsigned short *w; - __wsum sum = 0; - int i; - u16 pa; - - union { - struct { - u8 ph_src[16]; - u8 ph_dst[16]; - u32 ph_len; - u8 ph_zero[3]; - u8 ph_nxt; - } ph __packed; - u16 pa[20]; - } pseudo_header; - - memset(&pseudo_header, 0, sizeof(pseudo_header)); - memcpy(&pseudo_header.ph.ph_src, &ipv6->saddr.in6_u.u6_addr8, 16); - memcpy(&pseudo_header.ph.ph_dst, &ipv6->daddr.in6_u.u6_addr8, 16); - pseudo_header.ph.ph_len = be16_to_cpu(ipv6->payload_len); - pseudo_header.ph.ph_nxt = ipv6->nexthdr; - - for (i = 0; i < ARRAY_SIZE(pseudo_header.pa); i++) { - pa = pseudo_header.pa[i]; - sum = csum_add(sum, csum_unfold((__force __sum16)pa)); - } - - w = ptr; - while (len > 1) { - sum = csum_add(sum, csum_unfold((__force __sum16)*w++)); - len -= 2; - } - - return csum_fold(sum); -} - -static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type) -{ - struct nic *nic = netdev_priv(skb_in->dev); - struct sk_buff *skb_out; - struct ethhdr eth; - struct vlan_ethhdr vlan_eth; - struct neighbour_advertisement { - u8 target_address[16]; - u8 type; - u8 length; - u8 link_layer_address[6]; - }; - struct neighbour_advertisement na; - struct neighbour_solicitation { - u8 target_address[16]; - }; - struct neighbour_solicitation *ns; - struct ipv6hdr *ipv6_in; - struct ipv6hdr ipv6_out; - struct icmp6hdr *icmp6_in; - struct icmp6hdr icmp6_out; - - void *mac_header_data; - u32 mac_header_len; - - /* Format the mac header so that it can be put to skb */ - if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) { - memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr)); - if (ntohs(vlan_eth.h_vlan_encapsulated_proto) != ETH_P_IPV6) - return -EPROTONOSUPPORT; - mac_header_data = &vlan_eth; - mac_header_len = VLAN_ETH_HLEN; - } else { - memcpy(ð, skb_in->data, sizeof(struct ethhdr)); - if (ntohs(eth.h_proto) != ETH_P_IPV6) - return -EPROTONOSUPPORT; - mac_header_data = ð - mac_header_len = ETH_HLEN; - } - - /* Check if this is IPv6 ICMP packet */ - ipv6_in = (struct ipv6hdr *)(skb_in->data + mac_header_len); - if (ipv6_in->version != 6 || ipv6_in->nexthdr != IPPROTO_ICMPV6) - return -EPROTONOSUPPORT; - - /* Check if this is NDP packet */ - icmp6_in = (struct icmp6hdr *)(skb_in->data + mac_header_len + - sizeof(struct ipv6hdr)); - if (icmp6_in->icmp6_type == NDISC_ROUTER_SOLICITATION) { /* Check RS */ - return -EPROTONOSUPPORT; - } else if (icmp6_in->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { - /* Check NS */ - u8 icmp_na[sizeof(struct icmp6hdr) + - sizeof(struct neighbour_advertisement)]; - u8 zero_addr8[16] = {0,}; - - if (memcmp(ipv6_in->saddr.in6_u.u6_addr8, zero_addr8, 16) == 0) - /* Duplicate Address Detection: Source IP is all zero */ - return 0; - - icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; - icmp6_out.icmp6_code = 0; - icmp6_out.icmp6_cksum = 0; - /* R=0, S=1, O=1 */ - icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); - - ns = (struct neighbour_solicitation *) - (skb_in->data + mac_header_len + - sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr)); - memcpy(&na.target_address, ns->target_address, 16); - na.type = 0x02; - na.length = 1; - na.link_layer_address[0] = 0x00; - na.link_layer_address[1] = 0x0a; - na.link_layer_address[2] = 0x3b; - na.link_layer_address[3] = 0xaf; - na.link_layer_address[4] = 0x63; - na.link_layer_address[5] = 0xc7; - - memcpy(&ipv6_out, ipv6_in, sizeof(struct ipv6hdr)); - memcpy(ipv6_out.saddr.in6_u.u6_addr8, &na.target_address, 16); - memcpy(ipv6_out.daddr.in6_u.u6_addr8, - ipv6_in->saddr.in6_u.u6_addr8, 16); - ipv6_out.payload_len = htons(sizeof(struct icmp6hdr) + - sizeof(struct neighbour_advertisement)); - - memcpy(icmp_na, &icmp6_out, sizeof(struct icmp6hdr)); - memcpy(icmp_na + sizeof(struct icmp6hdr), &na, - sizeof(struct neighbour_advertisement)); - - icmp6_out.icmp6_cksum = icmp6_checksum(&ipv6_out, - (u16 *)icmp_na, - sizeof(icmp_na)); - } else { - return -EINVAL; - } - - /* Fill the destination mac with source mac of the received packet */ - memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN); - /* Fill the source mac with nic's source mac */ - memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN); - - /* Alloc skb and reserve align */ - skb_out = dev_alloc_skb(skb_in->len); - if (!skb_out) - return -ENOMEM; - skb_reserve(skb_out, NET_IP_ALIGN); - - skb_put_data(skb_out, mac_header_data, mac_header_len); - skb_put_data(skb_out, &ipv6_out, sizeof(struct ipv6hdr)); - skb_put_data(skb_out, &icmp6_out, sizeof(struct icmp6hdr)); - skb_put_data(skb_out, &na, sizeof(struct neighbour_advertisement)); - - skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto; - skb_out->dev = skb_in->dev; - skb_reset_mac_header(skb_out); - skb_pull(skb_out, ETH_HLEN); - - gdm_lte_rx(skb_out, nic, nic_type); - - return 0; -} - -static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb) -{ - struct nic *nic = netdev_priv(dev); - struct ethhdr *eth; - struct vlan_ethhdr *vlan_eth; - struct iphdr *ip; - struct ipv6hdr *ipv6; - int mac_proto; - void *network_data; - u32 nic_type; - - /* NIC TYPE is based on the nic_id of this net_device */ - nic_type = 0x00000010 | nic->nic_id; - - /* Get ethernet protocol */ - eth = (struct ethhdr *)skb->data; - if (ntohs(eth->h_proto) == ETH_P_8021Q) { - vlan_eth = skb_vlan_eth_hdr(skb); - mac_proto = ntohs(vlan_eth->h_vlan_encapsulated_proto); - network_data = skb->data + VLAN_ETH_HLEN; - nic_type |= NIC_TYPE_F_VLAN; - } else { - mac_proto = ntohs(eth->h_proto); - network_data = skb->data + ETH_HLEN; - } - - /* Process packet for nic type */ - switch (mac_proto) { - case ETH_P_ARP: - nic_type |= NIC_TYPE_ARP; - break; - case ETH_P_IP: - nic_type |= NIC_TYPE_F_IPV4; - ip = network_data; - - /* Check DHCPv4 */ - if (ip->protocol == IPPROTO_UDP) { - struct udphdr *udp = - network_data + sizeof(struct iphdr); - if (ntohs(udp->dest) == 67 || ntohs(udp->dest) == 68) - nic_type |= NIC_TYPE_F_DHCP; - } - break; - case ETH_P_IPV6: - nic_type |= NIC_TYPE_F_IPV6; - ipv6 = network_data; - - if (ipv6->nexthdr == IPPROTO_ICMPV6) /* Check NDP request */ { - struct icmp6hdr *icmp6 = - network_data + sizeof(struct ipv6hdr); - if (icmp6->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) - nic_type |= NIC_TYPE_ICMPV6; - } else if (ipv6->nexthdr == IPPROTO_UDP) /* Check DHCPv6 */ { - struct udphdr *udp = - network_data + sizeof(struct ipv6hdr); - if (ntohs(udp->dest) == 546 || ntohs(udp->dest) == 547) - nic_type |= NIC_TYPE_F_DHCP; - } - break; - default: - break; - } - - return nic_type; -} - -static netdev_tx_t gdm_lte_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - u32 nic_type; - void *data_buf; - int data_len; - int idx; - int ret = 0; - - nic_type = gdm_lte_tx_nic_type(dev, skb); - if (nic_type == 0) { - netdev_err(dev, "tx - invalid nic_type\n"); - return -EMEDIUMTYPE; - } - - if (nic_type & NIC_TYPE_ARP) { - if (gdm_lte_emulate_arp(skb, nic_type) == 0) { - dev_kfree_skb(skb); - return 0; - } - } - - if (nic_type & NIC_TYPE_ICMPV6) { - if (gdm_lte_emulate_ndp(skb, nic_type) == 0) { - dev_kfree_skb(skb); - return 0; - } - } - - /* - * Need byte shift (that is, remove VLAN tag) if there is one - * For the case of ARP, this breaks the offset as vlan_ethhdr+4 - * is treated as ethhdr However, it shouldn't be a problem as - * the response starts from arp_hdr and ethhdr is created by this - * driver based on the NIC mac - */ - if (nic_type & NIC_TYPE_F_VLAN) { - struct vlan_ethhdr *vlan_eth = skb_vlan_eth_hdr(skb); - - nic->vlan_id = ntohs(vlan_eth->h_vlan_TCI) & VLAN_VID_MASK; - data_buf = skb->data + (VLAN_ETH_HLEN - ETH_HLEN); - data_len = skb->len - (VLAN_ETH_HLEN - ETH_HLEN); - } else { - nic->vlan_id = 0; - data_buf = skb->data; - data_len = skb->len; - } - - /* If it is a ICMPV6 packet, clear all the other bits : - * for backward compatibility with the firmware - */ - if (nic_type & NIC_TYPE_ICMPV6) - nic_type = NIC_TYPE_ICMPV6; - - /* If it is not a dhcp packet, clear all the flag bits : - * original NIC, otherwise the special flag (IPVX | DHCP) - */ - if (!(nic_type & NIC_TYPE_F_DHCP)) - nic_type &= NIC_TYPE_MASK; - - ret = sscanf(dev->name, "lte%d", &idx); - if (ret != 1) { - dev_kfree_skb(skb); - return -EINVAL; - } - - ret = nic->phy_dev->send_sdu_func(nic->phy_dev->priv_dev, - data_buf, data_len, - nic->pdn_table.dft_eps_id, 0, - tx_complete, nic, idx, - nic_type); - - if (ret == TX_NO_BUFFER || ret == TX_NO_SPC) { - netif_stop_queue(dev); - if (ret == TX_NO_BUFFER) - ret = 0; - else - ret = -ENOSPC; - } else if (ret == TX_NO_DEV) { - ret = -ENODEV; - } - - /* Updates tx stats */ - if (ret) { - nic->stats.tx_dropped++; - } else { - nic->stats.tx_packets++; - nic->stats.tx_bytes += data_len; - } - dev_kfree_skb(skb); - - return 0; -} - -static struct net_device_stats *gdm_lte_stats(struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - - return &nic->stats; -} - -static int gdm_lte_event_send(struct net_device *dev, char *buf, int len) -{ - struct phy_dev *phy_dev = ((struct nic *)netdev_priv(dev))->phy_dev; - struct hci_packet *hci = (struct hci_packet *)buf; - int length; - int idx; - int ret; - - ret = sscanf(dev->name, "lte%d", &idx); - if (ret != 1) - return -EINVAL; - - length = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), - hci->len) + HCI_HEADER_SIZE; - return netlink_send(lte_event.sock, idx, 0, buf, length, dev); -} - -static void gdm_lte_event_rcv(struct net_device *dev, u16 type, - void *msg, int len) -{ - struct nic *nic = netdev_priv(dev); - - nic->phy_dev->send_hci_func(nic->phy_dev->priv_dev, msg, len, NULL, - NULL); -} - -int gdm_lte_event_init(void) -{ - if (lte_event.ref_cnt == 0) - lte_event.sock = netlink_init(NETLINK_LTE, gdm_lte_event_rcv); - - if (lte_event.sock) { - lte_event.ref_cnt++; - return 0; - } - - pr_err("event init failed\n"); - return -ENODATA; -} - -void gdm_lte_event_exit(void) -{ - if (lte_event.sock && --lte_event.ref_cnt == 0) { - sock_release(lte_event.sock->sk_socket); - lte_event.sock = NULL; - } -} - -static int find_dev_index(u32 nic_type) -{ - u8 index; - - index = (u8)(nic_type & 0x0000000f); - if (index >= MAX_NIC_TYPE) - return -EINVAL; - - return index; -} - -static void gdm_lte_netif_rx(struct net_device *dev, char *buf, - int len, int flagged_nic_type) -{ - u32 nic_type; - struct nic *nic; - struct sk_buff *skb; - struct ethhdr eth; - struct vlan_ethhdr vlan_eth; - void *mac_header_data; - u32 mac_header_len; - char ip_version = 0; - - nic_type = flagged_nic_type & NIC_TYPE_MASK; - nic = netdev_priv(dev); - - if (flagged_nic_type & NIC_TYPE_F_DHCP) { - /* Change the destination mac address - * with the one requested the IP - */ - if (flagged_nic_type & NIC_TYPE_F_IPV4) { - struct dhcp_packet { - u8 op; /* BOOTREQUEST or BOOTREPLY */ - u8 htype; /* hardware address type. - * 1 = 10mb ethernet - */ - u8 hlen; /* hardware address length */ - u8 hops; /* used by relay agents only */ - u32 xid; /* unique id */ - u16 secs; /* elapsed since client began - * acquisition/renewal - */ - u16 flags; /* only one flag so far: */ - #define BROADCAST_FLAG 0x8000 - /* "I need broadcast replies" */ - u32 ciaddr; /* client IP (if client is in - * BOUND, RENEW or REBINDING state) - */ - u32 yiaddr; /* 'your' (client) IP address */ - /* IP address of next server to use in - * bootstrap, returned in DHCPOFFER, - * DHCPACK by server - */ - u32 siaddr_nip; - u32 gateway_nip; /* relay agent IP address */ - u8 chaddr[16]; /* link-layer client hardware - * address (MAC) - */ - u8 sname[64]; /* server host name (ASCIZ) */ - u8 file[128]; /* boot file name (ASCIZ) */ - u32 cookie; /* fixed first four option - * bytes (99,130,83,99 dec) - */ - } __packed; - int offset = sizeof(struct iphdr) + - sizeof(struct udphdr) + - offsetof(struct dhcp_packet, chaddr); - if (offset + ETH_ALEN > len) - return; - ether_addr_copy(nic->dest_mac_addr, buf + offset); - } - } - - if (nic->vlan_id > 0) { - mac_header_data = (void *)&vlan_eth; - mac_header_len = VLAN_ETH_HLEN; - } else { - mac_header_data = (void *)ð - mac_header_len = ETH_HLEN; - } - - /* Format the data so that it can be put to skb */ - ether_addr_copy(mac_header_data, nic->dest_mac_addr); - memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN); - - vlan_eth.h_vlan_TCI = htons(nic->vlan_id); - vlan_eth.h_vlan_proto = htons(ETH_P_8021Q); - - if (nic_type == NIC_TYPE_ARP) { - /* Should be response: Only happens because - * there was a request from the host - */ - eth.h_proto = htons(ETH_P_ARP); - vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_ARP); - } else { - ip_version = buf[0] >> 4; - if (ip_version == IP_VERSION_4) { - eth.h_proto = htons(ETH_P_IP); - vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IP); - } else if (ip_version == IP_VERSION_6) { - eth.h_proto = htons(ETH_P_IPV6); - vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IPV6); - } else { - netdev_err(dev, "Unknown IP version %d\n", ip_version); - return; - } - } - - /* Alloc skb and reserve align */ - skb = dev_alloc_skb(len + mac_header_len + NET_IP_ALIGN); - if (!skb) - return; - skb_reserve(skb, NET_IP_ALIGN); - - skb_put_data(skb, mac_header_data, mac_header_len); - skb_put_data(skb, buf, len); - - skb->protocol = ((struct ethhdr *)mac_header_data)->h_proto; - skb->dev = dev; - skb_reset_mac_header(skb); - skb_pull(skb, ETH_HLEN); - - gdm_lte_rx(skb, nic, nic_type); -} - -static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) -{ - struct net_device *dev; - struct multi_sdu *multi_sdu = (struct multi_sdu *)buf; - struct sdu *sdu = NULL; - u8 endian = phy_dev->get_endian(phy_dev->priv_dev); - u8 *data = (u8 *)multi_sdu->data; - int copied; - u16 i = 0; - u16 num_packet; - u16 hci_len; - u16 cmd_evt; - u32 nic_type; - int index; - - num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet); - - for (i = 0; i < num_packet; i++) { - copied = data - multi_sdu->data; - if (len < copied + sizeof(*sdu)) { - pr_err("rx prevent buffer overflow"); - return; - } - - sdu = (struct sdu *)data; - - cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt); - hci_len = gdm_dev16_to_cpu(endian, sdu->len); - nic_type = gdm_dev32_to_cpu(endian, sdu->nic_type); - - if (cmd_evt != LTE_RX_SDU) { - pr_err("rx sdu wrong hci %04x\n", cmd_evt); - return; - } - if (hci_len < 12 || - len < copied + sizeof(*sdu) + (hci_len - 12)) { - pr_err("rx sdu invalid len %d\n", hci_len); - return; - } - - index = find_dev_index(nic_type); - if (index < 0) { - pr_err("rx sdu invalid nic_type :%x\n", nic_type); - return; - } - dev = phy_dev->dev[index]; - gdm_lte_netif_rx(dev, (char *)sdu->data, - (int)(hci_len - 12), nic_type); - - data += ((hci_len + 3) & 0xfffc) + HCI_HEADER_SIZE; - } -} - -static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len) -{ - struct nic *nic = netdev_priv(dev); - struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf; - u8 ed = nic->phy_dev->get_endian(nic->phy_dev->priv_dev); - - if (!pdn_table->activate) { - memset(&nic->pdn_table, 0x00, sizeof(struct pdn_table)); - netdev_info(dev, "pdn deactivated\n"); - - return; - } - - nic->pdn_table.activate = pdn_table->activate; - nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(ed, pdn_table->dft_eps_id); - nic->pdn_table.nic_type = gdm_dev32_to_cpu(ed, pdn_table->nic_type); - - netdev_info(dev, "pdn activated, nic_type=0x%x\n", - nic->pdn_table.nic_type); -} - -static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len) -{ - struct hci_packet *hci = (struct hci_packet *)buf; - struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf; - struct sdu *sdu; - struct net_device *dev; - u8 endian = phy_dev->get_endian(phy_dev->priv_dev); - int ret = 0; - u16 cmd_evt; - u32 nic_type; - int index; - - if (!len) - return ret; - - cmd_evt = gdm_dev16_to_cpu(endian, hci->cmd_evt); - - dev = phy_dev->dev[0]; - if (!dev) - return 0; - - switch (cmd_evt) { - case LTE_RX_SDU: - sdu = (struct sdu *)hci->data; - nic_type = gdm_dev32_to_cpu(endian, sdu->nic_type); - index = find_dev_index(nic_type); - if (index < 0) - return index; - dev = phy_dev->dev[index]; - gdm_lte_netif_rx(dev, hci->data, len, nic_type); - break; - case LTE_RX_MULTI_SDU: - gdm_lte_multi_sdu_pkt(phy_dev, buf, len); - break; - case LTE_LINK_ON_OFF_INDICATION: - netdev_info(dev, "link %s\n", - ((struct hci_connect_ind *)buf)->connect - ? "on" : "off"); - break; - case LTE_PDN_TABLE_IND: - pdn_table = (struct hci_pdn_table_ind *)buf; - nic_type = gdm_dev32_to_cpu(endian, pdn_table->nic_type); - index = find_dev_index(nic_type); - if (index < 0) - return index; - dev = phy_dev->dev[index]; - gdm_lte_pdn_table(dev, buf, len); - fallthrough; - default: - ret = gdm_lte_event_send(dev, buf, len); - break; - } - - return ret; -} - -static int rx_complete(void *arg, void *data, int len, int context) -{ - struct phy_dev *phy_dev = arg; - - return gdm_lte_receive_pkt(phy_dev, data, len); -} - -void start_rx_proc(struct phy_dev *phy_dev) -{ - int i; - - for (i = 0; i < MAX_RX_SUBMIT_COUNT; i++) - phy_dev->rcv_func(phy_dev->priv_dev, - rx_complete, phy_dev, USB_COMPLETE); -} - -static const struct net_device_ops gdm_netdev_ops = { - .ndo_open = gdm_lte_open, - .ndo_stop = gdm_lte_close, - .ndo_set_config = gdm_lte_set_config, - .ndo_start_xmit = gdm_lte_tx, - .ndo_get_stats = gdm_lte_stats, -}; - -static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00}; - -static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest, - u8 *mac_address, u8 index) -{ - /* Form the dev_addr */ - if (!mac_address) - ether_addr_copy(dev_addr, gdm_lte_macaddr); - else - ether_addr_copy(dev_addr, mac_address); - - /* The last byte of the mac address - * should be less than or equal to 0xFC - */ - dev_addr[ETH_ALEN - 1] += index; - - /* Create random nic src and copy the first - * 3 bytes to be the same as dev_addr - */ - eth_random_addr(nic_src); - memcpy(nic_src, dev_addr, 3); - - /* Copy the nic_dest from dev_addr*/ - ether_addr_copy(nic_dest, dev_addr); -} - -static void validate_mac_address(u8 *mac_address) -{ - /* if zero address or multicast bit set, restore the default value */ - if (is_zero_ether_addr(mac_address) || (mac_address[0] & 0x01)) { - pr_err("MAC invalid, restoring default\n"); - memcpy(mac_address, gdm_lte_macaddr, 6); - } -} - -int register_lte_device(struct phy_dev *phy_dev, - struct device *dev, u8 *mac_address) -{ - struct nic *nic; - struct net_device *net; - char pdn_dev_name[16]; - u8 addr[ETH_ALEN]; - int ret = 0; - u8 index; - - validate_mac_address(mac_address); - - for (index = 0; index < MAX_NIC_TYPE; index++) { - /* Create device name lteXpdnX */ - sprintf(pdn_dev_name, "lte%%dpdn%d", index); - - /* Allocate netdev */ - net = alloc_netdev(sizeof(struct nic), pdn_dev_name, - NET_NAME_UNKNOWN, ether_setup); - if (!net) { - ret = -ENOMEM; - goto err; - } - net->netdev_ops = &gdm_netdev_ops; - net->flags &= ~IFF_MULTICAST; - net->mtu = DEFAULT_MTU_SIZE; - - nic = netdev_priv(net); - memset(nic, 0, sizeof(struct nic)); - nic->netdev = net; - nic->phy_dev = phy_dev; - nic->nic_id = index; - - form_mac_address(addr, - nic->src_mac_addr, - nic->dest_mac_addr, - mac_address, - index); - eth_hw_addr_set(net, addr); - - SET_NETDEV_DEV(net, dev); - SET_NETDEV_DEVTYPE(net, &wwan_type); - - ret = register_netdev(net); - if (ret) - goto err; - - netif_carrier_on(net); - - phy_dev->dev[index] = net; - } - - return 0; - -err: - unregister_lte_device(phy_dev); - - return ret; -} - -void unregister_lte_device(struct phy_dev *phy_dev) -{ - struct net_device *net; - int index; - - for (index = 0; index < MAX_NIC_TYPE; index++) { - net = phy_dev->dev[index]; - if (!net) - continue; - - unregister_netdev(net); - free_netdev(net); - } -} diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h deleted file mode 100644 index f2143a6e0e990f1cef8c5f4ef14b90917931f4bc..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_lte.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _GDM_LTE_H_ -#define _GDM_LTE_H_ - -#include <linux/netdevice.h> -#include <linux/types.h> - -#include "gdm_endian.h" - -#define MAX_NIC_TYPE 4 -#define MAX_RX_SUBMIT_COUNT 3 -#define DRIVER_VERSION "3.7.17.0" - -enum TX_ERROR_CODE { - TX_NO_ERROR = 0, - TX_NO_DEV, - TX_NO_SPC, - TX_NO_BUFFER, -}; - -enum CALLBACK_CONTEXT { - KERNEL_THREAD = 0, - USB_COMPLETE, -}; - -struct pdn_table { - u8 activate; - u32 dft_eps_id; - u32 nic_type; -} __packed; - -struct nic; - -struct phy_dev { - void *priv_dev; - struct net_device *dev[MAX_NIC_TYPE]; - int (*send_hci_func)(void *priv_dev, void *data, int len, - void (*cb)(void *cb_data), void *cb_data); - int (*send_sdu_func)(void *priv_dev, void *data, int len, - unsigned int dft_eps_id, unsigned int eps_id, - void (*cb)(void *cb_data), void *cb_data, - int dev_idx, int nic_type); - int (*rcv_func)(void *priv_dev, - int (*cb)(void *cb_data, void *data, int len, - int context), - void *cb_data, int context); - u8 (*get_endian)(void *priv_dev); -}; - -struct nic { - struct net_device *netdev; - struct phy_dev *phy_dev; - struct net_device_stats stats; - struct pdn_table pdn_table; - u8 dest_mac_addr[ETH_ALEN]; - u8 src_mac_addr[ETH_ALEN]; - u32 nic_id; - u16 vlan_id; -}; - -int gdm_lte_event_init(void); -void gdm_lte_event_exit(void); - -void start_rx_proc(struct phy_dev *phy_dev); -int register_lte_device(struct phy_dev *phy_dev, struct device *dev, - u8 *mac_address); -void unregister_lte_device(struct phy_dev *phy_dev); - -#endif /* _GDM_LTE_H_ */ diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c deleted file mode 100644 index 9b12619671a13ec4b2ecc140ed830aeeb182bc54..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_mux.c +++ /dev/null @@ -1,668 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/slab.h> -#include <linux/usb/cdc.h> - -#include "gdm_mux.h" - -static u16 packet_type_for_tty_index[TTY_MAX_COUNT] = {0xF011, 0xF010}; - -#define USB_DEVICE_CDC_DATA(vid, pid) \ - .match_flags = \ - USB_DEVICE_ID_MATCH_DEVICE |\ - USB_DEVICE_ID_MATCH_INT_CLASS |\ - USB_DEVICE_ID_MATCH_INT_SUBCLASS,\ - .idVendor = vid,\ - .idProduct = pid,\ - .bInterfaceClass = USB_CLASS_COMM,\ - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM - -static const struct usb_device_id id_table[] = { - { USB_DEVICE_CDC_DATA(0x1076, 0x8000) }, /* GCT GDM7240 */ - { USB_DEVICE_CDC_DATA(0x1076, 0x8f00) }, /* GCT GDM7243 */ - { USB_DEVICE_CDC_DATA(0x1076, 0x9000) }, /* GCT GDM7243 */ - { USB_DEVICE_CDC_DATA(0x1d74, 0x2300) }, /* LGIT Phoenix */ - {} -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static int packet_type_to_tty_index(u16 packet_type) -{ - int i; - - for (i = 0; i < TTY_MAX_COUNT; i++) { - if (packet_type_for_tty_index[i] == packet_type) - return i; - } - - return -1; -} - -static struct mux_tx *alloc_mux_tx(int len) -{ - struct mux_tx *t; - - t = kzalloc(sizeof(*t), GFP_ATOMIC); - if (!t) - return NULL; - - t->urb = usb_alloc_urb(0, GFP_ATOMIC); - t->buf = kmalloc(MUX_TX_MAX_SIZE, GFP_ATOMIC); - if (!t->urb || !t->buf) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - return NULL; - } - - return t; -} - -static void free_mux_tx(struct mux_tx *t) -{ - if (t) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - } -} - -static struct mux_rx *alloc_mux_rx(void) -{ - struct mux_rx *r; - - r = kzalloc(sizeof(*r), GFP_KERNEL); - if (!r) - return NULL; - - r->urb = usb_alloc_urb(0, GFP_KERNEL); - r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_KERNEL); - if (!r->urb || !r->buf) { - usb_free_urb(r->urb); - kfree(r->buf); - kfree(r); - return NULL; - } - - return r; -} - -static void free_mux_rx(struct mux_rx *r) -{ - if (r) { - usb_free_urb(r->urb); - kfree(r->buf); - kfree(r); - } -} - -static struct mux_rx *get_rx_struct(struct rx_cxt *rx) -{ - struct mux_rx *r; - unsigned long flags; - - spin_lock_irqsave(&rx->free_list_lock, flags); - - if (list_empty(&rx->rx_free_list)) { - spin_unlock_irqrestore(&rx->free_list_lock, flags); - return NULL; - } - - r = list_entry(rx->rx_free_list.prev, struct mux_rx, free_list); - list_del(&r->free_list); - - spin_unlock_irqrestore(&rx->free_list_lock, flags); - - return r; -} - -static void put_rx_struct(struct rx_cxt *rx, struct mux_rx *r) -{ - unsigned long flags; - - spin_lock_irqsave(&rx->free_list_lock, flags); - list_add_tail(&r->free_list, &rx->rx_free_list); - spin_unlock_irqrestore(&rx->free_list_lock, flags); -} - -static int up_to_host(struct mux_rx *r) -{ - struct mux_dev *mux_dev = r->mux_dev; - struct mux_pkt_header *mux_header; - unsigned int start_flag; - unsigned int payload_size; - unsigned short packet_type; - int total_len; - u32 packet_size_sum = r->offset; - int index; - int ret = TO_HOST_INVALID_PACKET; - int len = r->len; - - while (1) { - mux_header = (struct mux_pkt_header *)(r->buf + - packet_size_sum); - start_flag = __le32_to_cpu(mux_header->start_flag); - payload_size = __le32_to_cpu(mux_header->payload_size); - packet_type = __le16_to_cpu(mux_header->packet_type); - - if (start_flag != START_FLAG) { - pr_err("invalid START_FLAG %x\n", start_flag); - break; - } - - total_len = ALIGN(MUX_HEADER_SIZE + payload_size, 4); - - if (len - packet_size_sum < total_len) { - pr_err("invalid payload : %d %d %04x\n", - payload_size, len, packet_type); - break; - } - - index = packet_type_to_tty_index(packet_type); - if (index < 0) { - pr_err("invalid index %d\n", index); - break; - } - - ret = r->callback(mux_header->data, - payload_size, - index, - mux_dev->tty_dev, - RECV_PACKET_PROCESS_CONTINUE - ); - if (ret == TO_HOST_BUFFER_REQUEST_FAIL) { - r->offset += packet_size_sum; - break; - } - - packet_size_sum += total_len; - if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) { - ret = r->callback(NULL, - 0, - index, - mux_dev->tty_dev, - RECV_PACKET_PROCESS_COMPLETE - ); - break; - } - } - - return ret; -} - -static void do_rx(struct work_struct *work) -{ - struct mux_dev *mux_dev = - container_of(work, struct mux_dev, work_rx.work); - struct mux_rx *r; - struct rx_cxt *rx = &mux_dev->rx; - unsigned long flags; - int ret = 0; - - while (1) { - spin_lock_irqsave(&rx->to_host_lock, flags); - if (list_empty(&rx->to_host_list)) { - spin_unlock_irqrestore(&rx->to_host_lock, flags); - break; - } - r = list_entry(rx->to_host_list.next, struct mux_rx, - to_host_list); - list_del(&r->to_host_list); - spin_unlock_irqrestore(&rx->to_host_lock, flags); - - ret = up_to_host(r); - if (ret == TO_HOST_BUFFER_REQUEST_FAIL) - pr_err("failed to send mux data to host\n"); - else - put_rx_struct(rx, r); - } -} - -static void remove_rx_submit_list(struct mux_rx *r, struct rx_cxt *rx) -{ - unsigned long flags; - struct mux_rx *r_remove, *r_remove_next; - - spin_lock_irqsave(&rx->submit_list_lock, flags); - list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list, - rx_submit_list) { - if (r == r_remove) - list_del(&r->rx_submit_list); - } - spin_unlock_irqrestore(&rx->submit_list_lock, flags); -} - -static void gdm_mux_rcv_complete(struct urb *urb) -{ - struct mux_rx *r = urb->context; - struct mux_dev *mux_dev = r->mux_dev; - struct rx_cxt *rx = &mux_dev->rx; - unsigned long flags; - - remove_rx_submit_list(r, rx); - - if (urb->status) { - if (mux_dev->usb_state == PM_NORMAL) - dev_err(&urb->dev->dev, "%s: urb status error %d\n", - __func__, urb->status); - put_rx_struct(rx, r); - } else { - r->len = r->urb->actual_length; - spin_lock_irqsave(&rx->to_host_lock, flags); - list_add_tail(&r->to_host_list, &rx->to_host_list); - schedule_work(&mux_dev->work_rx.work); - spin_unlock_irqrestore(&rx->to_host_lock, flags); - } -} - -static int gdm_mux_recv(void *priv_dev, - int (*cb)(void *data, int len, int tty_index, - struct tty_dev *tty_dev, int complete)) -{ - struct mux_dev *mux_dev = priv_dev; - struct usb_device *usbdev = mux_dev->usbdev; - struct mux_rx *r; - struct rx_cxt *rx = &mux_dev->rx; - unsigned long flags; - int ret; - - if (!usbdev) { - pr_err("device is disconnected\n"); - return -ENODEV; - } - - r = get_rx_struct(rx); - if (!r) { - pr_err("get_rx_struct fail\n"); - return -ENOMEM; - } - - r->offset = 0; - r->mux_dev = (void *)mux_dev; - r->callback = cb; - mux_dev->rx_cb = cb; - - usb_fill_bulk_urb(r->urb, - usbdev, - usb_rcvbulkpipe(usbdev, 0x86), - r->buf, - MUX_RX_MAX_SIZE, - gdm_mux_rcv_complete, - r); - - spin_lock_irqsave(&rx->submit_list_lock, flags); - list_add_tail(&r->rx_submit_list, &rx->rx_submit_list); - spin_unlock_irqrestore(&rx->submit_list_lock, flags); - - ret = usb_submit_urb(r->urb, GFP_KERNEL); - - if (ret) { - spin_lock_irqsave(&rx->submit_list_lock, flags); - list_del(&r->rx_submit_list); - spin_unlock_irqrestore(&rx->submit_list_lock, flags); - - put_rx_struct(rx, r); - - pr_err("usb_submit_urb ret=%d\n", ret); - } - - usb_mark_last_busy(usbdev); - - return ret; -} - -static void gdm_mux_send_complete(struct urb *urb) -{ - struct mux_tx *t = urb->context; - - if (urb->status == -ECONNRESET) { - dev_info(&urb->dev->dev, "CONNRESET\n"); - free_mux_tx(t); - return; - } - - if (t->callback) - t->callback(t->cb_data); - - free_mux_tx(t); -} - -static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, - void (*cb)(void *data), void *cb_data) -{ - struct mux_dev *mux_dev = priv_dev; - struct usb_device *usbdev = mux_dev->usbdev; - struct mux_pkt_header *mux_header; - struct mux_tx *t = NULL; - static u32 seq_num = 1; - int total_len; - int ret; - unsigned long flags; - - if (mux_dev->usb_state == PM_SUSPEND) { - ret = usb_autopm_get_interface(mux_dev->intf); - if (!ret) - usb_autopm_put_interface(mux_dev->intf); - } - - spin_lock_irqsave(&mux_dev->write_lock, flags); - - total_len = ALIGN(MUX_HEADER_SIZE + len, 4); - - t = alloc_mux_tx(total_len); - if (!t) { - pr_err("alloc_mux_tx fail\n"); - spin_unlock_irqrestore(&mux_dev->write_lock, flags); - return -ENOMEM; - } - - mux_header = (struct mux_pkt_header *)t->buf; - mux_header->start_flag = __cpu_to_le32(START_FLAG); - mux_header->seq_num = __cpu_to_le32(seq_num++); - mux_header->payload_size = __cpu_to_le32((u32)len); - mux_header->packet_type = __cpu_to_le16(packet_type_for_tty_index[tty_index]); - - memcpy(t->buf + MUX_HEADER_SIZE, data, len); - memset(t->buf + MUX_HEADER_SIZE + len, 0, - total_len - MUX_HEADER_SIZE - len); - - t->len = total_len; - t->callback = cb; - t->cb_data = cb_data; - - usb_fill_bulk_urb(t->urb, - usbdev, - usb_sndbulkpipe(usbdev, 5), - t->buf, - total_len, - gdm_mux_send_complete, - t); - - ret = usb_submit_urb(t->urb, GFP_ATOMIC); - - spin_unlock_irqrestore(&mux_dev->write_lock, flags); - - if (ret) - pr_err("usb_submit_urb Error: %d\n", ret); - - usb_mark_last_busy(usbdev); - - return ret; -} - -static int gdm_mux_send_control(void *priv_dev, int request, int value, - void *buf, int len) -{ - struct mux_dev *mux_dev = priv_dev; - struct usb_device *usbdev = mux_dev->usbdev; - int ret; - - ret = usb_control_msg(usbdev, - usb_sndctrlpipe(usbdev, 0), - request, - USB_RT_ACM, - value, - 2, - buf, - len, - 5000 - ); - - if (ret < 0) - pr_err("usb_control_msg error: %d\n", ret); - - return min(ret, 0); -} - -static void release_usb(struct mux_dev *mux_dev) -{ - struct rx_cxt *rx = &mux_dev->rx; - struct mux_rx *r, *r_next; - unsigned long flags; - - cancel_delayed_work(&mux_dev->work_rx); - - spin_lock_irqsave(&rx->submit_list_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, - rx_submit_list) { - spin_unlock_irqrestore(&rx->submit_list_lock, flags); - usb_kill_urb(r->urb); - spin_lock_irqsave(&rx->submit_list_lock, flags); - } - spin_unlock_irqrestore(&rx->submit_list_lock, flags); - - spin_lock_irqsave(&rx->free_list_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->rx_free_list, free_list) { - list_del(&r->free_list); - free_mux_rx(r); - } - spin_unlock_irqrestore(&rx->free_list_lock, flags); - - spin_lock_irqsave(&rx->to_host_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) { - if (r->mux_dev == (void *)mux_dev) { - list_del(&r->to_host_list); - free_mux_rx(r); - } - } - spin_unlock_irqrestore(&rx->to_host_lock, flags); -} - -static int init_usb(struct mux_dev *mux_dev) -{ - struct mux_rx *r; - struct rx_cxt *rx = &mux_dev->rx; - int ret = 0; - int i; - - spin_lock_init(&mux_dev->write_lock); - INIT_LIST_HEAD(&rx->to_host_list); - INIT_LIST_HEAD(&rx->rx_submit_list); - INIT_LIST_HEAD(&rx->rx_free_list); - spin_lock_init(&rx->to_host_lock); - spin_lock_init(&rx->submit_list_lock); - spin_lock_init(&rx->free_list_lock); - - for (i = 0; i < MAX_ISSUE_NUM * 2; i++) { - r = alloc_mux_rx(); - if (!r) { - ret = -ENOMEM; - break; - } - - list_add(&r->free_list, &rx->rx_free_list); - } - - INIT_DELAYED_WORK(&mux_dev->work_rx, do_rx); - - return ret; -} - -static int gdm_mux_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct mux_dev *mux_dev; - struct tty_dev *tty_dev; - u16 idVendor, idProduct; - int bInterfaceNumber; - int ret; - int i; - struct usb_device *usbdev = interface_to_usbdev(intf); - - bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; - - idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); - idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); - - pr_info("mux vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct); - - if (bInterfaceNumber != 2) - return -ENODEV; - - mux_dev = kzalloc(sizeof(*mux_dev), GFP_KERNEL); - if (!mux_dev) - return -ENOMEM; - - tty_dev = kzalloc(sizeof(*tty_dev), GFP_KERNEL); - if (!tty_dev) { - ret = -ENOMEM; - goto err_free_mux; - } - - mux_dev->usbdev = usbdev; - mux_dev->control_intf = intf; - - ret = init_usb(mux_dev); - if (ret) - goto err_free_usb; - - tty_dev->priv_dev = (void *)mux_dev; - tty_dev->send_func = gdm_mux_send; - tty_dev->recv_func = gdm_mux_recv; - tty_dev->send_control = gdm_mux_send_control; - - ret = register_lte_tty_device(tty_dev, &intf->dev); - if (ret) - goto err_unregister_tty; - - for (i = 0; i < TTY_MAX_COUNT; i++) - mux_dev->tty_dev = tty_dev; - - mux_dev->intf = intf; - mux_dev->usb_state = PM_NORMAL; - - usb_get_dev(usbdev); - usb_set_intfdata(intf, tty_dev); - - return 0; - -err_unregister_tty: - unregister_lte_tty_device(tty_dev); -err_free_usb: - release_usb(mux_dev); - kfree(tty_dev); -err_free_mux: - kfree(mux_dev); - - return ret; -} - -static void gdm_mux_disconnect(struct usb_interface *intf) -{ - struct tty_dev *tty_dev; - struct mux_dev *mux_dev; - struct usb_device *usbdev = interface_to_usbdev(intf); - - tty_dev = usb_get_intfdata(intf); - - mux_dev = tty_dev->priv_dev; - - release_usb(mux_dev); - unregister_lte_tty_device(tty_dev); - - kfree(mux_dev); - kfree(tty_dev); - - usb_put_dev(usbdev); -} - -static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg) -{ - struct tty_dev *tty_dev; - struct mux_dev *mux_dev; - struct rx_cxt *rx; - struct mux_rx *r, *r_next; - unsigned long flags; - - tty_dev = usb_get_intfdata(intf); - mux_dev = tty_dev->priv_dev; - rx = &mux_dev->rx; - - cancel_work_sync(&mux_dev->work_rx.work); - - if (mux_dev->usb_state != PM_NORMAL) { - dev_err(intf->usb_dev, "usb suspend - invalid state\n"); - return -1; - } - - mux_dev->usb_state = PM_SUSPEND; - - spin_lock_irqsave(&rx->submit_list_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, - rx_submit_list) { - spin_unlock_irqrestore(&rx->submit_list_lock, flags); - usb_kill_urb(r->urb); - spin_lock_irqsave(&rx->submit_list_lock, flags); - } - spin_unlock_irqrestore(&rx->submit_list_lock, flags); - - return 0; -} - -static int gdm_mux_resume(struct usb_interface *intf) -{ - struct tty_dev *tty_dev; - struct mux_dev *mux_dev; - u8 i; - - tty_dev = usb_get_intfdata(intf); - mux_dev = tty_dev->priv_dev; - - if (mux_dev->usb_state != PM_SUSPEND) { - dev_err(intf->usb_dev, "usb resume - invalid state\n"); - return -1; - } - - mux_dev->usb_state = PM_NORMAL; - - for (i = 0; i < MAX_ISSUE_NUM; i++) - gdm_mux_recv(mux_dev, mux_dev->rx_cb); - - return 0; -} - -static struct usb_driver gdm_mux_driver = { - .name = "gdm_mux", - .probe = gdm_mux_probe, - .disconnect = gdm_mux_disconnect, - .id_table = id_table, - .supports_autosuspend = 1, - .suspend = gdm_mux_suspend, - .resume = gdm_mux_resume, - .reset_resume = gdm_mux_resume, -}; - -static int __init gdm_usb_mux_init(void) -{ - int ret; - - ret = register_lte_tty_driver(); - if (ret) - return ret; - - return usb_register(&gdm_mux_driver); -} - -static void __exit gdm_usb_mux_exit(void) -{ - usb_deregister(&gdm_mux_driver); - unregister_lte_tty_driver(); -} - -module_init(gdm_usb_mux_init); -module_exit(gdm_usb_mux_exit); - -MODULE_DESCRIPTION("GCT LTE TTY Device Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h deleted file mode 100644 index 87b8d921fdc822208df7508158d699c40bea1c42..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_mux.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _GDM_MUX_H_ -#define _GDM_MUX_H_ - -#include <linux/types.h> -#include <linux/usb.h> -#include <linux/list.h> - -#include "gdm_tty.h" - -#define PM_NORMAL 0 -#define PM_SUSPEND 1 - -#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) - -#define START_FLAG 0xA512485A -#define MUX_HEADER_SIZE 14 -#define MUX_TX_MAX_SIZE (1024 * 10) -#define MUX_RX_MAX_SIZE (1024 * 30) -#define AT_PKT_TYPE 0xF011 -#define DM_PKT_TYPE 0xF010 - -#define RETRY_TIMER 30 /* msec */ - -struct mux_pkt_header { - __le32 start_flag; - __le32 seq_num; - __le32 payload_size; - __le16 packet_type; - unsigned char data[]; -}; - -struct mux_tx { - struct urb *urb; - u8 *buf; - int len; - void (*callback)(void *cb_data); - void *cb_data; -}; - -struct mux_rx { - struct list_head free_list; - struct list_head rx_submit_list; - struct list_head to_host_list; - struct urb *urb; - u8 *buf; - void *mux_dev; - u32 offset; - u32 len; - int (*callback)(void *data, - int len, - int tty_index, - struct tty_dev *tty_dev, - int complete); -}; - -struct rx_cxt { - struct list_head to_host_list; - struct list_head rx_submit_list; - struct list_head rx_free_list; - spinlock_t to_host_lock; - spinlock_t submit_list_lock; - spinlock_t free_list_lock; -}; - -struct mux_dev { - struct usb_device *usbdev; - struct usb_interface *control_intf; - struct usb_interface *data_intf; - struct rx_cxt rx; - struct delayed_work work_rx; - struct usb_interface *intf; - int usb_state; - int (*rx_cb)(void *data, - int len, - int tty_index, - struct tty_dev *tty_dev, - int complete); - spinlock_t write_lock; - struct tty_dev *tty_dev; -}; - -#endif /* _GDM_MUX_H_ */ diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c deleted file mode 100644 index 15c246d3b1a3ebeb4b03c189c8d5611c32f84ed1..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_tty.c +++ /dev/null @@ -1,316 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/usb/cdc.h> -#include <linux/serial.h> -#include "gdm_tty.h" - -#define GDM_TTY_MAJOR 0 -#define GDM_TTY_MINOR 32 - -#define WRITE_SIZE 2048 - -#define MUX_TX_MAX_SIZE 2048 - -static inline bool gdm_tty_ready(struct gdm *gdm) -{ - return gdm && gdm->tty_dev && gdm->port.count; -} - -static struct tty_driver *gdm_driver[TTY_MAX_COUNT]; -static struct gdm *gdm_table[TTY_MAX_COUNT][GDM_TTY_MINOR]; -static DEFINE_MUTEX(gdm_table_lock); - -static const char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"}; -static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"}; - -static void gdm_port_destruct(struct tty_port *port) -{ - struct gdm *gdm = container_of(port, struct gdm, port); - - mutex_lock(&gdm_table_lock); - gdm_table[gdm->index][gdm->minor] = NULL; - mutex_unlock(&gdm_table_lock); - - kfree(gdm); -} - -static const struct tty_port_operations gdm_port_ops = { - .destruct = gdm_port_destruct, -}; - -static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct gdm *gdm = NULL; - int ret; - - ret = match_string(DRIVER_STRING, TTY_MAX_COUNT, - tty->driver->driver_name); - if (ret < 0) - return -ENODEV; - - mutex_lock(&gdm_table_lock); - gdm = gdm_table[ret][tty->index]; - if (!gdm) { - mutex_unlock(&gdm_table_lock); - return -ENODEV; - } - - tty_port_get(&gdm->port); - - ret = tty_standard_install(driver, tty); - if (ret) { - tty_port_put(&gdm->port); - mutex_unlock(&gdm_table_lock); - return ret; - } - - tty->driver_data = gdm; - mutex_unlock(&gdm_table_lock); - - return 0; -} - -static int gdm_tty_open(struct tty_struct *tty, struct file *filp) -{ - struct gdm *gdm = tty->driver_data; - - return tty_port_open(&gdm->port, tty, filp); -} - -static void gdm_tty_cleanup(struct tty_struct *tty) -{ - struct gdm *gdm = tty->driver_data; - - tty_port_put(&gdm->port); -} - -static void gdm_tty_hangup(struct tty_struct *tty) -{ - struct gdm *gdm = tty->driver_data; - - tty_port_hangup(&gdm->port); -} - -static void gdm_tty_close(struct tty_struct *tty, struct file *filp) -{ - struct gdm *gdm = tty->driver_data; - - tty_port_close(&gdm->port, tty, filp); -} - -static int gdm_tty_recv_complete(void *data, - int len, - int index, - struct tty_dev *tty_dev, - int complete) -{ - struct gdm *gdm = tty_dev->gdm[index]; - - if (!gdm_tty_ready(gdm)) { - if (complete == RECV_PACKET_PROCESS_COMPLETE) - gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev, - gdm_tty_recv_complete); - return TO_HOST_PORT_CLOSE; - } - - if (data && len) { - if (tty_buffer_request_room(&gdm->port, len) == len) { - tty_insert_flip_string(&gdm->port, data, len); - tty_flip_buffer_push(&gdm->port); - } else { - return TO_HOST_BUFFER_REQUEST_FAIL; - } - } - - if (complete == RECV_PACKET_PROCESS_COMPLETE) - gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev, - gdm_tty_recv_complete); - - return 0; -} - -static void gdm_tty_send_complete(void *arg) -{ - struct gdm *gdm = arg; - - if (!gdm_tty_ready(gdm)) - return; - - tty_port_tty_wakeup(&gdm->port); -} - -static ssize_t gdm_tty_write(struct tty_struct *tty, const u8 *buf, size_t len) -{ - struct gdm *gdm = tty->driver_data; - size_t remain = len; - size_t sent_len = 0; - - if (!gdm_tty_ready(gdm)) - return -ENODEV; - - while (remain) { - size_t sending_len = min_t(size_t, MUX_TX_MAX_SIZE, remain); - - gdm->tty_dev->send_func(gdm->tty_dev->priv_dev, - (void *)(buf + sent_len), - sending_len, - gdm->index, - gdm_tty_send_complete, - gdm); - sent_len += sending_len; - remain -= sending_len; - } - - return len; -} - -static unsigned int gdm_tty_write_room(struct tty_struct *tty) -{ - struct gdm *gdm = tty->driver_data; - - if (!gdm_tty_ready(gdm)) - return 0; - - return WRITE_SIZE; -} - -int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) -{ - struct gdm *gdm; - int i; - int j; - - for (i = 0; i < TTY_MAX_COUNT; i++) { - gdm = kmalloc(sizeof(*gdm), GFP_KERNEL); - if (!gdm) - return -ENOMEM; - - mutex_lock(&gdm_table_lock); - for (j = 0; j < GDM_TTY_MINOR; j++) { - if (!gdm_table[i][j]) - break; - } - - if (j == GDM_TTY_MINOR) { - kfree(gdm); - mutex_unlock(&gdm_table_lock); - return -EINVAL; - } - - gdm_table[i][j] = gdm; - mutex_unlock(&gdm_table_lock); - - tty_dev->gdm[i] = gdm; - tty_port_init(&gdm->port); - - gdm->port.ops = &gdm_port_ops; - gdm->index = i; - gdm->minor = j; - gdm->tty_dev = tty_dev; - - tty_port_register_device(&gdm->port, gdm_driver[i], - gdm->minor, device); - } - - for (i = 0; i < MAX_ISSUE_NUM; i++) - gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev, - gdm_tty_recv_complete); - - return 0; -} - -void unregister_lte_tty_device(struct tty_dev *tty_dev) -{ - struct gdm *gdm; - struct tty_struct *tty; - int i; - - for (i = 0; i < TTY_MAX_COUNT; i++) { - gdm = tty_dev->gdm[i]; - if (!gdm) - continue; - - mutex_lock(&gdm_table_lock); - gdm_table[gdm->index][gdm->minor] = NULL; - mutex_unlock(&gdm_table_lock); - - tty = tty_port_tty_get(&gdm->port); - if (tty) { - tty_vhangup(tty); - tty_kref_put(tty); - } - - tty_unregister_device(gdm_driver[i], gdm->minor); - tty_port_put(&gdm->port); - } -} - -static const struct tty_operations gdm_tty_ops = { - .install = gdm_tty_install, - .open = gdm_tty_open, - .close = gdm_tty_close, - .cleanup = gdm_tty_cleanup, - .hangup = gdm_tty_hangup, - .write = gdm_tty_write, - .write_room = gdm_tty_write_room, -}; - -int register_lte_tty_driver(void) -{ - struct tty_driver *tty_driver; - int i; - int ret; - - for (i = 0; i < TTY_MAX_COUNT; i++) { - tty_driver = tty_alloc_driver(GDM_TTY_MINOR, - TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV); - if (IS_ERR(tty_driver)) - return PTR_ERR(tty_driver); - - tty_driver->owner = THIS_MODULE; - tty_driver->driver_name = DRIVER_STRING[i]; - tty_driver->name = DEVICE_STRING[i]; - tty_driver->major = GDM_TTY_MAJOR; - tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - tty_driver->subtype = SERIAL_TYPE_NORMAL; - tty_driver->init_termios = tty_std_termios; - tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL; - tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN; - tty_set_operations(tty_driver, &gdm_tty_ops); - - ret = tty_register_driver(tty_driver); - if (ret) { - tty_driver_kref_put(tty_driver); - return ret; - } - - gdm_driver[i] = tty_driver; - } - - return ret; -} - -void unregister_lte_tty_driver(void) -{ - struct tty_driver *tty_driver; - int i; - - for (i = 0; i < TTY_MAX_COUNT; i++) { - tty_driver = gdm_driver[i]; - if (tty_driver) { - tty_unregister_driver(tty_driver); - tty_driver_kref_put(tty_driver); - } - } -} - diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h deleted file mode 100644 index afec97ced4769b2b16cd52017925604cf62ced67..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_tty.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _GDM_TTY_H_ -#define _GDM_TTY_H_ - -#include <linux/types.h> -#include <linux/tty.h> - -#define TTY_MAX_COUNT 2 - -#define MAX_ISSUE_NUM 3 - -enum TO_HOST_RESULT { - TO_HOST_BUFFER_REQUEST_FAIL = 1, - TO_HOST_PORT_CLOSE = 2, - TO_HOST_INVALID_PACKET = 3, -}; - -enum RECV_PACKET_PROCESS { - RECV_PACKET_PROCESS_COMPLETE = 0, - RECV_PACKET_PROCESS_CONTINUE = 1, -}; - -struct gdm { - struct tty_dev *tty_dev; - struct tty_port port; - unsigned int index; - unsigned int minor; -}; - -struct tty_dev { - void *priv_dev; - int (*send_func)(void *priv_dev, - void *data, - int len, - int tty_index, - void (*cb)(void *cb_data), - void *cb_data); - int (*recv_func)(void *priv_dev, - int (*cb)(void *data, - int len, - int tty_index, - struct tty_dev *tty_dev, - int complete)); - int (*send_control)(void *priv_dev, - int request, - int value, - void *data, - int len); - struct gdm *gdm[2]; -}; - -int register_lte_tty_driver(void); -void unregister_lte_tty_driver(void); -int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev); -void unregister_lte_tty_device(struct tty_dev *tty_dev); - -#endif /* _GDM_USB_H_ */ - diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c deleted file mode 100644 index 54bdb64f52e889962205b7d2ff287e4e3a14a1ad..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_usb.c +++ /dev/null @@ -1,1012 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/usb.h> -#include <linux/sched.h> -#include <linux/kthread.h> -#include <linux/usb/cdc.h> -#include <linux/wait.h> -#include <linux/if_ether.h> -#include <linux/pm_runtime.h> - -#include "gdm_usb.h" -#include "gdm_lte.h" -#include "hci.h" -#include "hci_packet.h" -#include "gdm_endian.h" - -#define USB_DEVICE_CDC_DATA(vid, pid) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_CLASS | \ - USB_DEVICE_ID_MATCH_INT_SUBCLASS,\ - .idVendor = vid,\ - .idProduct = pid,\ - .bInterfaceClass = USB_CLASS_COMM,\ - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET - -#define USB_DEVICE_MASS_DATA(vid, pid) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ - USB_DEVICE_ID_MATCH_INT_INFO,\ - .idVendor = vid,\ - .idProduct = pid,\ - .bInterfaceSubClass = USB_SC_SCSI, \ - .bInterfaceClass = USB_CLASS_MASS_STORAGE,\ - .bInterfaceProtocol = USB_PR_BULK - -static const struct usb_device_id id_table[] = { - { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7240) }, /* GCT GDM7240 */ - { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7243) }, /* GCT GDM7243 */ - { } -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static void do_tx(struct work_struct *work); -static void do_rx(struct work_struct *work); - -static int gdm_usb_recv(void *priv_dev, - int (*cb)(void *cb_data, - void *data, int len, int context), - void *cb_data, - int context); - -static int request_mac_address(struct lte_udev *udev) -{ - struct hci_packet *hci; - struct usb_device *usbdev = udev->usbdev; - int actual; - int ret = -1; - - hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL); - if (!hci) - return -ENOMEM; - - hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION); - hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1); - hci->data[0] = MAC_ADDRESS; - - ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5, - &actual, 1000); - - udev->request_mac_addr = 1; - kfree(hci); - - return ret; -} - -static struct usb_tx *alloc_tx_struct(int len) -{ - struct usb_tx *t = NULL; - int ret = 0; - - t = kzalloc(sizeof(*t), GFP_ATOMIC); - if (!t) { - ret = -ENOMEM; - goto out; - } - - t->urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!(len % 512)) - len++; - - t->buf = kmalloc(len, GFP_ATOMIC); - if (!t->urb || !t->buf) { - ret = -ENOMEM; - goto out; - } - -out: - if (ret < 0) { - if (t) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - } - return NULL; - } - - return t; -} - -static struct usb_tx_sdu *alloc_tx_sdu_struct(void) -{ - struct usb_tx_sdu *t_sdu; - - t_sdu = kzalloc(sizeof(*t_sdu), GFP_KERNEL); - if (!t_sdu) - return NULL; - - t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_KERNEL); - if (!t_sdu->buf) { - kfree(t_sdu); - return NULL; - } - - return t_sdu; -} - -static void free_tx_struct(struct usb_tx *t) -{ - if (t) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - } -} - -static void free_tx_sdu_struct(struct usb_tx_sdu *t_sdu) -{ - if (t_sdu) { - kfree(t_sdu->buf); - kfree(t_sdu); - } -} - -static struct usb_tx_sdu *get_tx_sdu_struct(struct tx_cxt *tx, int *no_spc) -{ - struct usb_tx_sdu *t_sdu; - - if (list_empty(&tx->free_list)) - return NULL; - - t_sdu = list_entry(tx->free_list.next, struct usb_tx_sdu, list); - list_del(&t_sdu->list); - - tx->avail_count--; - - *no_spc = list_empty(&tx->free_list) ? 1 : 0; - - return t_sdu; -} - -static void put_tx_struct(struct tx_cxt *tx, struct usb_tx_sdu *t_sdu) -{ - list_add_tail(&t_sdu->list, &tx->free_list); - tx->avail_count++; -} - -static struct usb_rx *alloc_rx_struct(void) -{ - struct usb_rx *r = NULL; - int ret = 0; - - r = kmalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - ret = -ENOMEM; - goto out; - } - - r->urb = usb_alloc_urb(0, GFP_KERNEL); - r->buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); - if (!r->urb || !r->buf) { - ret = -ENOMEM; - goto out; - } -out: - - if (ret < 0) { - if (r) { - usb_free_urb(r->urb); - kfree(r->buf); - kfree(r); - } - return NULL; - } - - return r; -} - -static void free_rx_struct(struct usb_rx *r) -{ - if (r) { - usb_free_urb(r->urb); - kfree(r->buf); - kfree(r); - } -} - -static struct usb_rx *get_rx_struct(struct rx_cxt *rx, int *no_spc) -{ - struct usb_rx *r; - unsigned long flags; - - spin_lock_irqsave(&rx->rx_lock, flags); - - if (list_empty(&rx->free_list)) { - spin_unlock_irqrestore(&rx->rx_lock, flags); - return NULL; - } - - r = list_entry(rx->free_list.next, struct usb_rx, free_list); - list_del(&r->free_list); - - rx->avail_count--; - - *no_spc = list_empty(&rx->free_list) ? 1 : 0; - - spin_unlock_irqrestore(&rx->rx_lock, flags); - - return r; -} - -static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r) -{ - unsigned long flags; - - spin_lock_irqsave(&rx->rx_lock, flags); - - list_add_tail(&r->free_list, &rx->free_list); - rx->avail_count++; - - spin_unlock_irqrestore(&rx->rx_lock, flags); -} - -static void release_usb(struct lte_udev *udev) -{ - struct rx_cxt *rx = &udev->rx; - struct tx_cxt *tx = &udev->tx; - struct usb_tx *t, *t_next; - struct usb_rx *r, *r_next; - struct usb_tx_sdu *t_sdu, *t_sdu_next; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list) { - list_del(&t_sdu->list); - free_tx_sdu_struct(t_sdu); - } - - list_for_each_entry_safe(t, t_next, &tx->hci_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list) { - list_del(&t_sdu->list); - free_tx_sdu_struct(t_sdu); - } - spin_unlock_irqrestore(&tx->lock, flags); - - spin_lock_irqsave(&rx->submit_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, - rx_submit_list) { - spin_unlock_irqrestore(&rx->submit_lock, flags); - usb_kill_urb(r->urb); - spin_lock_irqsave(&rx->submit_lock, flags); - } - spin_unlock_irqrestore(&rx->submit_lock, flags); - - spin_lock_irqsave(&rx->rx_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->free_list, free_list) { - list_del(&r->free_list); - free_rx_struct(r); - } - spin_unlock_irqrestore(&rx->rx_lock, flags); - - spin_lock_irqsave(&rx->to_host_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) { - if (r->index == (void *)udev) { - list_del(&r->to_host_list); - free_rx_struct(r); - } - } - spin_unlock_irqrestore(&rx->to_host_lock, flags); -} - -static int init_usb(struct lte_udev *udev) -{ - int ret = 0; - int i; - struct tx_cxt *tx = &udev->tx; - struct rx_cxt *rx = &udev->rx; - struct usb_tx_sdu *t_sdu = NULL; - struct usb_rx *r = NULL; - - udev->send_complete = 1; - udev->tx_stop = 0; - udev->request_mac_addr = 0; - udev->usb_state = PM_NORMAL; - - INIT_LIST_HEAD(&tx->sdu_list); - INIT_LIST_HEAD(&tx->hci_list); - INIT_LIST_HEAD(&tx->free_list); - INIT_LIST_HEAD(&rx->rx_submit_list); - INIT_LIST_HEAD(&rx->free_list); - INIT_LIST_HEAD(&rx->to_host_list); - spin_lock_init(&tx->lock); - spin_lock_init(&rx->rx_lock); - spin_lock_init(&rx->submit_lock); - spin_lock_init(&rx->to_host_lock); - - tx->avail_count = 0; - rx->avail_count = 0; - - udev->rx_cb = NULL; - - for (i = 0; i < MAX_NUM_SDU_BUF; i++) { - t_sdu = alloc_tx_sdu_struct(); - if (!t_sdu) { - ret = -ENOMEM; - goto fail; - } - - list_add(&t_sdu->list, &tx->free_list); - tx->avail_count++; - } - - for (i = 0; i < MAX_RX_SUBMIT_COUNT * 2; i++) { - r = alloc_rx_struct(); - if (!r) { - ret = -ENOMEM; - goto fail; - } - - list_add(&r->free_list, &rx->free_list); - rx->avail_count++; - } - INIT_DELAYED_WORK(&udev->work_tx, do_tx); - INIT_DELAYED_WORK(&udev->work_rx, do_rx); - return 0; -fail: - release_usb(udev); - return ret; -} - -static int set_mac_address(u8 *data, void *arg) -{ - struct phy_dev *phy_dev = arg; - struct lte_udev *udev = phy_dev->priv_dev; - struct tlv *tlv = (struct tlv *)data; - u8 mac_address[ETH_ALEN] = {0, }; - - if (tlv->type == MAC_ADDRESS && udev->request_mac_addr) { - memcpy(mac_address, tlv->data, tlv->len); - - if (register_lte_device(phy_dev, - &udev->intf->dev, mac_address) < 0) - pr_err("register lte device failed\n"); - - udev->request_mac_addr = 0; - - return 1; - } - - return 0; -} - -static void do_rx(struct work_struct *work) -{ - struct lte_udev *udev = - container_of(work, struct lte_udev, work_rx.work); - struct rx_cxt *rx = &udev->rx; - struct usb_rx *r; - struct hci_packet *hci; - struct phy_dev *phy_dev; - u16 cmd_evt; - int ret; - unsigned long flags; - - while (1) { - spin_lock_irqsave(&rx->to_host_lock, flags); - if (list_empty(&rx->to_host_list)) { - spin_unlock_irqrestore(&rx->to_host_lock, flags); - break; - } - r = list_entry(rx->to_host_list.next, - struct usb_rx, to_host_list); - list_del(&r->to_host_list); - spin_unlock_irqrestore(&rx->to_host_lock, flags); - - phy_dev = r->cb_data; - udev = phy_dev->priv_dev; - hci = (struct hci_packet *)r->buf; - cmd_evt = gdm_dev16_to_cpu(udev->gdm_ed, hci->cmd_evt); - - switch (cmd_evt) { - case LTE_GET_INFORMATION_RESULT: - if (set_mac_address(hci->data, r->cb_data) == 0) { - r->callback(r->cb_data, - r->buf, - r->urb->actual_length, - KERNEL_THREAD); - } - break; - - default: - if (r->callback) { - ret = r->callback(r->cb_data, - r->buf, - r->urb->actual_length, - KERNEL_THREAD); - - if (ret == -EAGAIN) - pr_err("failed to send received data\n"); - } - break; - } - - put_rx_struct(rx, r); - - gdm_usb_recv(udev, - r->callback, - r->cb_data, - USB_COMPLETE); - } -} - -static void remove_rx_submit_list(struct usb_rx *r, struct rx_cxt *rx) -{ - unsigned long flags; - struct usb_rx *r_remove, *r_remove_next; - - spin_lock_irqsave(&rx->submit_lock, flags); - list_for_each_entry_safe(r_remove, r_remove_next, - &rx->rx_submit_list, rx_submit_list) { - if (r == r_remove) { - list_del(&r->rx_submit_list); - break; - } - } - spin_unlock_irqrestore(&rx->submit_lock, flags); -} - -static void gdm_usb_rcv_complete(struct urb *urb) -{ - struct usb_rx *r = urb->context; - struct rx_cxt *rx = r->rx; - unsigned long flags; - struct lte_udev *udev = container_of(r->rx, struct lte_udev, rx); - struct usb_device *usbdev = udev->usbdev; - - remove_rx_submit_list(r, rx); - - if (!urb->status && r->callback) { - spin_lock_irqsave(&rx->to_host_lock, flags); - list_add_tail(&r->to_host_list, &rx->to_host_list); - schedule_work(&udev->work_rx.work); - spin_unlock_irqrestore(&rx->to_host_lock, flags); - } else { - if (urb->status && udev->usb_state == PM_NORMAL) - dev_err(&urb->dev->dev, "%s: urb status error %d\n", - __func__, urb->status); - - put_rx_struct(rx, r); - } - - usb_mark_last_busy(usbdev); -} - -static int gdm_usb_recv(void *priv_dev, - int (*cb)(void *cb_data, - void *data, int len, int context), - void *cb_data, - int context) -{ - struct lte_udev *udev = priv_dev; - struct usb_device *usbdev = udev->usbdev; - struct rx_cxt *rx = &udev->rx; - struct usb_rx *r; - int no_spc; - int ret; - unsigned long flags; - - if (!udev->usbdev) { - pr_err("invalid device\n"); - return -ENODEV; - } - - r = get_rx_struct(rx, &no_spc); - if (!r) { - pr_err("Out of Memory\n"); - return -ENOMEM; - } - - udev->rx_cb = cb; - r->callback = cb; - r->cb_data = cb_data; - r->index = (void *)udev; - r->rx = rx; - - usb_fill_bulk_urb(r->urb, - usbdev, - usb_rcvbulkpipe(usbdev, 0x83), - r->buf, - RX_BUF_SIZE, - gdm_usb_rcv_complete, - r); - - spin_lock_irqsave(&rx->submit_lock, flags); - list_add_tail(&r->rx_submit_list, &rx->rx_submit_list); - spin_unlock_irqrestore(&rx->submit_lock, flags); - - if (context == KERNEL_THREAD) - ret = usb_submit_urb(r->urb, GFP_KERNEL); - else - ret = usb_submit_urb(r->urb, GFP_ATOMIC); - - if (ret) { - spin_lock_irqsave(&rx->submit_lock, flags); - list_del(&r->rx_submit_list); - spin_unlock_irqrestore(&rx->submit_lock, flags); - - pr_err("usb_submit_urb failed (%p)\n", r); - put_rx_struct(rx, r); - } - - return ret; -} - -static void gdm_usb_send_complete(struct urb *urb) -{ - struct usb_tx *t = urb->context; - struct tx_cxt *tx = t->tx; - struct lte_udev *udev = container_of(tx, struct lte_udev, tx); - unsigned long flags; - - if (urb->status == -ECONNRESET) { - dev_info(&urb->dev->dev, "CONNRESET\n"); - return; - } - - if (t->callback) - t->callback(t->cb_data); - - free_tx_struct(t); - - spin_lock_irqsave(&tx->lock, flags); - udev->send_complete = 1; - schedule_work(&udev->work_tx.work); - spin_unlock_irqrestore(&tx->lock, flags); -} - -static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len) -{ - int ret = 0; - - if (!(len % 512)) - len++; - - usb_fill_bulk_urb(t->urb, - usbdev, - usb_sndbulkpipe(usbdev, 2), - t->buf, - len, - gdm_usb_send_complete, - t); - - ret = usb_submit_urb(t->urb, GFP_ATOMIC); - - if (ret) - dev_err(&usbdev->dev, "usb_submit_urb failed: %d\n", - ret); - - usb_mark_last_busy(usbdev); - - return ret; -} - -static u32 packet_aggregation(struct lte_udev *udev, u8 *send_buf) -{ - struct tx_cxt *tx = &udev->tx; - struct usb_tx_sdu *t_sdu = NULL; - struct multi_sdu *multi_sdu = (struct multi_sdu *)send_buf; - u16 send_len = 0; - u16 num_packet = 0; - unsigned long flags; - - multi_sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_MULTI_SDU); - - while (num_packet < MAX_PACKET_IN_MULTI_SDU) { - spin_lock_irqsave(&tx->lock, flags); - if (list_empty(&tx->sdu_list)) { - spin_unlock_irqrestore(&tx->lock, flags); - break; - } - - t_sdu = list_entry(tx->sdu_list.next, struct usb_tx_sdu, list); - if (send_len + t_sdu->len > MAX_SDU_SIZE) { - spin_unlock_irqrestore(&tx->lock, flags); - break; - } - - list_del(&t_sdu->list); - spin_unlock_irqrestore(&tx->lock, flags); - - memcpy(multi_sdu->data + send_len, t_sdu->buf, t_sdu->len); - - send_len += (t_sdu->len + 3) & 0xfffc; - num_packet++; - - if (tx->avail_count > 10) - t_sdu->callback(t_sdu->cb_data); - - spin_lock_irqsave(&tx->lock, flags); - put_tx_struct(tx, t_sdu); - spin_unlock_irqrestore(&tx->lock, flags); - } - - multi_sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len); - multi_sdu->num_packet = gdm_cpu_to_dev16(udev->gdm_ed, num_packet); - - return send_len + offsetof(struct multi_sdu, data); -} - -static void do_tx(struct work_struct *work) -{ - struct lte_udev *udev = - container_of(work, struct lte_udev, work_tx.work); - struct usb_device *usbdev = udev->usbdev; - struct tx_cxt *tx = &udev->tx; - struct usb_tx *t = NULL; - int is_send = 0; - u32 len = 0; - unsigned long flags; - - if (!usb_autopm_get_interface(udev->intf)) - usb_autopm_put_interface(udev->intf); - - if (udev->usb_state == PM_SUSPEND) - return; - - spin_lock_irqsave(&tx->lock, flags); - if (!udev->send_complete) { - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - udev->send_complete = 0; - - if (!list_empty(&tx->hci_list)) { - t = list_entry(tx->hci_list.next, struct usb_tx, list); - list_del(&t->list); - len = t->len; - t->is_sdu = 0; - is_send = 1; - } else if (!list_empty(&tx->sdu_list)) { - if (udev->tx_stop) { - udev->send_complete = 1; - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - - t = alloc_tx_struct(TX_BUF_SIZE); - if (!t) { - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - t->callback = NULL; - t->tx = tx; - t->is_sdu = 1; - is_send = 1; - } - - if (!is_send) { - udev->send_complete = 1; - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - spin_unlock_irqrestore(&tx->lock, flags); - - if (t->is_sdu) - len = packet_aggregation(udev, t->buf); - - if (send_tx_packet(usbdev, t, len)) { - pr_err("send_tx_packet failed\n"); - t->callback = NULL; - gdm_usb_send_complete(t->urb); - } -} - -#define SDU_PARAM_LEN 12 -static int gdm_usb_sdu_send(void *priv_dev, void *data, int len, - unsigned int dft_eps_ID, unsigned int eps_ID, - void (*cb)(void *data), void *cb_data, - int dev_idx, int nic_type) -{ - struct lte_udev *udev = priv_dev; - struct tx_cxt *tx = &udev->tx; - struct usb_tx_sdu *t_sdu; - struct sdu *sdu = NULL; - unsigned long flags; - int no_spc = 0; - u16 send_len; - - if (!udev->usbdev) { - pr_err("sdu send - invalid device\n"); - return TX_NO_DEV; - } - - spin_lock_irqsave(&tx->lock, flags); - t_sdu = get_tx_sdu_struct(tx, &no_spc); - spin_unlock_irqrestore(&tx->lock, flags); - - if (!t_sdu) { - pr_err("sdu send - free list empty\n"); - return TX_NO_SPC; - } - - sdu = (struct sdu *)t_sdu->buf; - sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_SDU); - if (nic_type == NIC_TYPE_ARP) { - send_len = len + SDU_PARAM_LEN; - memcpy(sdu->data, data, len); - } else { - send_len = len - ETH_HLEN; - send_len += SDU_PARAM_LEN; - memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN); - } - - sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len); - sdu->dft_eps_ID = gdm_cpu_to_dev32(udev->gdm_ed, dft_eps_ID); - sdu->bearer_ID = gdm_cpu_to_dev32(udev->gdm_ed, eps_ID); - sdu->nic_type = gdm_cpu_to_dev32(udev->gdm_ed, nic_type); - - t_sdu->len = send_len + HCI_HEADER_SIZE; - t_sdu->callback = cb; - t_sdu->cb_data = cb_data; - - spin_lock_irqsave(&tx->lock, flags); - list_add_tail(&t_sdu->list, &tx->sdu_list); - schedule_work(&udev->work_tx.work); - spin_unlock_irqrestore(&tx->lock, flags); - - if (no_spc) - return TX_NO_BUFFER; - - return 0; -} - -static int gdm_usb_hci_send(void *priv_dev, void *data, int len, - void (*cb)(void *data), void *cb_data) -{ - struct lte_udev *udev = priv_dev; - struct tx_cxt *tx = &udev->tx; - struct usb_tx *t; - unsigned long flags; - - if (!udev->usbdev) { - pr_err("hci send - invalid device\n"); - return -ENODEV; - } - - t = alloc_tx_struct(len); - if (!t) { - pr_err("hci_send - out of memory\n"); - return -ENOMEM; - } - - memcpy(t->buf, data, len); - t->callback = cb; - t->cb_data = cb_data; - t->len = len; - t->tx = tx; - t->is_sdu = 0; - - spin_lock_irqsave(&tx->lock, flags); - list_add_tail(&t->list, &tx->hci_list); - schedule_work(&udev->work_tx.work); - spin_unlock_irqrestore(&tx->lock, flags); - - return 0; -} - -static u8 gdm_usb_get_endian(void *priv_dev) -{ - struct lte_udev *udev = priv_dev; - - return udev->gdm_ed; -} - -static int gdm_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret = 0; - struct phy_dev *phy_dev = NULL; - struct lte_udev *udev = NULL; - u16 idVendor, idProduct; - int bInterfaceNumber; - struct usb_device *usbdev = interface_to_usbdev(intf); - - bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; - idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); - idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); - - pr_info("net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct); - - if (bInterfaceNumber > NETWORK_INTERFACE) { - pr_info("not a network device\n"); - return -ENODEV; - } - - phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL); - if (!phy_dev) - return -ENOMEM; - - udev = kzalloc(sizeof(*udev), GFP_KERNEL); - if (!udev) { - ret = -ENOMEM; - goto err_udev; - } - - phy_dev->priv_dev = (void *)udev; - phy_dev->send_hci_func = gdm_usb_hci_send; - phy_dev->send_sdu_func = gdm_usb_sdu_send; - phy_dev->rcv_func = gdm_usb_recv; - phy_dev->get_endian = gdm_usb_get_endian; - - udev->usbdev = usbdev; - ret = init_usb(udev); - if (ret < 0) { - dev_err(intf->usb_dev, "init_usb func failed\n"); - goto err_init_usb; - } - udev->intf = intf; - - intf->needs_remote_wakeup = 1; - usb_enable_autosuspend(usbdev); - pm_runtime_set_autosuspend_delay(&usbdev->dev, AUTO_SUSPEND_TIMER); - - /* List up hosts with big endians, otherwise, - * defaults to little endian - */ - if (idProduct == PID_GDM7243) - udev->gdm_ed = ENDIANNESS_BIG; - else - udev->gdm_ed = ENDIANNESS_LITTLE; - - ret = request_mac_address(udev); - if (ret < 0) { - dev_err(intf->usb_dev, "request Mac address failed\n"); - goto err_mac_address; - } - - start_rx_proc(phy_dev); - usb_get_dev(usbdev); - usb_set_intfdata(intf, phy_dev); - - return 0; - -err_mac_address: - release_usb(udev); -err_init_usb: - kfree(udev); -err_udev: - kfree(phy_dev); - - return ret; -} - -static void gdm_usb_disconnect(struct usb_interface *intf) -{ - struct phy_dev *phy_dev; - struct lte_udev *udev; - struct usb_device *usbdev; - - usbdev = interface_to_usbdev(intf); - phy_dev = usb_get_intfdata(intf); - - udev = phy_dev->priv_dev; - unregister_lte_device(phy_dev); - - release_usb(udev); - - kfree(udev); - udev = NULL; - - kfree(phy_dev); - phy_dev = NULL; - - usb_put_dev(usbdev); -} - -static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg) -{ - struct phy_dev *phy_dev; - struct lte_udev *udev; - struct rx_cxt *rx; - struct usb_rx *r; - struct usb_rx *r_next; - unsigned long flags; - - phy_dev = usb_get_intfdata(intf); - udev = phy_dev->priv_dev; - rx = &udev->rx; - if (udev->usb_state != PM_NORMAL) { - dev_err(intf->usb_dev, "usb suspend - invalid state\n"); - return -1; - } - - udev->usb_state = PM_SUSPEND; - - spin_lock_irqsave(&rx->submit_lock, flags); - list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, - rx_submit_list) { - spin_unlock_irqrestore(&rx->submit_lock, flags); - usb_kill_urb(r->urb); - spin_lock_irqsave(&rx->submit_lock, flags); - } - spin_unlock_irqrestore(&rx->submit_lock, flags); - - cancel_work_sync(&udev->work_tx.work); - cancel_work_sync(&udev->work_rx.work); - - return 0; -} - -static int gdm_usb_resume(struct usb_interface *intf) -{ - struct phy_dev *phy_dev; - struct lte_udev *udev; - struct tx_cxt *tx; - struct rx_cxt *rx; - unsigned long flags; - int issue_count; - int i; - - phy_dev = usb_get_intfdata(intf); - udev = phy_dev->priv_dev; - rx = &udev->rx; - - if (udev->usb_state != PM_SUSPEND) { - dev_err(intf->usb_dev, "usb resume - invalid state\n"); - return -1; - } - udev->usb_state = PM_NORMAL; - - spin_lock_irqsave(&rx->rx_lock, flags); - issue_count = rx->avail_count - MAX_RX_SUBMIT_COUNT; - spin_unlock_irqrestore(&rx->rx_lock, flags); - - if (issue_count >= 0) { - for (i = 0; i < issue_count; i++) - gdm_usb_recv(phy_dev->priv_dev, - udev->rx_cb, - phy_dev, - USB_COMPLETE); - } - - tx = &udev->tx; - spin_lock_irqsave(&tx->lock, flags); - schedule_work(&udev->work_tx.work); - spin_unlock_irqrestore(&tx->lock, flags); - - return 0; -} - -static struct usb_driver gdm_usb_lte_driver = { - .name = "gdm_lte", - .probe = gdm_usb_probe, - .disconnect = gdm_usb_disconnect, - .id_table = id_table, - .supports_autosuspend = 1, - .suspend = gdm_usb_suspend, - .resume = gdm_usb_resume, - .reset_resume = gdm_usb_resume, -}; - -static int __init gdm_usb_lte_init(void) -{ - if (gdm_lte_event_init() < 0) { - pr_err("error creating event\n"); - return -1; - } - - return usb_register(&gdm_usb_lte_driver); -} - -static void __exit gdm_usb_lte_exit(void) -{ - gdm_lte_event_exit(); - - usb_deregister(&gdm_usb_lte_driver); -} - -module_init(gdm_usb_lte_init); -module_exit(gdm_usb_lte_exit); - -MODULE_VERSION(DRIVER_VERSION); -MODULE_DESCRIPTION("GCT LTE USB Device Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h deleted file mode 100644 index db689b091c4fd40129e170ed52b27faef146a75e..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/gdm_usb.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _GDM_USB_H_ -#define _GDM_USB_H_ - -#include <linux/types.h> -#include <linux/usb.h> -#include <linux/list.h> -#include <linux/time.h> - -#include "gdm_endian.h" -#include "hci_packet.h" - -#define PM_NORMAL 0 -#define PM_SUSPEND 1 -#define AUTO_SUSPEND_TIMER 5000 /* ms */ - -#define RX_BUF_SIZE (1024 * 32) -#define TX_BUF_SIZE (1024 * 32) -#define SDU_BUF_SIZE 2048 -#define MAX_SDU_SIZE (1024 * 30) -#define MAX_PACKET_IN_MULTI_SDU 256 - -#define VID_GCT 0x1076 -#define PID_GDM7240 0x8000 -#define PID_GDM7243 0x9000 - -#define NETWORK_INTERFACE 1 -#define USB_SC_SCSI 0x06 -#define USB_PR_BULK 0x50 - -#define MAX_NUM_SDU_BUF 64 - -struct usb_tx { - struct list_head list; - struct urb *urb; - u8 *buf; - u32 len; - void (*callback)(void *cb_data); - void *cb_data; - struct tx_cxt *tx; - u8 is_sdu; -}; - -struct usb_tx_sdu { - struct list_head list; - u8 *buf; - u32 len; - void (*callback)(void *cb_data); - void *cb_data; -}; - -struct usb_rx { - struct list_head to_host_list; - struct list_head free_list; - struct list_head rx_submit_list; - struct rx_cxt *rx; - struct urb *urb; - u8 *buf; - int (*callback)(void *cb_data, void *data, int len, int context); - void *cb_data; - void *index; -}; - -struct tx_cxt { - struct list_head sdu_list; - struct list_head hci_list; - struct list_head free_list; - u32 avail_count; - spinlock_t lock; -}; - -struct rx_cxt { - struct list_head to_host_list; - struct list_head rx_submit_list; - struct list_head free_list; - u32 avail_count; - spinlock_t to_host_lock; - spinlock_t rx_lock; - spinlock_t submit_lock; -}; - -struct lte_udev { - struct usb_device *usbdev; - struct tx_cxt tx; - struct rx_cxt rx; - struct delayed_work work_tx; - struct delayed_work work_rx; - u8 gdm_ed; - u8 send_complete; - u8 tx_stop; - struct usb_interface *intf; - int (*rx_cb)(void *cb_data, void *data, int len, int context); - int usb_state; - u8 request_mac_addr; -}; - -#endif /* _GDM_USB_H_ */ diff --git a/drivers/staging/gdm724x/hci.h b/drivers/staging/gdm724x/hci.h deleted file mode 100644 index b30945daf3a539a43c70da0d02f18ae1e4338fdd..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/hci.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _HCI_H_ -#define _HCI_H_ - -#define LTE_GET_INFORMATION 0x3002 -#define LTE_GET_INFORMATION_RESULT 0xB003 - #define MAC_ADDRESS 0xA2 - -#define LTE_LINK_ON_OFF_INDICATION 0xB133 -#define LTE_PDN_TABLE_IND 0xB143 - -#define LTE_TX_SDU 0x3200 -#define LTE_RX_SDU 0xB201 -#define LTE_TX_MULTI_SDU 0x3202 -#define LTE_RX_MULTI_SDU 0xB203 - -#define LTE_DL_SDU_FLOW_CONTROL 0x3305 -#define LTE_UL_SDU_FLOW_CONTROL 0xB306 - -#define LTE_AT_CMD_TO_DEVICE 0x3307 -#define LTE_AT_CMD_FROM_DEVICE 0xB308 - -#define LTE_SDIO_DM_SEND_PKT 0x3312 -#define LTE_SDIO_DM_RECV_PKT 0xB313 - -#define LTE_NV_RESTORE_REQUEST 0xB30C -#define LTE_NV_RESTORE_RESPONSE 0x330D -#define LTE_NV_SAVE_REQUEST 0xB30E - #define NV_TYPE_LTE_INFO 0x00 - #define NV_TYPE_BOARD_CONFIG 0x01 - #define NV_TYPE_RF_CAL 0x02 - #define NV_TYPE_TEMP 0x03 - #define NV_TYPE_NET_INFO 0x04 - #define NV_TYPE_SAFETY_INFO 0x05 - #define NV_TYPE_CDMA_CAL 0x06 - #define NV_TYPE_VENDOR 0x07 - #define NV_TYPE_ALL 0xff -#define LTE_NV_SAVE_RESPONSE 0x330F - -#define LTE_AT_CMD_TO_DEVICE_EXT 0x3323 -#define LTE_AT_CMD_FROM_DEVICE_EXT 0xB324 - -#endif /* _HCI_H_ */ diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h deleted file mode 100644 index 3bb01e94f3b576d1b093b7c2ef696dabdda38dc2..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/hci_packet.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _HCI_PACKET_H_ -#define _HCI_PACKET_H_ - -#define HCI_HEADER_SIZE 4 - -/* - * The NIC type definition: - * For backward compatibility, lower 16 bits used as they were. - * Lower 16 bit: NIC_TYPE values - * Uppoer 16 bit: NIC_TYPE Flags - */ -#define NIC_TYPE_NIC0 0x00000010 -#define NIC_TYPE_NIC1 0x00000011 -#define NIC_TYPE_NIC2 0x00000012 -#define NIC_TYPE_NIC3 0x00000013 -#define NIC_TYPE_ARP 0x00000100 -#define NIC_TYPE_ICMPV6 0x00000200 -#define NIC_TYPE_MASK 0x0000FFFF -#define NIC_TYPE_F_IPV4 0x00010000 -#define NIC_TYPE_F_IPV6 0x00020000 -#define NIC_TYPE_F_DHCP 0x00040000 -#define NIC_TYPE_F_NDP 0x00080000 -#define NIC_TYPE_F_VLAN 0x00100000 - -struct hci_packet { - __dev16 cmd_evt; - __dev16 len; - u8 data[]; -} __packed; - -struct tlv { - u8 type; - u8 len; - u8 *data[]; -} __packed; - -struct sdu_header { - __dev16 cmd_evt; - __dev16 len; - __dev32 dft_eps_id; - __dev32 bearer_ID; - __dev32 nic_type; -} __packed; - -struct sdu { - __dev16 cmd_evt; - __dev16 len; - __dev32 dft_eps_ID; - __dev32 bearer_ID; - __dev32 nic_type; - u8 data[]; -} __packed; - -struct multi_sdu { - __dev16 cmd_evt; - __dev16 len; - __dev16 num_packet; - __dev16 reserved; - u8 data[]; -} __packed; - -struct hci_pdn_table_ind { - __dev16 cmd_evt; - __dev16 len; - u8 activate; - __dev32 dft_eps_id; - __dev32 nic_type; - u8 pdn_type; - u8 ipv4_addr[4]; - u8 ipv6_intf_id[8]; -} __packed; - -struct hci_connect_ind { - __dev16 cmd_evt; - __dev16 len; - __dev32 connect; -} __packed; - -#endif /* _HCI_PACKET_H_ */ diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c deleted file mode 100644 index 8f39cc5617aada5353f9e0a36f8bc818e8083b62..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/netlink_k.c +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/export.h> -#include <linux/mutex.h> -#include <linux/etherdevice.h> -#include <linux/netlink.h> -#include <asm/byteorder.h> -#include <net/sock.h> - -#include "netlink_k.h" - -static DEFINE_MUTEX(netlink_mutex); - -#define ND_MAX_GROUP 30 -#define ND_IFINDEX_LEN sizeof(int) -#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN) -#define ND_NLMSG_DATA(nlh) ((void *)((char *)NLMSG_DATA(nlh) + \ - ND_IFINDEX_LEN)) -#define ND_NLMSG_S_LEN(len) ((len) + ND_IFINDEX_LEN) -#define ND_NLMSG_R_LEN(nlh) ((nlh)->nlmsg_len - ND_IFINDEX_LEN) -#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh) -#define ND_MAX_MSG_LEN (1024 * 32) - -static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len); - -static void netlink_rcv_cb(struct sk_buff *skb) -{ - struct nlmsghdr *nlh; - struct net_device *dev; - u32 mlen; - void *msg; - int ifindex; - - if (!rcv_cb) { - pr_err("nl cb - unregistered\n"); - return; - } - - if (skb->len < NLMSG_HDRLEN) { - pr_err("nl cb - invalid skb length\n"); - return; - } - - nlh = (struct nlmsghdr *)skb->data; - - if (skb->len < nlh->nlmsg_len || nlh->nlmsg_len > ND_MAX_MSG_LEN) { - pr_err("nl cb - invalid length (%d,%d)\n", - skb->len, nlh->nlmsg_len); - return; - } - - memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN); - msg = ND_NLMSG_DATA(nlh); - mlen = ND_NLMSG_R_LEN(nlh); - - dev = dev_get_by_index(&init_net, ifindex); - if (dev) { - rcv_cb(dev, nlh->nlmsg_type, msg, mlen); - dev_put(dev); - } else { - pr_err("nl cb - dev (%d) not found\n", ifindex); - } -} - -static void netlink_rcv(struct sk_buff *skb) -{ - mutex_lock(&netlink_mutex); - netlink_rcv_cb(skb); - mutex_unlock(&netlink_mutex); -} - -struct sock *netlink_init(int unit, - void (*cb)(struct net_device *dev, u16 type, - void *msg, int len)) -{ - struct sock *sock; - struct netlink_kernel_cfg cfg = { - .input = netlink_rcv, - }; - - sock = netlink_kernel_create(&init_net, unit, &cfg); - - if (sock) - rcv_cb = cb; - - return sock; -} - -int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len, - struct net_device *dev) -{ - static u32 seq; - struct sk_buff *skb = NULL; - struct nlmsghdr *nlh; - int ret = 0; - - if (group > ND_MAX_GROUP) - return -EINVAL; - - if (!netlink_has_listeners(sock, group + 1)) - return -ESRCH; - - skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC); - if (!skb) - return -ENOMEM; - - seq++; - - nlh = nlmsg_put(skb, 0, seq, type, len, 0); - memcpy(NLMSG_DATA(nlh), msg, len); - NETLINK_CB(skb).portid = 0; - NETLINK_CB(skb).dst_group = 0; - - ret = netlink_broadcast(sock, skb, 0, group + 1, GFP_ATOMIC); - if (!ret) - return len; - - if (ret != -ESRCH) - netdev_err(dev, "nl broadcast g=%d, t=%d, l=%d, r=%d\n", - group, type, len, ret); - else if (netlink_has_listeners(sock, group + 1)) - return -EAGAIN; - - return ret; -} diff --git a/drivers/staging/gdm724x/netlink_k.h b/drivers/staging/gdm724x/netlink_k.h deleted file mode 100644 index d42eea9bea3ec5719be32dfbc5f0e614e2319535..0000000000000000000000000000000000000000 --- a/drivers/staging/gdm724x/netlink_k.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */ - -#ifndef _NETLINK_K_H -#define _NETLINK_K_H - -#include <linux/netdevice.h> -#include <net/sock.h> - -struct sock *netlink_init(int unit, - void (*cb)(struct net_device *dev, - u16 type, void *msg, int len)); -int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len, - struct net_device *dev); - -#endif /* _NETLINK_K_H_ */ diff --git a/drivers/staging/gpib/Kconfig b/drivers/staging/gpib/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..95308d15a55516de9118e7ae90a6103ee8c6c003 --- /dev/null +++ b/drivers/staging/gpib/Kconfig @@ -0,0 +1,251 @@ +# SPDX-License-Identifier: GPL-2.0 +menuconfig GPIB + tristate "Linux GPIB drivers" + help + Enable support for GPIB cards and dongles for Linux. GPIB + is the General Purpose Interface Bus which conforms to the + IEEE488 standard. + + This set of drivers can be used with the corresponding user + space library that can be found on Sourceforge under linux-gpib. + Select the drivers for your hardware from the list. + +if GPIB + +config GPIB_COMMON + tristate "GPIB core" + help + + Core common driver for all GPIB drivers. It provides the + interface for the userland library + + To compile this driver as a module, choose M here: the module will be + called gpib_common + +config GPIB_AGILENT_82350B + tristate "Agilent 8235xx PCI(e) adapters" + depends on PCI + select GPIB_COMMON + select GPIB_TMS9914 + help + Enable support for HP/Agilent/Keysight boards + 82350A + 82350B + 82351A + + To compile this driver as a module, choose M here: the module will be + called agilent_82350b. + +config GPIB_AGILENT_82357A + tristate "Agilent 82357a/b USB dongles" + select GPIB_COMMON + depends on USB + help + Enable support for Agilent/Keysight 82357x USB dongles. + + To compile this driver as a module, choose M here: the module will be + called agilent_82357a. + +config GPIB_CEC_PCI + tristate "CEC PCI board" + depends on PCI + depends on HAS_IOPORT + select GPIB_COMMON + select GPIB_NEC7210 + help + Enable support for Capital Equipment Corporation PCI-488 + and Keithly KPCI-488 boards. + + To compile this driver as a module, choose M here: the module will be + called cec_gpib. + +config GPIB_NI_PCI_ISA + tristate "NI PCI/ISA compatible boards" + depends on ISA_BUS || PCI || PCMCIA + select GPIB_COMMON + select GPIB_NEC7210 + help + Enable support for National Instruments boards based + on TNT4882 chips: + AT-GPIB (with NAT4882 chip) + AT-GPIB (with NEC7210 chip) + AT-GPIB/TNT + PCI-GPIB + PCIe-GPIB + PCI-GPIB+ + PCM-GPIB + PXI-GPIB + PCMCIA-GPIB + and Capital Equipment Corporation CEC-488 board. + + To compile this driver as a module, choose M here: the module will be + called tnt4882. + +config GPIB_CB7210 + tristate "Measurement Computing compatible boards" + depends on HAS_IOPORT + depends on ISA_BUS || PCI || PCMCIA + select GPIB_COMMON + select GPIB_NEC7210 + help + Enable support for Measurement Computing (Computer Boards): + CPCI_GPIB, ISA-GPIB, ISA-GPIB/LC, PCI-GPIB/1M, PCI-GPIB/300K and + PCMCIA-GPIB + Quancom PCIGPIB-1 with MC cb7210 chip + + To compile this driver as a module, choose M here: the module will be + +config GPIB_NI_USB + tristate "NI USB dongles" + select GPIB_COMMON + depends on USB + help + Enable support for National Instruments + GPIB-USB-B + GPIB-USB-HS + GPIB-USB-HS+ + Keithly + KUSB-488 + KUSB-488A + Measurement Computing (Computer Boards) + USB-488 + + To compile this driver as a module, choose M here: the module will be + called ni_usb. + +config GPIB_FLUKE + tristate "Fluke" + depends on OF + select GPIB_COMMON + select GPIB_NEC7210 + help + GPIB driver for Fluke based cda devices. + + To compile this driver as a module, choose M here: the module will be + called fluke_gpib + +config GPIB_FMH + tristate "FMH FPGA based devices" + select GPIB_COMMON + select GPIB_NEC7210 + depends on BROKEN + depends on OF && PCI + help + GPIB driver for fmhess FPGA based devices + + To compile this driver as a module, choose M here: the module will be + called fmh_gpib + +config GPIB_GPIO + tristate "RPi GPIO bitbang" + depends on ARCH_BCM2835 || COMPILE_TEST + select GPIB_COMMON + help + GPIB bitbang driver Raspberry Pi GPIO adapters + + To compile this driver as a module, choose M here: the module will be + called gpib_bitbang + +config GPIB_HP82335 + tristate "HP82335/HP27209" + depends on ISA_BUS + select GPIB_COMMON + select GPIB_TMS9914 + help + GPIB driver for HP82335 and HP27209 boards + + To compile this driver as a module, choose M here: the module will be + called hp82335 + + +config GPIB_HP82341 + tristate "HP82341x" + select GPIB_COMMON + select GPIB_TMS9914 + depends on BROKEN + depends on ISA_BUS || EISA + help + GPIB driver for HP82341 A/B/C/D boards + + To compile this driver as a module, choose M here: the module will be + called hp82341 + +config GPIB_INES + tristate "INES" + depends on PCI || ISA_BUS || PCMCIA + depends on HAS_IOPORT + select GPIB_COMMON + select GPIB_NEC7210 + help + GPIB driver for Ines compatible boards + Ines + GPIB-HS-NT + GPIB for Compact PCI + GPIB for PCI + GPIB for PCMCIA + GPIB PC/104 + Hameg + HO80-2 + Quancom + PCIGPIB-1 based on Ines iGPIB 72010 chip + + To compile this driver as a module, choose M here: the module will be + called ines_gpib + called cb7210. + +config GPIB_PCMCIA + bool "PCMCIA/Cardbus support for NI MC and Ines boards" + depends on PCCARD && (GPIB_NI_PCI_ISA || GPIB_CB7210 || GPIB_INES) + help + Enable PCMCIA/CArdbus support for National Instruments, + measurement computing boards and Ines boards. + +config GPIB_LPVO + tristate "LPVO DIY USB GPIB" + select GPIB_COMMON + depends on USB + help + Enable support for LPVO Self-made usb-gpib adapter + + To compile this driver as a module, choose M here: the module will be + called lpvo_usb_gpib + +config GPIB_PC2 + tristate "PC2 PC2a" + depends on ISA_BUS + depends on HAS_IOPORT + select GPIB_COMMON + select GPIB_NEC7210 + help + Enable support for pc2 and pc2a compatible adapters + Capital Equipment Corporation PC-488 + CONTEC GP-IB(PC) + Hameg HO80 + Iotech GP488B + Keithly MBC-488 + Measurement Computing ISA-GPIB-PCA2 + National Instruments PCII, PCIIa and PCII/IIa + + To compile this driver as a module, choose M here: the module will be + called pc2_gpib + + +config GPIB_TMS9914 + tristate + select GPIB_COMMON + help + Enable support for TMS 9914 chip. + + To compile this driver as a module, choose M here: the module will be + called tms9914 + +config GPIB_NEC7210 + tristate + select GPIB_COMMON + help + Enable support for NEC 7210 compatible chips. + + To compile this driver as a module, choose M here: the module will be + called nec7210 + +endif # GPIB diff --git a/drivers/staging/gpib/Makefile b/drivers/staging/gpib/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d0e88f5c08444ddb477e26f40fa26dcdc20bcd92 --- /dev/null +++ b/drivers/staging/gpib/Makefile @@ -0,0 +1,20 @@ + +subdir-ccflags-y += -I$(src)/include -I$(src)/uapi + +obj-$(CONFIG_GPIB_AGILENT_82350B) += agilent_82350b/ +obj-$(CONFIG_GPIB_AGILENT_82357A) += agilent_82357a/ +obj-$(CONFIG_GPIB_CB7210) += cb7210/ +obj-$(CONFIG_GPIB_CEC_PCI) += cec/ +obj-$(CONFIG_GPIB_COMMON) += common/ +obj-$(CONFIG_GPIB_FLUKE) += eastwood/ +obj-$(CONFIG_GPIB_FMH) += fmh_gpib/ +obj-$(CONFIG_GPIB_GPIO) += gpio/ +obj-$(CONFIG_GPIB_HP82335) += hp_82335/ +obj-$(CONFIG_GPIB_HP82341) += hp_82341/ +obj-$(CONFIG_GPIB_INES) += ines/ +obj-$(CONFIG_GPIB_LPVO) += lpvo_usb_gpib/ +obj-$(CONFIG_GPIB_NEC7210) += nec7210/ +obj-$(CONFIG_GPIB_NI_USB) += ni_usb/ +obj-$(CONFIG_GPIB_PC2) += pc2/ +obj-$(CONFIG_GPIB_TMS9914) += tms9914/ +obj-$(CONFIG_GPIB_NI_PCI_ISA) += tnt4882/ diff --git a/drivers/staging/gpib/TODO b/drivers/staging/gpib/TODO new file mode 100644 index 0000000000000000000000000000000000000000..bf2c3974254872f0d5bce1f061ccf4b2680d78e3 --- /dev/null +++ b/drivers/staging/gpib/TODO @@ -0,0 +1,21 @@ +TODO: +- checkpatch.pl fixes +- fix device drivers that are broken ("depends on BROKEN" in Kconfig) +- tidy-up comments: + - there are some "//comments" and "// comments" scattered around + - sometimes they are misaligned + - sometimes "// comments" are interleaved with "/* comments */" + - multiline comments should start with initial almost-blank line: + /* + * Good + * multiline + * comment + */ + /* Bad + * multiline + * comment + */ +- resolve XXX notes where possible +- fix FIXME notes +- clean-up commented-out code +- fix typos diff --git a/drivers/staging/gpib/agilent_82350b/Makefile b/drivers/staging/gpib/agilent_82350b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d9236c92e04be45bab3c92c34c3af9bfcf3ec32d --- /dev/null +++ b/drivers/staging/gpib/agilent_82350b/Makefile @@ -0,0 +1,2 @@ + +obj-m += agilent_82350b.o diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c new file mode 100644 index 0000000000000000000000000000000000000000..53006d0cc79c5dd2200d2e7bcd48b978b88a5740 --- /dev/null +++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c @@ -0,0 +1,932 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2002, 2004 by Frank Mori Hess * + ***************************************************************************/ + +#include "agilent_82350b.h" +#include <linux/delay.h> +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/dma.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/wait.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for Agilent 82350b"); + +int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; + int retval = 0; + unsigned short event_status; + int i, num_fifo_bytes; + //hardware doesn't support checking for end-of-string character when using fifo + if (tms_priv->eos_flags & REOS) { + //pr_info("ag-rd: using tms9914 read for REOS %x EOS %x\n",tms_priv->eos_flags, + // tms_priv->eos); + return tms9914_read(board, tms_priv, buffer, length, end, bytes_read); + } + + clear_bit(DEV_CLEAR_BN, &tms_priv->state); + + read_and_clear_event_status(board); + *end = 0; + *bytes_read = 0; + if (length == 0) + return 0; + //disable fifo for the moment + writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + // handle corner case of board not in holdoff and one byte might slip in early + if (tms_priv->holdoff_active == 0 && length > 1) { + size_t num_bytes; + + retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + dev_err(board->gpib_dev, "%s: tms9914_read failed retval=%i\n", + driver_name, retval); + if (retval < 0 || *end) + return retval; + ++buffer; + --length; + } + tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI); + tms9914_release_holdoff(tms_priv); + i = 0; + num_fifo_bytes = length - 1; + write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BIIE, IMR0); // disable BI interrupts + while (i < num_fifo_bytes && *end == 0) { + int block_size; + int j; + int count; + + if (num_fifo_bytes - i < agilent_82350b_fifo_size) + block_size = num_fifo_bytes - i; + else + block_size = agilent_82350b_fifo_size; + set_transfer_counter(a_priv, block_size); + writeb(ENABLE_TI_TO_SRAM | DIRECTION_GPIB_TO_HOST, + a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + if (agilent_82350b_fifo_is_halted(a_priv)) + writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG); + + clear_bit(READ_READY_BN, &tms_priv->state); + + retval = wait_event_interruptible(board->wait, + ((event_status = + read_and_clear_event_status(board)) & + (TERM_COUNT_STATUS_BIT | + BUFFER_END_STATUS_BIT)) || + test_bit(DEV_CLEAR_BN, &tms_priv->state) || + test_bit(TIMO_NUM, &board->status)); + if (retval) { + dev_dbg(board->gpib_dev, "%s: read wait interrupted\n", driver_name); + retval = -ERESTARTSYS; + break; + } + count = block_size - read_transfer_counter(a_priv); + for (j = 0; j < count && i < num_fifo_bytes; ++j) + buffer[i++] = readb(a_priv->sram_base + j); + if (event_status & BUFFER_END_STATUS_BIT) { + clear_bit(RECEIVED_END_BN, &tms_priv->state); + + tms_priv->holdoff_active = 1; + *end = 1; + } + if (test_bit(TIMO_NUM, &board->status)) { + dev_err(board->gpib_dev, "%s: read timed out\n", driver_name); + retval = -ETIMEDOUT; + break; + } + if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { + dev_err(board->gpib_dev, "%s: device clear interrupted read\n", + driver_name); + retval = -EINTR; + break; + } + } + write_byte(tms_priv, tms_priv->imr0_bits, IMR0); // re-enable BI interrupts + *bytes_read += i; + buffer += i; + length -= i; + writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + if (retval < 0) + return retval; + // read last bytes if we havn't received an END yet + if (*end == 0) { + size_t num_bytes; + // try to make sure we holdoff after last byte read + retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + return retval; + } + return 0; +} + +static int translate_wait_return_value(gpib_board_t *board, int retval) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; + + if (retval) { + dev_err(board->gpib_dev, "%s: write wait interrupted\n", driver_name); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) { + dev_err(board->gpib_dev, "%s: write timed out\n", driver_name); + return -ETIMEDOUT; + } + if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { + dev_err(board->gpib_dev, "%s: device clear interrupted write\n", driver_name); + return -EINTR; + } + return 0; +} + +int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; + int i, j; + unsigned short event_status; + int retval = 0; + int fifotransferlength = length; + int block_size = 0; + size_t num_bytes; + + *bytes_written = 0; + if (send_eoi) + --fifotransferlength; + + clear_bit(DEV_CLEAR_BN, &tms_priv->state); + + writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + + event_status = read_and_clear_event_status(board); + + //pr_info("ag_ac_wr: event status 0x%x tms state 0x%lx\n", event_status, tms_priv->state); + +#ifdef EXPERIMENTAL + pr_info("ag_ac_wr: wait for previous BO to complete if any\n"); + retval = wait_event_interruptible(board->wait, + test_bit(DEV_CLEAR_BN, &tms_priv->state) || + test_bit(WRITE_READY_BN, &tms_priv->state) || + test_bit(TIMO_NUM, &board->status)); + retval = translate_wait_return_value(board, retval); + + if (retval) + return retval; +#endif + + //pr_info("ag_ac_wr: sending first byte\n"); + retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + + //pr_info("ag_ac_wr: %ld bytes eoi %d tms state 0x%lx\n",length, send_eoi, tms_priv->state); + + write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BOIE, IMR0); + for (i = 1; i < fifotransferlength;) { + clear_bit(WRITE_READY_BN, &tms_priv->state); + + if (fifotransferlength - i < agilent_82350b_fifo_size) + block_size = fifotransferlength - i; + else + block_size = agilent_82350b_fifo_size; + set_transfer_counter(a_priv, block_size); + for (j = 0; j < block_size; ++j, ++i) { + // load data into board's sram + writeb(buffer[i], a_priv->sram_base + j); + } + writeb(ENABLE_TI_TO_SRAM, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + + //pr_info("ag_ac_wr: send block: %d bytes tms 0x%lx\n", block_size, + // tms_priv->state); + + if (agilent_82350b_fifo_is_halted(a_priv)) { + writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG); + // pr_info("ag_ac_wr: needed restart\n"); + } + + retval = wait_event_interruptible(board->wait, + ((event_status = + read_and_clear_event_status(board)) & + TERM_COUNT_STATUS_BIT) || + test_bit(DEV_CLEAR_BN, &tms_priv->state) || + test_bit(TIMO_NUM, &board->status)); + writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + num_bytes = block_size - read_transfer_counter(a_priv); + //pr_info("ag_ac_wr: sent %ld bytes tms 0x%lx\n", num_bytes, tms_priv->state); + + *bytes_written += num_bytes; + retval = translate_wait_return_value(board, retval); + if (retval) + break; + } + write_byte(tms_priv, tms_priv->imr0_bits, IMR0); + if (retval) + return retval; + + if (send_eoi) { + //pr_info("ag_ac_wr: sending last byte with eoi byte no: %d\n", + // fifotransferlength+1); + + retval = agilent_82350b_write(board, buffer + fifotransferlength, 1, send_eoi, + &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + } + return 0; +} + +unsigned short read_and_clear_event_status(gpib_board_t *board) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + unsigned long flags; + unsigned short status; + + spin_lock_irqsave(&board->spinlock, flags); + status = a_priv->event_status_bits; + a_priv->event_status_bits = 0; + spin_unlock_irqrestore(&board->spinlock, flags); + return status; +} + +irqreturn_t agilent_82350b_interrupt(int irq, void *arg) + +{ + int tms9914_status1 = 0, tms9914_status2 = 0; + int event_status; + gpib_board_t *board = arg; + struct agilent_82350b_priv *a_priv = board->private_data; + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + + spin_lock_irqsave(&board->spinlock, flags); + event_status = readb(a_priv->gpib_base + EVENT_STATUS_REG); + if (event_status & IRQ_STATUS_BIT) + retval = IRQ_HANDLED; + + if (event_status & TMS9914_IRQ_STATUS_BIT) { + tms9914_status1 = read_byte(&a_priv->tms9914_priv, ISR0); + tms9914_status2 = read_byte(&a_priv->tms9914_priv, ISR1); + tms9914_interrupt_have_status(board, &a_priv->tms9914_priv, tms9914_status1, + tms9914_status2); + } +//pr_info("event_status=0x%x s1 %x s2 %x\n", event_status,tms9914_status1,tms9914_status2); +//write-clear status bits + if (event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT)) { + writeb(event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT), + a_priv->gpib_base + EVENT_STATUS_REG); + a_priv->event_status_bits |= event_status; + wake_up_interruptible(&board->wait); + } + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +void agilent_82350b_detach(gpib_board_t *board); + +const char *driver_name = "agilent_82350b"; + +int read_transfer_counter(struct agilent_82350b_priv *a_priv) + +{ + int lo, mid, value; + + lo = readb(a_priv->gpib_base + XFER_COUNT_LO_REG); + mid = readb(a_priv->gpib_base + XFER_COUNT_MID_REG); + value = (lo & 0xff) | ((mid << 8) & 0x7f00); + value = ~(value - 1) & 0x7fff; + return value; +} + +void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count) + +{ + int complement = -count; + + writeb(complement & 0xff, a_priv->gpib_base + XFER_COUNT_LO_REG); + writeb((complement >> 8) & 0xff, a_priv->gpib_base + XFER_COUNT_MID_REG); + //I don't think the hi count reg is even used, but oh well + writeb((complement >> 16) & 0xf, a_priv->gpib_base + XFER_COUNT_HI_REG); +} + +// wrappers for interface functions +int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); +} + +int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); +} + +int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); +} + +int agilent_82350b_take_control(gpib_board_t *board, int synchronous) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_take_control_workaround(board, &priv->tms9914_priv, synchronous); +} + +int agilent_82350b_go_to_standby(gpib_board_t *board) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_go_to_standby(board, &priv->tms9914_priv); +} + +void agilent_82350b_request_system_control(gpib_board_t *board, int request_control) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + + if (request_control) { + a_priv->card_mode_bits |= CM_SYSTEM_CONTROLLER_BIT; + if (a_priv->model != MODEL_82350A) + writeb(IC_SYSTEM_CONTROLLER_BIT, a_priv->gpib_base + INTERNAL_CONFIG_REG); + } else { + a_priv->card_mode_bits &= ~CM_SYSTEM_CONTROLLER_BIT; + if (a_priv->model != MODEL_82350A) + writeb(0, a_priv->gpib_base + INTERNAL_CONFIG_REG); + } + writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG); + tms9914_request_system_control(board, &a_priv->tms9914_priv, request_control); +} + +void agilent_82350b_interface_clear(gpib_board_t *board, int assert) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_interface_clear(board, &priv->tms9914_priv, assert); +} + +void agilent_82350b_remote_enable(gpib_board_t *board, int enable) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_remote_enable(board, &priv->tms9914_priv, enable); +} + +int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); +} + +void agilent_82350b_disable_eos(gpib_board_t *board) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_disable_eos(board, &priv->tms9914_priv); +} + +unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); +} + +int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_primary_address(board, &priv->tms9914_priv, address); +} + +int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int enable) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); +} + +int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_parallel_poll(board, &priv->tms9914_priv, result); +} + +void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); +} + +void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); +} + +void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_serial_poll_response(board, &priv->tms9914_priv, status); +} + +uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_serial_poll_status(board, &priv->tms9914_priv); +} + +int agilent_82350b_line_status(const gpib_board_t *board) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + return tms9914_line_status(board, &priv->tms9914_priv); +} + +unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + static const int nanosec_per_clock = 30; + unsigned int value; + + tms9914_t1_delay(board, &a_priv->tms9914_priv, nanosec); + + value = (nanosec + nanosec_per_clock - 1) / nanosec_per_clock; + if (value > 0xff) + value = 0xff; + writeb(value, a_priv->gpib_base + T1_DELAY_REG); + return value * nanosec_per_clock; +} + +void agilent_82350b_return_to_local(gpib_board_t *board) + +{ + struct agilent_82350b_priv *priv = board->private_data; + + tms9914_return_to_local(board, &priv->tms9914_priv); +} + +int agilent_82350b_allocate_private(gpib_board_t *board) + +{ + board->private_data = kzalloc(sizeof(struct agilent_82350b_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + return 0; +} + +void agilent_82350b_free_private(gpib_board_t *board) + +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t *config) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + static const unsigned int firmware_length = 5302; + unsigned int borg_status; + static const unsigned int timeout = 1000; + int i, j; + const char *firmware_data = config->init_data; + const unsigned int plx_cntrl_static_bits = PLX9050_WAITO_NOT_USER0_SELECT_BIT | + PLX9050_USER0_OUTPUT_BIT | + PLX9050_LLOCK_NOT_USER1_SELECT_BIT | + PLX9050_USER1_OUTPUT_BIT | + PLX9050_USER2_OUTPUT_BIT | + PLX9050_USER3_OUTPUT_BIT | + PLX9050_PCI_READ_MODE_BIT | + PLX9050_PCI_WRITE_MODE_BIT | + PLX9050_PCI_RETRY_DELAY_BITS(64) | + PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT; + +// load borg data + borg_status = readb(a_priv->borg_base); + if ((borg_status & BORG_DONE_BIT)) + return 0; + // need to programme borg + if (!config->init_data || config->init_data_length != firmware_length) { + dev_err(board->gpib_dev, "%s: the 82350A board requires firmware after powering on.\n", + driver_name); + return -EIO; + } + dev_info(board->gpib_dev, "%s: Loading firmware...\n", driver_name); + + // tickle the borg + writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT, + a_priv->plx_base + PLX9050_CNTRL_REG); + usleep_range(1000, 2000); + writel(plx_cntrl_static_bits, a_priv->plx_base + PLX9050_CNTRL_REG); + usleep_range(1000, 2000); + writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT, + a_priv->plx_base + PLX9050_CNTRL_REG); + usleep_range(1000, 2000); + + for (i = 0; i < config->init_data_length; ++i) { + for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_READY_BIT) == 0; ++j) { + if (need_resched()) + schedule(); + usleep_range(10, 20); + } + if (j == timeout) { + dev_err(board->gpib_dev, "%s: timed out loading firmware.\n", driver_name); + return -ETIMEDOUT; + } + writeb(firmware_data[i], a_priv->gpib_base + CONFIG_DATA_REG); + } + for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_DONE_BIT) == 0; ++j) { + if (need_resched()) + schedule(); + usleep_range(10, 20); + } + if (j == timeout) { + dev_err(board->gpib_dev, "%s: timed out waiting for firmware load to complete.\n", + driver_name); + return -ETIMEDOUT; + } + dev_info(board->gpib_dev, "%s: ...done.\n", driver_name); + return 0; +} + +static int test_sram(gpib_board_t *board) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + unsigned int i; + const unsigned int sram_length = pci_resource_len(a_priv->pci_device, SRAM_82350A_REGION); + // test SRAM + const unsigned int byte_mask = 0xff; + + for (i = 0; i < sram_length; ++i) { + writeb(i & byte_mask, a_priv->sram_base + i); + if (need_resched()) + schedule(); + } + for (i = 0; i < sram_length; ++i) { + unsigned int read_value = readb(a_priv->sram_base + i); + + if ((i & byte_mask) != read_value) { + dev_err(board->gpib_dev, "%s: SRAM test failed at %d wanted %d got %d\n", + driver_name, i, (i & byte_mask), read_value); + return -EIO; + } + if (need_resched()) + schedule(); + } + dev_info(board->gpib_dev, "%s: SRAM test passed 0x%x bytes checked\n", + driver_name, sram_length); + return 0; +} + +static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_config_t *config, + int use_fifos) + +{ + struct agilent_82350b_priv *a_priv; + struct tms9914_priv *tms_priv; + int retval; + + board->status = 0; + + if (agilent_82350b_allocate_private(board)) + return -ENOMEM; + a_priv = board->private_data; + a_priv->using_fifos = use_fifos; + tms_priv = &a_priv->tms9914_priv; + tms_priv->read_byte = tms9914_iomem_read_byte; + tms_priv->write_byte = tms9914_iomem_write_byte; + tms_priv->offset = 1; + + // find board + a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT, + PCI_DEVICE_ID_82350B, NULL); + if (a_priv->pci_device) { + a_priv->model = MODEL_82350B; + dev_info(board->gpib_dev, "%s: Agilent 82350B board found\n", driver_name); + + } else { + a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT, + PCI_DEVICE_ID_82351A, NULL); + if (a_priv->pci_device) { + a_priv->model = MODEL_82351A; + dev_info(board->gpib_dev, "%s: Agilent 82351B board found\n", driver_name); + + } else { + a_priv->pci_device = gpib_pci_get_subsys(config, PCI_VENDOR_ID_PLX, + PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_HP, + PCI_SUBDEVICE_ID_82350A, + a_priv->pci_device); + if (a_priv->pci_device) { + a_priv->model = MODEL_82350A; + dev_info(board->gpib_dev, "%s: HP/Agilent 82350A board found\n", + driver_name); + } else { + dev_err(board->gpib_dev, "%s: no 82350/82351 board found\n", + driver_name); + return -ENODEV; + } + } + } + if (pci_enable_device(a_priv->pci_device)) { + dev_err(board->gpib_dev, "%s: error enabling pci device\n", driver_name); + return -EIO; + } + if (pci_request_regions(a_priv->pci_device, driver_name)) + return -EIO; + switch (a_priv->model) { + case MODEL_82350A: + a_priv->plx_base = ioremap(pci_resource_start(a_priv->pci_device, PLX_MEM_REGION), + pci_resource_len(a_priv->pci_device, PLX_MEM_REGION)); + dev_dbg(board->gpib_dev, "%s: plx base address remapped to 0x%p\n", + driver_name, a_priv->plx_base); + a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, + GPIB_82350A_REGION), + pci_resource_len(a_priv->pci_device, + GPIB_82350A_REGION)); + dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n", + driver_name, a_priv->gpib_base); + tms_priv->iobase = a_priv->gpib_base + TMS9914_BASE_REG; + a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, + SRAM_82350A_REGION), + pci_resource_len(a_priv->pci_device, + SRAM_82350A_REGION)); + dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n", + driver_name, a_priv->sram_base); + a_priv->borg_base = ioremap(pci_resource_start(a_priv->pci_device, + BORG_82350A_REGION), + pci_resource_len(a_priv->pci_device, + BORG_82350A_REGION)); + dev_dbg(board->gpib_dev, "%s: borg base address remapped to 0x%p\n", + driver_name, a_priv->borg_base); + + retval = init_82350a_hardware(board, config); + if (retval < 0) + return retval; + break; + case MODEL_82350B: + case MODEL_82351A: + a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, GPIB_REGION), + pci_resource_len(a_priv->pci_device, GPIB_REGION)); + dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n", + driver_name, a_priv->gpib_base); + tms_priv->iobase = a_priv->gpib_base + TMS9914_BASE_REG; + a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, SRAM_REGION), + pci_resource_len(a_priv->pci_device, SRAM_REGION)); + dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n", + driver_name, a_priv->sram_base); + a_priv->misc_base = ioremap(pci_resource_start(a_priv->pci_device, MISC_REGION), + pci_resource_len(a_priv->pci_device, MISC_REGION)); + dev_dbg(board->gpib_dev, "%s: misc base address remapped to 0x%p\n", + driver_name, a_priv->misc_base); + break; + default: + pr_err("%s: invalid board\n", driver_name); + return -1; + } + + retval = test_sram(board); + if (retval < 0) + return retval; + + if (request_irq(a_priv->pci_device->irq, agilent_82350b_interrupt, + IRQF_SHARED, driver_name, board)) { + pr_err("%s: can't request IRQ %d\n", driver_name, a_priv->pci_device->irq); + return -EIO; + } + a_priv->irq = a_priv->pci_device->irq; + dev_dbg(board->gpib_dev, "%s: IRQ %d\n", driver_name, a_priv->irq); + + writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); + a_priv->card_mode_bits = ENABLE_PCI_IRQ_BIT; + writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG); + + if (a_priv->model == MODEL_82350A) { + // enable PCI interrupts for 82350a + writel(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR2_POLARITY_BIT | + PLX9050_PCI_INTR_EN_BIT, + a_priv->plx_base + PLX9050_INTCSR_REG); + } + + if (use_fifos) { + writeb(ENABLE_BUFFER_END_EVENTS_BIT | ENABLE_TERM_COUNT_EVENTS_BIT, + a_priv->gpib_base + EVENT_ENABLE_REG); + writeb(ENABLE_TERM_COUNT_INTERRUPT_BIT | ENABLE_BUFFER_END_INTERRUPT_BIT | + ENABLE_TMS9914_INTERRUPTS_BIT, a_priv->gpib_base + INTERRUPT_ENABLE_REG); + //write-clear event status bits + writeb(BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT, + a_priv->gpib_base + EVENT_STATUS_REG); + } else { + writeb(0, a_priv->gpib_base + EVENT_ENABLE_REG); + writeb(ENABLE_TMS9914_INTERRUPTS_BIT, + a_priv->gpib_base + INTERRUPT_ENABLE_REG); + } + board->t1_nano_sec = agilent_82350b_t1_delay(board, 2000); + tms9914_board_reset(tms_priv); + + tms9914_online(board, tms_priv); + + return 0; +} + +int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config) + +{ + return agilent_82350b_generic_attach(board, config, 0); +} + +int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config) + +{ + return agilent_82350b_generic_attach(board, config, 1); +} + +void agilent_82350b_detach(gpib_board_t *board) + +{ + struct agilent_82350b_priv *a_priv = board->private_data; + struct tms9914_priv *tms_priv; + + if (a_priv) { + if (a_priv->plx_base) // disable interrupts + writel(0, a_priv->plx_base + PLX9050_INTCSR_REG); + + tms_priv = &a_priv->tms9914_priv; + if (a_priv->irq) + free_irq(a_priv->irq, board); + if (a_priv->gpib_base) { + tms9914_board_reset(tms_priv); + if (a_priv->misc_base) + iounmap((void *)a_priv->misc_base); + if (a_priv->borg_base) + iounmap((void *)a_priv->borg_base); + if (a_priv->sram_base) + iounmap((void *)a_priv->sram_base); + if (a_priv->gpib_base) + iounmap((void *)a_priv->gpib_base); + if (a_priv->plx_base) + iounmap((void *)a_priv->plx_base); + pci_release_regions(a_priv->pci_device); + } + if (a_priv->pci_device) + pci_dev_put(a_priv->pci_device); + } + agilent_82350b_free_private(board); +} + +gpib_interface_t agilent_82350b_unaccel_interface = { +name: "agilent_82350b_unaccel", +attach : agilent_82350b_unaccel_attach, +detach : agilent_82350b_detach, +read : agilent_82350b_read, +write : agilent_82350b_write, +command : agilent_82350b_command, +request_system_control : agilent_82350b_request_system_control, +take_control : agilent_82350b_take_control, +go_to_standby : agilent_82350b_go_to_standby, +interface_clear : agilent_82350b_interface_clear, +remote_enable : agilent_82350b_remote_enable, +enable_eos : agilent_82350b_enable_eos, +disable_eos : agilent_82350b_disable_eos, +parallel_poll : agilent_82350b_parallel_poll, +parallel_poll_configure : agilent_82350b_parallel_poll_configure, +parallel_poll_response : agilent_82350b_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : agilent_82350b_line_status, +update_status : agilent_82350b_update_status, +primary_address : agilent_82350b_primary_address, +secondary_address : agilent_82350b_secondary_address, +serial_poll_response : agilent_82350b_serial_poll_response, +t1_delay : agilent_82350b_t1_delay, +return_to_local : agilent_82350b_return_to_local, +}; + +gpib_interface_t agilent_82350b_interface = { +name: "agilent_82350b", +attach : agilent_82350b_accel_attach, +detach : agilent_82350b_detach, +read : agilent_82350b_accel_read, +write : agilent_82350b_accel_write, +command : agilent_82350b_command, +request_system_control : agilent_82350b_request_system_control, +take_control : agilent_82350b_take_control, +go_to_standby : agilent_82350b_go_to_standby, +interface_clear : agilent_82350b_interface_clear, +remote_enable : agilent_82350b_remote_enable, +enable_eos : agilent_82350b_enable_eos, +disable_eos : agilent_82350b_disable_eos, +parallel_poll : agilent_82350b_parallel_poll, +parallel_poll_configure : agilent_82350b_parallel_poll_configure, +parallel_poll_response : agilent_82350b_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : agilent_82350b_line_status, +update_status : agilent_82350b_update_status, +primary_address : agilent_82350b_primary_address, +secondary_address : agilent_82350b_secondary_address, +serial_poll_response : agilent_82350b_serial_poll_response, +t1_delay : agilent_82350b_t1_delay, +return_to_local : agilent_82350b_return_to_local, +}; + +static int agilent_82350b_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) + +{ + return 0; +} + +static const struct pci_device_id agilent_82350b_pci_table[] = { + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_HP, + PCI_SUBDEVICE_ID_82350A, 0, 0, 0 }, + { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82350B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82351A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, agilent_82350b_pci_table); + +static struct pci_driver agilent_82350b_pci_driver = { + .name = "agilent_82350b", + .id_table = agilent_82350b_pci_table, + .probe = &agilent_82350b_pci_probe +}; + +static int __init agilent_82350b_init_module(void) + +{ + int result; + + result = pci_register_driver(&agilent_82350b_pci_driver); + if (result) { + pr_err("agilent_82350b: pci_driver_register failed!\n"); + return result; + } + + gpib_register_driver(&agilent_82350b_unaccel_interface, THIS_MODULE); + gpib_register_driver(&agilent_82350b_interface, THIS_MODULE); + return 0; +} + +static void __exit agilent_82350b_exit_module(void) + +{ + gpib_unregister_driver(&agilent_82350b_interface); + gpib_unregister_driver(&agilent_82350b_unaccel_interface); + + pci_unregister_driver(&agilent_82350b_pci_driver); +} + +module_init(agilent_82350b_init_module); +module_exit(agilent_82350b_exit_module); diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h new file mode 100644 index 0000000000000000000000000000000000000000..30683d67d170506910fc7934c2f38b20aa431781 --- /dev/null +++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002, 2004 by Frank Mori Hess * + ***************************************************************************/ + +#include "gpibP.h" +#include "plx9050.h" +#include "tms9914.h" + +enum pci_vendor_ids { + PCI_VENDOR_ID_AGILENT = 0x15bc, +}; + +enum pci_device_ids { + PCI_DEVICE_ID_82350B = 0x0b01, + PCI_DEVICE_ID_82351A = 0x1218 +}; + +enum pci_subdevice_ids { + PCI_SUBDEVICE_ID_82350A = 0x10b0, +}; + +enum pci_regions_82350a { + PLX_MEM_REGION = 0, + PLX_IO_REGION = 1, + GPIB_82350A_REGION = 2, + SRAM_82350A_REGION = 3, + BORG_82350A_REGION = 4 +}; + +enum pci_regions_82350b { + GPIB_REGION = 0, + SRAM_REGION = 1, + MISC_REGION = 2, +}; + +enum board_model { + MODEL_82350A, + MODEL_82350B, + MODEL_82351A +}; + +// struct which defines private_data for board +struct agilent_82350b_priv { + struct tms9914_priv tms9914_priv; + struct pci_dev *pci_device; + void *plx_base; //82350a only + void *gpib_base; + void *sram_base; + void *misc_base; + void *borg_base; + int irq; + unsigned short card_mode_bits; + unsigned short event_status_bits; + enum board_model model; + bool using_fifos; +}; + +// driver name +extern const char *driver_name; + +// interfaces +extern gpib_interface_t agilent_82350b_interface; +// init functions + +int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config); +int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config); + +// interface functions +int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read); +int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); +int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read); +int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); +int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written); +int agilent_82350b_take_control(gpib_board_t *board, int synchronous); +int agilent_82350b_go_to_standby(gpib_board_t *board); +void agilent_82350b_request_system_control(gpib_board_t *board, int request_control); +void agilent_82350b_interface_clear(gpib_board_t *board, int assert); +void agilent_82350b_remote_enable(gpib_board_t *board, int enable); +int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int + compare_8_bits); +void agilent_82350b_disable_eos(gpib_board_t *board); +unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask); +int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address); +int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int + enable); +int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result); +void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config); +void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist); +void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status); +void agilent_82350b_return_to_local(gpib_board_t *board); +uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board); +int agilent_82350b_line_status(const gpib_board_t *board); +unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec); + +// interrupt service routines +irqreturn_t agilent_82350b_interrupt(int irq, void *arg); + +// utility functions +int agilent_82350b_allocate_private(gpib_board_t *board); +void agilent_82350b_free_private(gpib_board_t *board); +unsigned short read_and_clear_event_status(gpib_board_t *board); +int read_transfer_counter(struct agilent_82350b_priv *a_priv); +void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count); + +//registers +enum agilent_82350b_gpib_registers + +{ + CARD_MODE_REG = 0x1, + CONFIG_DATA_REG = 0x2, // 82350A specific + INTERRUPT_ENABLE_REG = 0x3, + EVENT_STATUS_REG = 0x4, + EVENT_ENABLE_REG = 0x5, + STREAM_STATUS_REG = 0x7, + DEBUG_RAM0_REG = 0x8, + DEBUG_RAM1_REG = 0x9, + DEBUG_RAM2_REG = 0xa, + DEBUG_RAM3_REG = 0xb, + XFER_COUNT_LO_REG = 0xc, + XFER_COUNT_MID_REG = 0xd, + XFER_COUNT_HI_REG = 0xe, + TMS9914_BASE_REG = 0x10, + INTERNAL_CONFIG_REG = 0x18, + IMR0_READ_REG = 0x19, //read + T1_DELAY_REG = 0x19, // write + IMR1_READ_REG = 0x1a, + ADR_READ_REG = 0x1b, + SPMR_READ_REG = 0x1c, + PPR_READ_REG = 0x1d, + CDOR_READ_REG = 0x1e, + SRAM_ACCESS_CONTROL_REG = 0x1f, +}; + +enum card_mode_bits + +{ + ACTIVE_CONTROLLER_BIT = 0x2, // read-only + CM_SYSTEM_CONTROLLER_BIT = 0x8, + ENABLE_BUS_MONITOR_BIT = 0x10, + ENABLE_PCI_IRQ_BIT = 0x20, +}; + +enum interrupt_enable_bits + +{ + ENABLE_TMS9914_INTERRUPTS_BIT = 0x1, + ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10, + ENABLE_TERM_COUNT_INTERRUPT_BIT = 0x20, +}; + +enum event_enable_bits + +{ + ENABLE_BUFFER_END_EVENTS_BIT = 0x10, + ENABLE_TERM_COUNT_EVENTS_BIT = 0x20, +}; + +enum event_status_bits + +{ + TMS9914_IRQ_STATUS_BIT = 0x1, + IRQ_STATUS_BIT = 0x2, + BUFFER_END_STATUS_BIT = 0x10, // write-clear + TERM_COUNT_STATUS_BIT = 0x20, // write-clear +}; + +enum stream_status_bits + +{ + HALTED_STATUS_BIT = 0x1, //read + RESTART_STREAM_BIT = 0x1, //write +}; + +enum internal_config_bits + +{ + IC_SYSTEM_CONTROLLER_BIT = 0x80, +}; + +enum sram_access_control_bits + +{ + DIRECTION_GPIB_TO_HOST = 0x20, // transfer direction + ENABLE_TI_TO_SRAM = 0x40, // enable fifo + ENABLE_FAST_TALKER = 0x80 // added for 82350A (not used) +}; + +enum borg_bits + +{ + BORG_READY_BIT = 0x40, + BORG_DONE_BIT = 0x80 +}; + +static const int agilent_82350b_fifo_size = 0x8000; + +static inline int agilent_82350b_fifo_is_halted(struct agilent_82350b_priv *a_priv) + +{ + return readb(a_priv->gpib_base + STREAM_STATUS_REG) & HALTED_STATUS_BIT; +} + diff --git a/drivers/staging/gpib/agilent_82357a/Makefile b/drivers/staging/gpib/agilent_82357a/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4a1d940fce2b83508012274c9df6dad2d42844c6 --- /dev/null +++ b/drivers/staging/gpib/agilent_82357a/Makefile @@ -0,0 +1,4 @@ + +obj-m += agilent_82357a.o + + diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c new file mode 100644 index 0000000000000000000000000000000000000000..bf05fb4a736b3f4b7f9b12e3cac4d1b53a6cd49c --- /dev/null +++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c @@ -0,0 +1,1712 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * driver for Agilent 82357A/B usb to gpib adapters * + * copyright : (C) 2004 by Frank Mori Hess * + ***************************************************************************/ + +#define _GNU_SOURCE + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include "agilent_82357a.h" +#include "gpibP.h" +#include "tms9914.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for Agilent 82357A/B usb adapters"); + +#define MAX_NUM_82357A_INTERFACES 128 +static struct usb_interface *agilent_82357a_driver_interfaces[MAX_NUM_82357A_INTERFACES]; +DEFINE_MUTEX(agilent_82357a_hotplug_lock); // protect board insertion and removal + +static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask); + +static int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous); + +static void agilent_82357a_bulk_complete(struct urb *urb) +{ + struct agilent_82357a_urb_ctx *context = urb->context; + + up(&context->complete); +} + +static void agilent_82357a_timeout_handler(struct timer_list *t) +{ + struct agilent_82357a_priv *a_priv = from_timer(a_priv, t, bulk_timer); + struct agilent_82357a_urb_ctx *context = &a_priv->context; + + context->timed_out = 1; + up(&context->complete); +} + +static int agilent_82357a_send_bulk_msg(struct agilent_82357a_priv *a_priv, void *data, + int data_length, int *actual_data_length, + int timeout_msecs) +{ + struct usb_device *usb_dev; + int retval; + unsigned int out_pipe; + struct agilent_82357a_urb_ctx *context = &a_priv->context; + + *actual_data_length = 0; + retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock); + if (retval) + return retval; + if (!a_priv->bus_interface) { + mutex_unlock(&a_priv->bulk_alloc_lock); + return -ENODEV; + } + if (a_priv->bulk_urb) { + mutex_unlock(&a_priv->bulk_alloc_lock); + return -EAGAIN; + } + a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!a_priv->bulk_urb) { + mutex_unlock(&a_priv->bulk_alloc_lock); + return -ENOMEM; + } + usb_dev = interface_to_usbdev(a_priv->bus_interface); + out_pipe = usb_sndbulkpipe(usb_dev, a_priv->bulk_out_endpoint); + sema_init(&context->complete, 0); + context->timed_out = 0; + usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, out_pipe, data, data_length, + &agilent_82357a_bulk_complete, context); + + if (timeout_msecs) + mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); + + retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL); + if (retval) { + dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", + __func__, retval); + mutex_unlock(&a_priv->bulk_alloc_lock); + goto cleanup; + } + mutex_unlock(&a_priv->bulk_alloc_lock); + if (down_interruptible(&context->complete)) { + dev_err(&usb_dev->dev, "%s: interrupted\n", __func__); + retval = -ERESTARTSYS; + goto cleanup; + } + if (context->timed_out) { + retval = -ETIMEDOUT; + } else { + retval = a_priv->bulk_urb->status; + *actual_data_length = a_priv->bulk_urb->actual_length; + } +cleanup: + if (timeout_msecs) { + if (timer_pending(&a_priv->bulk_timer)) + del_timer_sync(&a_priv->bulk_timer); + } + mutex_lock(&a_priv->bulk_alloc_lock); + if (a_priv->bulk_urb) { + usb_kill_urb(a_priv->bulk_urb); + usb_free_urb(a_priv->bulk_urb); + a_priv->bulk_urb = NULL; + } + mutex_unlock(&a_priv->bulk_alloc_lock); + return retval; +} + +static int agilent_82357a_receive_bulk_msg(struct agilent_82357a_priv *a_priv, void *data, + int data_length, int *actual_data_length, + int timeout_msecs) +{ + struct usb_device *usb_dev; + int retval; + unsigned int in_pipe; + struct agilent_82357a_urb_ctx *context = &a_priv->context; + + *actual_data_length = 0; + retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock); + if (retval) + return retval; + if (!a_priv->bus_interface) { + mutex_unlock(&a_priv->bulk_alloc_lock); + return -ENODEV; + } + if (a_priv->bulk_urb) { + mutex_unlock(&a_priv->bulk_alloc_lock); + return -EAGAIN; + } + a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!a_priv->bulk_urb) { + mutex_unlock(&a_priv->bulk_alloc_lock); + return -ENOMEM; + } + usb_dev = interface_to_usbdev(a_priv->bus_interface); + in_pipe = usb_rcvbulkpipe(usb_dev, AGILENT_82357_BULK_IN_ENDPOINT); + sema_init(&context->complete, 0); + context->timed_out = 0; + usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, in_pipe, data, data_length, + &agilent_82357a_bulk_complete, context); + + if (timeout_msecs) + mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); + + retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL); + if (retval) { + dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", + __func__, retval); + mutex_unlock(&a_priv->bulk_alloc_lock); + goto cleanup; + } + mutex_unlock(&a_priv->bulk_alloc_lock); + if (down_interruptible(&context->complete)) { + dev_err(&usb_dev->dev, "%s: interrupted\n", __func__); + retval = -ERESTARTSYS; + goto cleanup; + } + if (context->timed_out) { + retval = -ETIMEDOUT; + goto cleanup; + } + retval = a_priv->bulk_urb->status; + *actual_data_length = a_priv->bulk_urb->actual_length; +cleanup: + if (timeout_msecs) + del_timer_sync(&a_priv->bulk_timer); + + mutex_lock(&a_priv->bulk_alloc_lock); + if (a_priv->bulk_urb) { + usb_kill_urb(a_priv->bulk_urb); + usb_free_urb(a_priv->bulk_urb); + a_priv->bulk_urb = NULL; + } + mutex_unlock(&a_priv->bulk_alloc_lock); + return retval; +} + +static int agilent_82357a_receive_control_msg(struct agilent_82357a_priv *a_priv, __u8 request, + __u8 requesttype, __u16 value, __u16 index, + void *data, __u16 size, int timeout_msecs) +{ + struct usb_device *usb_dev; + int retval; + unsigned int in_pipe; + + retval = mutex_lock_interruptible(&a_priv->control_alloc_lock); + if (retval) + return retval; + if (!a_priv->bus_interface) { + mutex_unlock(&a_priv->control_alloc_lock); + return -ENODEV; + } + usb_dev = interface_to_usbdev(a_priv->bus_interface); + in_pipe = usb_rcvctrlpipe(usb_dev, AGILENT_82357_CONTROL_ENDPOINT); + retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data, + size, timeout_msecs); + mutex_unlock(&a_priv->control_alloc_lock); + return retval; +} + +static void agilent_82357a_dump_raw_block(const u8 *raw_data, int length) +{ + pr_info("hex block dump\n"); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true); +} + +static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv, + const struct agilent_82357a_register_pairlet *writes, + int num_writes) +{ + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + int retval; + u8 *out_data, *in_data; + int out_data_length, in_data_length; + int bytes_written, bytes_read; + int i = 0; + int j; + static const int bytes_per_write = 2; + static const int header_length = 2; + static const int max_writes = 31; + + if (num_writes > max_writes) { + dev_err(&usb_dev->dev, "%s: bug! num_writes=%i too large\n", __func__, num_writes); + return -EIO; + } + out_data_length = num_writes * bytes_per_write + header_length; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + + out_data[i++] = DATA_PIPE_CMD_WR_REGS; + out_data[i++] = num_writes; + for (j = 0; j < num_writes; j++) { + out_data[i++] = writes[j].address; + out_data[i++] = writes[j].value; + } + if (i > out_data_length) + dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__); + retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); + if (retval) { + kfree(out_data); + return retval; + } + retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + mutex_unlock(&a_priv->bulk_transfer_lock); + return retval; + } + in_data_length = 0x20; + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&a_priv->bulk_transfer_lock); + return -ENOMEM; + } + retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length, + &bytes_read, 1000); + mutex_unlock(&a_priv->bulk_transfer_lock); + + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + agilent_82357a_dump_raw_block(in_data, bytes_read); + kfree(in_data); + return -EIO; + } + if (in_data[0] != (0xff & ~DATA_PIPE_CMD_WR_REGS)) { + dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_WR_REGS\n", + __func__, in_data[0]); + return -EIO; + } + if (in_data[1]) { + dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_WR_REGS response\n", + __func__, in_data[1]); + return -EIO; + } + kfree(in_data); + return 0; +} + +static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv, + struct agilent_82357a_register_pairlet *reads, + int num_reads, int blocking) +{ + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + int retval; + u8 *out_data, *in_data; + int out_data_length, in_data_length; + int bytes_written, bytes_read; + int i = 0; + int j; + static const int header_length = 2; + static const int max_reads = 62; + + if (num_reads > max_reads) + dev_err(&usb_dev->dev, "%s: bug! num_reads=%i too large\n", __func__, num_reads); + + out_data_length = num_reads + header_length; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + + out_data[i++] = DATA_PIPE_CMD_RD_REGS; + out_data[i++] = num_reads; + for (j = 0; j < num_reads; j++) + out_data[i++] = reads[j].address; + if (i > out_data_length) + dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__); + if (blocking) { + retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); + if (retval) { + kfree(out_data); + return retval; + } + } else { + retval = mutex_trylock(&a_priv->bulk_transfer_lock); + if (retval == 0) { + kfree(out_data); + return -EAGAIN; + } + } + retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + mutex_unlock(&a_priv->bulk_transfer_lock); + return retval; + } + in_data_length = 0x20; + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&a_priv->bulk_transfer_lock); + return -ENOMEM; + } + retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length, + &bytes_read, 10000); + mutex_unlock(&a_priv->bulk_transfer_lock); + + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + agilent_82357a_dump_raw_block(in_data, bytes_read); + kfree(in_data); + return -EIO; + } + i = 0; + if (in_data[i++] != (0xff & ~DATA_PIPE_CMD_RD_REGS)) { + dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_RD_REGS\n", + __func__, in_data[0]); + return -EIO; + } + if (in_data[i++]) { + dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_RD_REGS response\n", + __func__, in_data[1]); + return -EIO; + } + for (j = 0; j < num_reads; j++) + reads[j].value = in_data[i++]; + kfree(in_data); + return 0; +} + +static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush) +{ + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + int retval = 0; + int receive_control_retval; + u16 wIndex = 0; + u8 *status_data; + static const unsigned int status_data_len = 2; + + status_data = kmalloc(status_data_len, GFP_KERNEL); + if (!status_data) + return -ENOMEM; + + if (flush) + wIndex |= XA_FLUSH; + receive_control_retval = agilent_82357a_receive_control_msg(a_priv, + agilent_82357a_control_request, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, XFER_ABORT, + wIndex, status_data, + status_data_len, 100); + if (receive_control_retval < 0) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n", + __func__, receive_control_retval); + retval = -EIO; + goto cleanup; + } + if (status_data[0] != (~XFER_ABORT & 0xff)) { + dev_err(&usb_dev->dev, "%s: error, major code=0x%x != ~XFER_ABORT\n", + __func__, status_data[0]); + retval = -EIO; + goto cleanup; + } + switch (status_data[1]) { + case UGP_SUCCESS: + retval = 0; + break; + case UGP_ERR_FLUSHING: + if (flush) { + retval = 0; + break; + } + fallthrough; + case UGP_ERR_FLUSHING_ALREADY: + default: + dev_err(&usb_dev->dev, "%s: abort returned error code=0x%x\n", + __func__, status_data[1]); + retval = -EIO; + break; + } + +cleanup: + kfree(status_data); + return retval; +} + +// interface functions +int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written); + +static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *nbytes) +{ + int retval; + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + u8 *out_data, *in_data; + int out_data_length, in_data_length; + int bytes_written, bytes_read; + int i = 0; + u8 trailing_flags; + unsigned long start_jiffies = jiffies; + int msec_timeout; + + *nbytes = 0; + *end = 0; + out_data_length = 0x9; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + out_data[i++] = DATA_PIPE_CMD_READ; + out_data[i++] = 0; //primary address when ARF_NO_ADDR is not set + out_data[i++] = 0; //secondary address when ARF_NO_ADDR is not set + out_data[i] = ARF_NO_ADDRESS | ARF_END_ON_EOI; + if (a_priv->eos_mode & REOS) + out_data[i] |= ARF_END_ON_EOS_CHAR; + ++i; + out_data[i++] = length & 0xff; + out_data[i++] = (length >> 8) & 0xff; + out_data[i++] = (length >> 16) & 0xff; + out_data[i++] = (length >> 24) & 0xff; + out_data[i++] = a_priv->eos_char; + msec_timeout = (board->usec_timeout + 999) / 1000; + retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); + if (retval) { + kfree(out_data); + return retval; + } + retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, msec_timeout); + kfree(out_data); + if (retval || bytes_written != i) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + mutex_unlock(&a_priv->bulk_transfer_lock); + if (retval < 0) + return retval; + return -EIO; + } + in_data_length = length + 1; + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&a_priv->bulk_transfer_lock); + return -ENOMEM; + } + if (board->usec_timeout != 0) + msec_timeout -= jiffies_to_msecs(jiffies - start_jiffies) - 1; + if (msec_timeout >= 0) { + retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length, + &bytes_read, msec_timeout); + } else { + retval = -ETIMEDOUT; + bytes_read = 0; + } + if (retval == -ETIMEDOUT) { + int extra_bytes_read; + int extra_bytes_retval; + + agilent_82357a_abort(a_priv, 1); + extra_bytes_retval = agilent_82357a_receive_bulk_msg(a_priv, in_data + bytes_read, + in_data_length - bytes_read, + &extra_bytes_read, 100); + bytes_read += extra_bytes_read; + if (extra_bytes_retval) { + dev_err(&usb_dev->dev, "%s: extra_bytes_retval=%i, bytes_read=%i\n", + __func__, extra_bytes_retval, bytes_read); + agilent_82357a_abort(a_priv, 0); + } + } else if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + agilent_82357a_abort(a_priv, 0); + } + mutex_unlock(&a_priv->bulk_transfer_lock); + if (bytes_read > length + 1) { + bytes_read = length + 1; + pr_warn("%s: bytes_read > length? truncating", __func__); + } + + if (bytes_read >= 1) { + memcpy(buffer, in_data, bytes_read - 1); + trailing_flags = in_data[bytes_read - 1]; + *nbytes = bytes_read - 1; + if (trailing_flags & (ATRF_EOI | ATRF_EOS)) + *end = 1; + } + kfree(in_data); + + /* Fix for a bug in 9914A that does not return the contents of ADSR + * when the board is in listener active state and ATN is not asserted. + * Set ATN here to obtain a valid board level ibsta + */ + agilent_82357a_take_control_internal(board, 0); + + //FIXME check trailing flags for error + return retval; +} + +static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_commands, int send_eoi, size_t *bytes_written) +{ + int retval; + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + u8 *out_data = NULL; + u8 *status_data = NULL; + int out_data_length; + int raw_bytes_written; + int i = 0, j; + int msec_timeout; + unsigned short bsr, adsr; + struct agilent_82357a_register_pairlet read_reg; + + *bytes_written = 0; + out_data_length = length + 0x8; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + out_data[i++] = DATA_PIPE_CMD_WRITE; + out_data[i++] = 0; // primary address when AWF_NO_ADDRESS is not set + out_data[i++] = 0; // secondary address when AWF_NO_ADDRESS is not set + out_data[i] = AWF_NO_ADDRESS | AWF_NO_FAST_TALKER_FIRST_BYTE; + if (send_commands) + out_data[i] |= AWF_ATN | AWF_NO_FAST_TALKER; + if (send_eoi) + out_data[i] |= AWF_SEND_EOI; + ++i; + out_data[i++] = length & 0xff; + out_data[i++] = (length >> 8) & 0xff; + out_data[i++] = (length >> 16) & 0xff; + out_data[i++] = (length >> 24) & 0xff; + for (j = 0; j < length; j++) + out_data[i++] = buffer[j]; + + clear_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags); + + msec_timeout = (board->usec_timeout + 999) / 1000; + retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); + if (retval) { + kfree(out_data); + return retval; + } + retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &raw_bytes_written, + msec_timeout); + kfree(out_data); + if (retval || raw_bytes_written != i) { + agilent_82357a_abort(a_priv, 0); + dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, raw_bytes_written=%i, i=%i\n", + __func__, retval, raw_bytes_written, i); + mutex_unlock(&a_priv->bulk_transfer_lock); + if (retval < 0) + return retval; + return -EIO; + } + + retval = wait_event_interruptible(board->wait, + test_bit(AIF_WRITE_COMPLETE_BN, + &a_priv->interrupt_flags) || + test_bit(TIMO_NUM, &board->status)); + if (retval) { + dev_err(&usb_dev->dev, "%s: wait write complete interrupted\n", __func__); + agilent_82357a_abort(a_priv, 0); + mutex_unlock(&a_priv->bulk_transfer_lock); + return -ERESTARTSYS; + } + + if (test_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags) == 0) { + dev_dbg(&usb_dev->dev, "write timed out ibs %i, tmo %i\n", + test_bit(TIMO_NUM, &board->status), msec_timeout); + + agilent_82357a_abort(a_priv, 0); + + mutex_unlock(&a_priv->bulk_transfer_lock); + + read_reg.address = BSR; + retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return -ETIMEDOUT; + } + + bsr = read_reg.value; + dev_dbg(&usb_dev->dev, "write aborted bsr 0x%x\n", bsr); + + if (send_commands) {/* check for no listeners */ + if ((bsr & BSR_ATN_BIT) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) { + dev_dbg(&usb_dev->dev, "No listener on command\n"); + clear_bit(TIMO_NUM, &board->status); + return -ENOTCONN; // no listener on bus + } + } else { + read_reg.address = ADSR; + retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return -ETIMEDOUT; + } + adsr = read_reg.value; + if ((adsr & HR_TA) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) { + dev_dbg(&usb_dev->dev, "No listener on write\n"); + clear_bit(TIMO_NUM, &board->status); + return -ECOMM; + } + } + + return -ETIMEDOUT; + } + + status_data = kmalloc(STATUS_DATA_LEN, GFP_KERNEL); + if (!status_data) { + mutex_unlock(&a_priv->bulk_transfer_lock); + return -ENOMEM; + } + + retval = agilent_82357a_receive_control_msg(a_priv, agilent_82357a_control_request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + XFER_STATUS, 0, status_data, STATUS_DATA_LEN, + 100); + mutex_unlock(&a_priv->bulk_transfer_lock); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n", + __func__, retval); + kfree(status_data); + return -EIO; + } + *bytes_written = (u32)status_data[2]; + *bytes_written |= (u32)status_data[3] << 8; + *bytes_written |= (u32)status_data[4] << 16; + *bytes_written |= (u32)status_data[5] << 24; + + kfree(status_data); + return 0; +} + +static int agilent_82357a_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + return agilent_82357a_generic_write(board, buffer, length, 0, send_eoi, bytes_written); +} + +int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written) +{ + return agilent_82357a_generic_write(board, buffer, length, 1, 0, bytes_written); +} + +int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet write; + int retval; + + write.address = AUXCR; + if (synchronous) + write.value = AUX_TCS; + else + write.value = AUX_TCA; + retval = agilent_82357a_write_registers(a_priv, &write, 1); + if (retval) + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + + return retval; +} + +static int agilent_82357a_take_control(gpib_board_t *board, int synchronous) +{ + const int timeout = 10; + int i; + +/* It looks like the 9914 does not handle tcs properly. + * See comment above tms9914_take_control_workaround() in + * drivers/gpib/tms9914/tms9914_aux.c + */ + if (synchronous) + return -ETIMEDOUT; + + agilent_82357a_take_control_internal(board, synchronous); + // busy wait until ATN is asserted + for (i = 0; i < timeout; ++i) { + agilent_82357a_update_status(board, 0); + if (test_bit(ATN_NUM, &board->status)) + break; + udelay(1); + } + if (i == timeout) + return -ETIMEDOUT; + return 0; +} + +static int agilent_82357a_go_to_standby(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet write; + int retval; + + write.address = AUXCR; + write.value = AUX_GTS; + retval = agilent_82357a_write_registers(a_priv, &write, 1); + if (retval) + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return 0; +} + +//FIXME should change prototype to return int +static void agilent_82357a_request_system_control(gpib_board_t *board, int request_control) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet writes[2]; + int retval; + int i = 0; + + /* 82357B needs bit to be set in 9914 AUXCR register */ + writes[i].address = AUXCR; + if (request_control) { + writes[i].value = AUX_RQC; + a_priv->hw_control_bits |= SYSTEM_CONTROLLER; + } else { + writes[i].value = AUX_RLC; + a_priv->is_cic = 0; + a_priv->hw_control_bits &= ~SYSTEM_CONTROLLER; + } + ++i; + writes[i].address = HW_CONTROL; + writes[i].value = a_priv->hw_control_bits; + ++i; + retval = agilent_82357a_write_registers(a_priv, writes, i); + if (retval) + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return;// retval; +} + +static void agilent_82357a_interface_clear(gpib_board_t *board, int assert) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet write; + int retval; + + write.address = AUXCR; + write.value = AUX_SIC; + if (assert) { + write.value |= AUX_CS; + a_priv->is_cic = 1; + } + retval = agilent_82357a_write_registers(a_priv, &write, 1); + if (retval) + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); +} + +static void agilent_82357a_remote_enable(gpib_board_t *board, int enable) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet write; + int retval; + + write.address = AUXCR; + write.value = AUX_SRE; + if (enable) + write.value |= AUX_CS; + retval = agilent_82357a_write_registers(a_priv, &write, 1); + if (retval) + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + a_priv->ren_state = enable; + return;// 0; +} + +static int agilent_82357a_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + + if (compare_8_bits == 0) { + pr_warn("%s: hardware only supports 8-bit EOS compare", __func__); + return -EOPNOTSUPP; + } + a_priv->eos_char = eos_byte; + a_priv->eos_mode = REOS | BIN; + return 0; +} + +static void agilent_82357a_disable_eos(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + + a_priv->eos_mode &= ~REOS; +} + +static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet address_status, bus_status; + int retval; + + board->status &= ~clear_mask; + if (a_priv->is_cic) + set_bit(CIC_NUM, &board->status); + else + clear_bit(CIC_NUM, &board->status); + address_status.address = ADSR; + retval = agilent_82357a_read_registers(a_priv, &address_status, 1, 0); + if (retval) { + if (retval != -EAGAIN) + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return board->status; + } + // check for remote/local + if (address_status.value & HR_REM) + set_bit(REM_NUM, &board->status); + else + clear_bit(REM_NUM, &board->status); + // check for lockout + if (address_status.value & HR_LLO) + set_bit(LOK_NUM, &board->status); + else + clear_bit(LOK_NUM, &board->status); + // check for ATN + if (address_status.value & HR_ATN) + set_bit(ATN_NUM, &board->status); + else + clear_bit(ATN_NUM, &board->status); + // check for talker/listener addressed + if (address_status.value & HR_TA) + set_bit(TACS_NUM, &board->status); + else + clear_bit(TACS_NUM, &board->status); + if (address_status.value & HR_LA) + set_bit(LACS_NUM, &board->status); + else + clear_bit(LACS_NUM, &board->status); + + bus_status.address = BSR; + retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0); + if (retval) { + if (retval != -EAGAIN) + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return board->status; + } + if (bus_status.value & BSR_SRQ_BIT) + set_bit(SRQI_NUM, &board->status); + else + clear_bit(SRQI_NUM, &board->status); + + return board->status; +} + +static int agilent_82357a_primary_address(gpib_board_t *board, unsigned int address) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet write; + int retval; + + // put primary address in address0 + write.address = ADR; + write.value = address & ADDRESS_MASK; + retval = agilent_82357a_write_registers(a_priv, &write, 1); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return retval; + } + return retval; +} + +static int agilent_82357a_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + if (enable) + pr_warn("%s: warning: assigning a secondary address not supported\n", __func__); + return -EOPNOTSUPP; +} + +static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet writes[2]; + struct agilent_82357a_register_pairlet read; + int retval; + + // execute parallel poll + writes[0].address = AUXCR; + writes[0].value = AUX_CS | AUX_RPP; + writes[1].address = HW_CONTROL; + writes[1].value = a_priv->hw_control_bits & ~NOT_PARALLEL_POLL; + retval = agilent_82357a_write_registers(a_priv, writes, 2); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return retval; + } + udelay(2); //silly, since usb write will take way longer + read.address = CPTR; + retval = agilent_82357a_read_registers(a_priv, &read, 1, 1); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return retval; + } + *result = read.value; + // clear parallel poll state + writes[0].address = HW_CONTROL; + writes[0].value = a_priv->hw_control_bits | NOT_PARALLEL_POLL; + writes[1].address = AUXCR; + writes[1].value = AUX_RPP; + retval = agilent_82357a_write_registers(a_priv, writes, 2); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return retval; + } + return 0; +} + +static void agilent_82357a_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + //board can only be system controller + return;// 0; +} + +static void agilent_82357a_parallel_poll_response(gpib_board_t *board, int ist) +{ + //board can only be system controller + return;// 0; +} + +static void agilent_82357a_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + //board can only be system controller + return;// 0; +} + +static uint8_t agilent_82357a_serial_poll_status(gpib_board_t *board) +{ + //board can only be system controller + return 0; +} + +static void agilent_82357a_return_to_local(gpib_board_t *board) +{ + //board can only be system controller + return;// 0; +} + +static int agilent_82357a_line_status(const gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet bus_status; + int retval; + int status = ValidALL; + + bus_status.address = BSR; + retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0); + if (retval) { + if (retval != -EAGAIN) + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return retval; + } + if (bus_status.value & BSR_REN_BIT) + status |= BusREN; + if (bus_status.value & BSR_IFC_BIT) + status |= BusIFC; + if (bus_status.value & BSR_SRQ_BIT) + status |= BusSRQ; + if (bus_status.value & BSR_EOI_BIT) + status |= BusEOI; + if (bus_status.value & BSR_NRFD_BIT) + status |= BusNRFD; + if (bus_status.value & BSR_NDAC_BIT) + status |= BusNDAC; + if (bus_status.value & BSR_DAV_BIT) + status |= BusDAV; + if (bus_status.value & BSR_ATN_BIT) + status |= BusATN; + return status; +} + +static unsigned short nanosec_to_fast_talker_bits(unsigned int *nanosec) +{ + static const int nanosec_per_bit = 21; + static const int max_value = 0x72; + static const int min_value = 0x11; + unsigned short bits; + + bits = (*nanosec + nanosec_per_bit / 2) / nanosec_per_bit; + if (bits < min_value) + bits = min_value; + if (bits > max_value) + bits = max_value; + *nanosec = bits * nanosec_per_bit; + return bits; +} + +static unsigned int agilent_82357a_t1_delay(gpib_board_t *board, unsigned int nanosec) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet write; + int retval; + + write.address = FAST_TALKER_T1; + write.value = nanosec_to_fast_talker_bits(&nanosec); + retval = agilent_82357a_write_registers(a_priv, &write, 1); + if (retval) + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return nanosec; +} + +static void agilent_82357a_interrupt_complete(struct urb *urb) +{ + gpib_board_t *board = urb->context; + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + int retval; + u8 *transfer_buffer = urb->transfer_buffer; + unsigned long interrupt_flags; + + switch (urb->status) { + /* success */ + case 0: + break; + /* unlinked, don't resubmit */ + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* other error, resubmit */ + retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC); + if (retval) + dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); + return; + } + + interrupt_flags = transfer_buffer[0]; + if (test_bit(AIF_READ_COMPLETE_BN, &interrupt_flags)) + set_bit(AIF_READ_COMPLETE_BN, &a_priv->interrupt_flags); + if (test_bit(AIF_WRITE_COMPLETE_BN, &interrupt_flags)) + set_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags); + if (test_bit(AIF_SRQ_BN, &interrupt_flags)) + set_bit(SRQI_NUM, &board->status); + + wake_up_interruptible(&board->wait); + + retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC); + if (retval) + dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); +} + +static int agilent_82357a_setup_urbs(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev; + int int_pipe; + int retval; + + retval = mutex_lock_interruptible(&a_priv->interrupt_alloc_lock); + if (retval) + return retval; + if (!a_priv->bus_interface) { + retval = -ENODEV; + goto setup_exit; + } + + a_priv->interrupt_buffer = kmalloc(INTERRUPT_BUF_LEN, GFP_KERNEL); + if (!a_priv->interrupt_buffer) { + retval = -ENOMEM; + goto setup_exit; + } + a_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!a_priv->interrupt_urb) { + retval = -ENOMEM; + goto setup_exit; + } + usb_dev = interface_to_usbdev(a_priv->bus_interface); + int_pipe = usb_rcvintpipe(usb_dev, a_priv->interrupt_in_endpoint); + usb_fill_int_urb(a_priv->interrupt_urb, usb_dev, int_pipe, a_priv->interrupt_buffer, + INTERRUPT_BUF_LEN, &agilent_82357a_interrupt_complete, board, 1); + retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL); + if (retval) { + usb_free_urb(a_priv->interrupt_urb); + a_priv->interrupt_urb = NULL; + dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n", + __func__, retval); + goto setup_exit; + } + mutex_unlock(&a_priv->interrupt_alloc_lock); + return 0; + +setup_exit: + kfree(a_priv->interrupt_buffer); + mutex_unlock(&a_priv->interrupt_alloc_lock); + return retval; +} + +#ifdef RESET_USB_CONFIG +static int agilent_82357a_reset_usb_configuration(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct usb_device *usb_dev; + int retval; + + if (!a_priv->bus_interface) + return -ENODEV; + usb_dev = interface_to_usbdev(a_priv->bus_interface); + retval = usb_reset_configuration(usb_dev); + if (retval) + dev_err(&usb_dev->dev, "%s: usb_reset_configuration() returned %i\n", + __func__, retval); + return retval; +} +#endif + +static void agilent_82357a_cleanup_urbs(struct agilent_82357a_priv *a_priv) +{ + if (a_priv && a_priv->bus_interface) { + if (a_priv->interrupt_urb) + usb_kill_urb(a_priv->interrupt_urb); + if (a_priv->bulk_urb) + usb_kill_urb(a_priv->bulk_urb); + } +}; + +static int agilent_82357a_allocate_private(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv; + + board->private_data = kmalloc(sizeof(struct agilent_82357a_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + a_priv = board->private_data; + memset(a_priv, 0, sizeof(struct agilent_82357a_priv)); + mutex_init(&a_priv->bulk_transfer_lock); + mutex_init(&a_priv->bulk_alloc_lock); + mutex_init(&a_priv->control_alloc_lock); + mutex_init(&a_priv->interrupt_alloc_lock); + return 0; +} + +static void agilent_82357a_free_private(struct agilent_82357a_priv *a_priv) +{ + usb_free_urb(a_priv->interrupt_urb); + kfree(a_priv->interrupt_buffer); + kfree(a_priv); +} + +static int agilent_82357a_init(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet hw_control; + struct agilent_82357a_register_pairlet writes[0x20]; + int retval; + int i; + unsigned int nanosec; + + i = 0; + writes[i].address = LED_CONTROL; + writes[i].value = FAIL_LED_ON; + ++i; + writes[i].address = RESET_TO_POWERUP; + writes[i].value = RESET_SPACEBALL; + ++i; + retval = agilent_82357a_write_registers(a_priv, writes, i); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return -EIO; + } + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(usec_to_jiffies(2000))) + return -ERESTARTSYS; + i = 0; + writes[i].address = AUXCR; + writes[i].value = AUX_NBAF; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_HLDE; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_TON; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_LON; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_RSV2; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_INVAL; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_RPP; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_STDL; + ++i; + writes[i].address = AUXCR; + writes[i].value = AUX_VSTDL; + ++i; + writes[i].address = FAST_TALKER_T1; + nanosec = board->t1_nano_sec; + writes[i].value = nanosec_to_fast_talker_bits(&nanosec); + board->t1_nano_sec = nanosec; + ++i; + writes[i].address = ADR; + writes[i].value = board->pad & ADDRESS_MASK; + ++i; + writes[i].address = PPR; + writes[i].value = 0; + ++i; + writes[i].address = SPMR; + writes[i].value = 0; + ++i; + writes[i].address = PROTOCOL_CONTROL; + writes[i].value = WRITE_COMPLETE_INTERRUPT_EN; + ++i; + writes[i].address = IMR0; + writes[i].value = HR_BOIE | HR_BIIE; + ++i; + writes[i].address = IMR1; + writes[i].value = HR_SRQIE; + ++i; + // turn off reset state + writes[i].address = AUXCR; + writes[i].value = AUX_CHIP_RESET; + ++i; + writes[i].address = LED_CONTROL; + writes[i].value = FIRMWARE_LED_CONTROL; + ++i; + if (i > ARRAY_SIZE(writes)) { + dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__); + return -EFAULT; + } + retval = agilent_82357a_write_registers(a_priv, writes, i); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return -EIO; + } + hw_control.address = HW_CONTROL; + retval = agilent_82357a_read_registers(a_priv, &hw_control, 1, 1); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n", + __func__); + return -EIO; + } + a_priv->hw_control_bits = (hw_control.value & ~0x7) | NOT_TI_RESET | NOT_PARALLEL_POLL; + + return 0; +} + +static inline int agilent_82357a_device_match(struct usb_interface *interface, + const gpib_board_config_t *config) +{ + struct usb_device * const usbdev = interface_to_usbdev(interface); + + if (gpib_match_device_path(&interface->dev, config->device_path) == 0) + return 0; + if (config->serial_number && + strcmp(usbdev->serial, config->serial_number) != 0) + return 0; + + return 1; +} + +static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + int retval; + int i; + unsigned int product_id; + struct agilent_82357a_priv *a_priv; + struct usb_device *usb_dev; + + if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock)) + return -ERESTARTSYS; + + retval = agilent_82357a_allocate_private(board); + if (retval < 0) { + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } + a_priv = board->private_data; + for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { + if (agilent_82357a_driver_interfaces[i] && + !usb_get_intfdata(agilent_82357a_driver_interfaces[i]) && + agilent_82357a_device_match(agilent_82357a_driver_interfaces[i], config)) { + a_priv->bus_interface = agilent_82357a_driver_interfaces[i]; + usb_set_intfdata(agilent_82357a_driver_interfaces[i], board); + usb_dev = interface_to_usbdev(a_priv->bus_interface); + dev_info(&usb_dev->dev, + "bus %d dev num %d attached to gpib minor %d, agilent usb interface %i\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + break; + } + } + if (i == MAX_NUM_82357A_INTERFACES) { + mutex_unlock(&agilent_82357a_hotplug_lock); + pr_err("No Agilent 82357 gpib adapters found, have you loaded its firmware?\n"); + return -ENODEV; + } + product_id = le16_to_cpu(interface_to_usbdev(a_priv->bus_interface)->descriptor.idProduct); + switch (product_id) { + case USB_DEVICE_ID_AGILENT_82357A: + a_priv->bulk_out_endpoint = AGILENT_82357A_BULK_OUT_ENDPOINT; + a_priv->interrupt_in_endpoint = AGILENT_82357A_INTERRUPT_IN_ENDPOINT; + break; + case USB_DEVICE_ID_AGILENT_82357B: + a_priv->bulk_out_endpoint = AGILENT_82357B_BULK_OUT_ENDPOINT; + a_priv->interrupt_in_endpoint = AGILENT_82357B_INTERRUPT_IN_ENDPOINT; + break; + default: + dev_err(&usb_dev->dev, "bug, unhandled product_id in switch?\n"); + return -EIO; + } +#ifdef RESET_USB_CONFIG + retval = agilent_82357a_reset_usb_configuration(board); + if (retval < 0) { + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } +#endif + retval = agilent_82357a_setup_urbs(board); + if (retval < 0) { + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } + + timer_setup(&a_priv->bulk_timer, agilent_82357a_timeout_handler, 0); + + board->t1_nano_sec = 800; + + retval = agilent_82357a_init(board); + + if (retval < 0) { + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } + + dev_info(&usb_dev->dev, "%s: attached\n", __func__); + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; +} + +static int agilent_82357a_go_idle(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); + struct agilent_82357a_register_pairlet writes[0x20]; + int retval; + int i; + + i = 0; + // turn on tms9914 reset state + writes[i].address = AUXCR; + writes[i].value = AUX_CS | AUX_CHIP_RESET; + ++i; + a_priv->hw_control_bits &= ~NOT_TI_RESET; + writes[i].address = HW_CONTROL; + writes[i].value = a_priv->hw_control_bits; + ++i; + writes[i].address = PROTOCOL_CONTROL; + writes[i].value = 0; + ++i; + writes[i].address = IMR0; + writes[i].value = 0; + ++i; + writes[i].address = IMR1; + writes[i].value = 0; + ++i; + writes[i].address = LED_CONTROL; + writes[i].value = 0; + ++i; + if (i > ARRAY_SIZE(writes)) { + dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__); + return -EFAULT; + } + retval = agilent_82357a_write_registers(a_priv, writes, i); + if (retval) { + dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n", + __func__); + return -EIO; + } + return 0; +} + +static void agilent_82357a_detach(gpib_board_t *board) +{ + struct agilent_82357a_priv *a_priv; + struct usb_device *usb_dev; + + mutex_lock(&agilent_82357a_hotplug_lock); + + a_priv = board->private_data; + usb_dev = interface_to_usbdev(a_priv->bus_interface); + if (a_priv) { + if (a_priv->bus_interface) { + agilent_82357a_go_idle(board); + usb_set_intfdata(a_priv->bus_interface, NULL); + } + mutex_lock(&a_priv->control_alloc_lock); + mutex_lock(&a_priv->bulk_alloc_lock); + mutex_lock(&a_priv->interrupt_alloc_lock); + agilent_82357a_cleanup_urbs(a_priv); + agilent_82357a_free_private(a_priv); + } + dev_info(&usb_dev->dev, "%s: detached\n", __func__); + mutex_unlock(&agilent_82357a_hotplug_lock); +} + +gpib_interface_t agilent_82357a_gpib_interface = { +name: "agilent_82357a", +attach : agilent_82357a_attach, +detach : agilent_82357a_detach, +read : agilent_82357a_read, +write : agilent_82357a_write, +command : agilent_82357a_command, +take_control : agilent_82357a_take_control, +go_to_standby : agilent_82357a_go_to_standby, +request_system_control : agilent_82357a_request_system_control, +interface_clear : agilent_82357a_interface_clear, +remote_enable : agilent_82357a_remote_enable, +enable_eos : agilent_82357a_enable_eos, +disable_eos : agilent_82357a_disable_eos, +parallel_poll : agilent_82357a_parallel_poll, +parallel_poll_configure : agilent_82357a_parallel_poll_configure, +parallel_poll_response : agilent_82357a_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : agilent_82357a_line_status, +update_status : agilent_82357a_update_status, +primary_address : agilent_82357a_primary_address, +secondary_address : agilent_82357a_secondary_address, +serial_poll_response : agilent_82357a_serial_poll_response, +serial_poll_status : agilent_82357a_serial_poll_status, +t1_delay : agilent_82357a_t1_delay, +return_to_local : agilent_82357a_return_to_local, +no_7_bit_eos : 1, +skip_check_for_command_acceptors : 1 +}; + +// Table with the USB-devices: just now only testing IDs +static struct usb_device_id agilent_82357a_driver_device_table[] = { + {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357A)}, + {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357B)}, + {} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, agilent_82357a_driver_device_table); + +static int agilent_82357a_driver_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int i; + char *path; + static const int path_length = 1024; + struct usb_device *usb_dev; + + if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock)) + return -ERESTARTSYS; + usb_dev = usb_get_dev(interface_to_usbdev(interface)); + for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { + if (!agilent_82357a_driver_interfaces[i]) { + agilent_82357a_driver_interfaces[i] = interface; + usb_set_intfdata(interface, NULL); + dev_dbg(&usb_dev->dev, "set bus interface %i to address 0x%p\n", + i, interface); + break; + } + } + if (i == MAX_NUM_82357A_INTERFACES) { + usb_put_dev(usb_dev); + mutex_unlock(&agilent_82357a_hotplug_lock); + dev_err(&usb_dev->dev, "%s: out of space in agilent_82357a_driver_interfaces[]\n", + __func__); + return -1; + } + path = kmalloc(path_length, GFP_KERNEL); + if (!path) { + usb_put_dev(usb_dev); + mutex_unlock(&agilent_82357a_hotplug_lock); + return -ENOMEM; + } + usb_make_path(usb_dev, path, path_length); + dev_info(&usb_dev->dev, "probe succeeded for path: %s\n", path); + kfree(path); + mutex_unlock(&agilent_82357a_hotplug_lock); + return 0; +} + +static void agilent_82357a_driver_disconnect(struct usb_interface *interface) +{ + int i; + struct usb_device *usb_dev = interface_to_usbdev(interface); + + mutex_lock(&agilent_82357a_hotplug_lock); + + for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { + if (agilent_82357a_driver_interfaces[i] == interface) { + gpib_board_t *board = usb_get_intfdata(interface); + + if (board) { + struct agilent_82357a_priv *a_priv = board->private_data; + + if (a_priv) { + mutex_lock(&a_priv->control_alloc_lock); + mutex_lock(&a_priv->bulk_alloc_lock); + mutex_lock(&a_priv->interrupt_alloc_lock); + agilent_82357a_cleanup_urbs(a_priv); + a_priv->bus_interface = NULL; + mutex_unlock(&a_priv->interrupt_alloc_lock); + mutex_unlock(&a_priv->bulk_alloc_lock); + mutex_unlock(&a_priv->control_alloc_lock); + } + } + dev_dbg(&usb_dev->dev, "nulled agilent_82357a_driver_interfaces[%i]\n", i); + agilent_82357a_driver_interfaces[i] = NULL; + break; + } + } + if (i == MAX_NUM_82357A_INTERFACES) + dev_err(&usb_dev->dev, "unable to find interface in agilent_82357a_driver_interfaces[]? bug?\n"); + usb_put_dev(usb_dev); + + mutex_unlock(&agilent_82357a_hotplug_lock); +} + +static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_message_t message) +{ + int i, retval; + struct usb_device *usb_dev = interface_to_usbdev(interface); + + mutex_lock(&agilent_82357a_hotplug_lock); + + for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { + if (agilent_82357a_driver_interfaces[i] == interface) { + gpib_board_t *board = usb_get_intfdata(interface); + + if (board) { + struct agilent_82357a_priv *a_priv = board->private_data; + + if (a_priv) { + agilent_82357a_abort(a_priv, 0); + agilent_82357a_abort(a_priv, 0); + retval = agilent_82357a_go_idle(board); + if (retval) { + dev_err(&usb_dev->dev, "%s: failed to go idle, retval=%i\n", + __func__, retval); + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } + mutex_lock(&a_priv->interrupt_alloc_lock); + agilent_82357a_cleanup_urbs(a_priv); + mutex_unlock(&a_priv->interrupt_alloc_lock); + dev_info(&usb_dev->dev, + "bus %d dev num %d gpib minor %d, agilent usb interface %i suspended\n", + usb_dev->bus->busnum, usb_dev->devnum, + board->minor, i); + } + } + break; + } + } + + mutex_unlock(&agilent_82357a_hotplug_lock); + + return 0; +} + +static int agilent_82357a_driver_resume(struct usb_interface *interface) +{ + struct usb_device *usb_dev = interface_to_usbdev(interface); + gpib_board_t *board; + int i, retval; + + mutex_lock(&agilent_82357a_hotplug_lock); + + for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { + if (agilent_82357a_driver_interfaces[i] == interface) { + board = usb_get_intfdata(interface); + if (board) + break; + } + } + if (i == MAX_NUM_82357A_INTERFACES) + goto resume_exit; + + struct agilent_82357a_priv *a_priv = board->private_data; + + if (a_priv) { + if (a_priv->interrupt_urb) { + mutex_lock(&a_priv->interrupt_alloc_lock); + retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL); + if (retval) { + dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n", + __func__, retval); + mutex_unlock(&a_priv->interrupt_alloc_lock); + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } + mutex_unlock(&a_priv->interrupt_alloc_lock); + } + retval = agilent_82357a_init(board); + if (retval < 0) { + mutex_unlock(&agilent_82357a_hotplug_lock); + return retval; + } + // set/unset system controller + agilent_82357a_request_system_control(board, board->master); + // toggle ifc if master + if (board->master) { + agilent_82357a_interface_clear(board, 1); + usleep_range(200, 250); + agilent_82357a_interface_clear(board, 0); + } + // assert/unassert REN + agilent_82357a_remote_enable(board, a_priv->ren_state); + + dev_info(&usb_dev->dev, + "bus %d dev num %d gpib minor %d, agilent usb interface %i resumed\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + } + +resume_exit: + mutex_unlock(&agilent_82357a_hotplug_lock); + + return 0; +} + +static struct usb_driver agilent_82357a_bus_driver = { + .name = "agilent_82357a_gpib", + .probe = agilent_82357a_driver_probe, + .disconnect = agilent_82357a_driver_disconnect, + .suspend = agilent_82357a_driver_suspend, + .resume = agilent_82357a_driver_resume, + .id_table = agilent_82357a_driver_device_table, +}; + +static int __init agilent_82357a_init_module(void) +{ + int i; + + pr_info("agilent_82357a_gpib driver loading"); + for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) + agilent_82357a_driver_interfaces[i] = NULL; + usb_register(&agilent_82357a_bus_driver); + gpib_register_driver(&agilent_82357a_gpib_interface, THIS_MODULE); + + return 0; +} + +static void __exit agilent_82357a_exit_module(void) +{ + pr_info("agilent_82357a_gpib driver unloading"); + gpib_unregister_driver(&agilent_82357a_gpib_interface); + usb_deregister(&agilent_82357a_bus_driver); +} + +module_init(agilent_82357a_init_module); +module_exit(agilent_82357a_exit_module); diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.h b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h new file mode 100644 index 0000000000000000000000000000000000000000..cdbc3ec5d8bd07e7b23ed9388a9c0be590b631f0 --- /dev/null +++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2004 by Frank Mori Hess * + ***************************************************************************/ + +#include <linux/kernel.h> +#include <linux/mutex.h> +#include <linux/semaphore.h> +#include <linux/usb.h> +#include <linux/timer.h> +#include <linux/compiler_attributes.h> +#include "gpibP.h" +#include "tms9914.h" + +enum usb_vendor_ids { + USB_VENDOR_ID_AGILENT = 0x0957 +}; + +enum usb_device_ids { + USB_DEVICE_ID_AGILENT_82357A = 0x0107, + USB_DEVICE_ID_AGILENT_82357A_PREINIT = 0x0007, // device id before firmware is loaded + USB_DEVICE_ID_AGILENT_82357B = 0x0718, // device id before firmware is loaded + USB_DEVICE_ID_AGILENT_82357B_PREINIT = 0x0518, // device id before firmware is loaded +}; + +enum endpoint_addresses { + AGILENT_82357_CONTROL_ENDPOINT = 0x0, + AGILENT_82357_BULK_IN_ENDPOINT = 0x2, + AGILENT_82357A_BULK_OUT_ENDPOINT = 0x4, + AGILENT_82357A_INTERRUPT_IN_ENDPOINT = 0x6, + AGILENT_82357B_BULK_OUT_ENDPOINT = 0x6, + AGILENT_82357B_INTERRUPT_IN_ENDPOINT = 0x8, +}; + +enum bulk_commands { + DATA_PIPE_CMD_WRITE = 0x1, + DATA_PIPE_CMD_READ = 0x3, + DATA_PIPE_CMD_WR_REGS = 0x4, + DATA_PIPE_CMD_RD_REGS = 0x5 +}; + +enum agilent_82357a_read_flags { + ARF_END_ON_EOI = 0x1, + ARF_NO_ADDRESS = 0x2, + ARF_END_ON_EOS_CHAR = 0x4, + ARF_SPOLL = 0x8 +}; + +enum agilent_82357a_trailing_read_flags { + ATRF_EOI = 0x1, + ATRF_ATN = 0x2, + ATRF_IFC = 0x4, + ATRF_EOS = 0x8, + ATRF_ABORT = 0x10, + ATRF_COUNT = 0x20, + ATRF_DEAD_BUS = 0x40, + ATRF_UNADDRESSED = 0x80 +}; + +enum agilent_82357a_write_flags { + AWF_SEND_EOI = 0x1, + AWF_NO_FAST_TALKER_FIRST_BYTE = 0x2, + AWF_NO_FAST_TALKER = 0x4, + AWF_NO_ADDRESS = 0x8, + AWF_ATN = 0x10, + AWF_SEPARATE_HEADER = 0x80 +}; + +enum agilent_82357a_interrupt_flag_bit_numbers { + AIF_SRQ_BN = 0, + AIF_WRITE_COMPLETE_BN = 1, + AIF_READ_COMPLETE_BN = 2, +}; + +enum agilent_82357_error_codes { + UGP_SUCCESS = 0, + UGP_ERR_INVALID_CMD = 1, + UGP_ERR_INVALID_PARAM = 2, + UGP_ERR_INVALID_REG = 3, + UGP_ERR_GPIB_READ = 4, + UGP_ERR_GPIB_WRITE = 5, + UGP_ERR_FLUSHING = 6, + UGP_ERR_FLUSHING_ALREADY = 7, + UGP_ERR_UNSUPPORTED = 8, + UGP_ERR_OTHER = 9 +}; + +enum agilent_82357_control_values { + XFER_ABORT = 0xa0, + XFER_STATUS = 0xb0, +}; + +enum xfer_status_bits { + XS_COMPLETED = 0x1, + XS_READ = 0x2, +}; + +enum xfer_status_completion_bits { + XSC_EOI = 0x1, + XSC_ATN = 0x2, + XSC_IFC = 0x4, + XSC_EOS = 0x8, + XSC_ABORT = 0x10, + XSC_COUNT = 0x20, + XSC_DEAD_BUS = 0x40, + XSC_BUS_NOT_ADDRESSED = 0x80 +}; + +enum xfer_abort_type { + XA_FLUSH = 0x1 +}; + +#define STATUS_DATA_LEN 8 +#define INTERRUPT_BUF_LEN 8 + +struct agilent_82357a_urb_ctx { + struct semaphore complete; + unsigned timed_out : 1; +}; + +// struct which defines local data for each 82357 device +struct agilent_82357a_priv { + struct usb_interface *bus_interface; + unsigned short eos_char; + unsigned short eos_mode; + unsigned short hw_control_bits; + unsigned long interrupt_flags; + struct urb *bulk_urb; + struct urb *interrupt_urb; + u8 *interrupt_buffer; + struct mutex bulk_transfer_lock; // bulk transfer lock + struct mutex bulk_alloc_lock; // bulk transfer allocation lock + struct mutex interrupt_alloc_lock; // interrupt allocation lock + struct mutex control_alloc_lock; // control message allocation lock + struct timer_list bulk_timer; + struct agilent_82357a_urb_ctx context; + unsigned int bulk_out_endpoint; + unsigned int interrupt_in_endpoint; + unsigned is_cic : 1; + unsigned ren_state : 1; +}; + +struct agilent_82357a_register_pairlet { + short address; + unsigned short value; +}; + +enum firmware_registers { + HW_CONTROL = 0xa, + LED_CONTROL = 0xb, + RESET_TO_POWERUP = 0xc, + PROTOCOL_CONTROL = 0xd, + FAST_TALKER_T1 = 0xe +}; + +enum hardware_control_bits { + NOT_TI_RESET = 0x1, + SYSTEM_CONTROLLER = 0x2, + NOT_PARALLEL_POLL = 0x4, + OSCILLATOR_5V_ON = 0x8, + OUTPUT_5V_ON = 0x20, + CPLD_3V_ON = 0x80, +}; + +enum led_control_bits { + FIRMWARE_LED_CONTROL = 0x1, + FAIL_LED_ON = 0x20, + READY_LED_ON = 0x40, + ACCESS_LED_ON = 0x80 +}; + +enum reset_to_powerup_bits { + RESET_SPACEBALL = 0x1, // wait 2 millisec after sending +}; + +enum protocol_control_bits { + WRITE_COMPLETE_INTERRUPT_EN = 0x1, +}; + +static const int agilent_82357a_control_request = 0x4; + diff --git a/drivers/staging/gpib/cb7210/Makefile b/drivers/staging/gpib/cb7210/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..22e0214fc17dcae470d4693856007e81d631ca42 --- /dev/null +++ b/drivers/staging/gpib/cb7210/Makefile @@ -0,0 +1,4 @@ +ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA +obj-m += cb7210.o + + diff --git a/drivers/staging/gpib/cb7210/cb7210.c b/drivers/staging/gpib/cb7210/cb7210.c new file mode 100644 index 0000000000000000000000000000000000000000..63df7f3eb3f3e73d9ba448fa9778b4a65214ac50 --- /dev/null +++ b/drivers/staging/gpib/cb7210/cb7210.c @@ -0,0 +1,1556 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * Measurement Computing boards using cb7210.2 and cbi488.2 chips + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "cb7210.h" +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/dma.h> +#include <linux/bitops.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/delay.h> +#include "gpib_pci_ids.h" +#include "quancom_pci.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver Measurement Computing boards using cb7210.2 and cbi488.2"); + +static inline int have_fifo_word(const struct cb7210_priv *cb_priv) +{ + if (((cb7210_read_byte(cb_priv, HS_STATUS)) & + (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) == + (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) + return 1; + else + return 0; +} + +static inline void input_fifo_enable(gpib_board_t *board, int enable) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + + if (enable) { + cb_priv->in_fifo_half_full = 0; + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + + cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT | + HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits, + HS_MODE); + + cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); + + cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL); + + cb_priv->hs_mode_bits |= HS_RX_ENABLE; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); + } else { + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + + cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, nec7210_iobase(cb_priv) + + HS_MODE); + + clear_bit(READ_READY_BN, &nec_priv->state); + } + + spin_unlock_irqrestore(&board->spinlock, flags); +} + +static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval = 0; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + int hs_status; + u16 word; + unsigned long flags; + + *bytes_read = 0; + if (cb_priv->fifo_iobase == 0) { + pr_err("cb7210: fifo iobase is zero!\n"); + return -EIO; + } + *end = 0; + if (length <= cb7210_fifo_size) { + pr_err("cb7210: bug! %s with length < fifo size\n", __func__); + return -EINVAL; + } + + input_fifo_enable(board, 1); + + while (*bytes_read + cb7210_fifo_size < length) { + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); + + if (wait_event_interruptible(board->wait, + (cb_priv->in_fifo_half_full && + have_fifo_word(cb_priv)) || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_warn("cb7210: fifo half full wait interrupted\n"); + retval = -ERESTARTSYS; + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + break; + } + + spin_lock_irqsave(&board->spinlock, flags); + + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + + while (have_fifo_word(cb_priv)) { + word = inw(cb_priv->fifo_iobase + DIR); + buffer[(*bytes_read)++] = word & 0xff; + buffer[(*bytes_read)++] = (word >> 8) & 0xff; + } + + cb_priv->in_fifo_half_full = 0; + + hs_status = cb7210_read_byte(cb_priv, HS_STATUS); + + spin_unlock_irqrestore(&board->spinlock, flags); + + if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) { + *end = 1; + break; + } + if (hs_status & HS_FIFO_FULL) + break; + if (test_bit(TIMO_NUM, &board->status)) { + retval = -ETIMEDOUT; + break; + } + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { + retval = -EINTR; + break; + } + } + hs_status = cb7210_read_byte(cb_priv, HS_STATUS); + if (hs_status & HS_RX_LSB_NOT_EMPTY) { + word = inw(cb_priv->fifo_iobase + DIR); + buffer[(*bytes_read)++] = word & 0xff; + } + + input_fifo_enable(board, 0); + + if (wait_event_interruptible(board->wait, + test_bit(READ_READY_BN, &nec_priv->state) || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_warn("cb7210: fifo half full wait interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + if (test_bit(READ_READY_BN, &nec_priv->state)) { + nec7210_set_handshake_mode(board, nec_priv, HR_HLDA); + buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end); + } + + return retval; +} + +int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval; + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + size_t num_bytes; + + *bytes_read = 0; + // deal with limitations of fifo + if (length < cb7210_fifo_size + 3 || (nec_priv->auxa_bits & HR_REOS)) + return cb7210_read(board, buffer, length, end, bytes_read); + *end = 0; + + nec7210_release_rfd_holdoff(board, nec_priv); + + if (wait_event_interruptible(board->wait, + test_bit(READ_READY_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_warn("cb7210: read ready wait interrupted\n"); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + return -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + return -EINTR; + + nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); + buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end); + if (*end) + return 0; + + nec7210_release_rfd_holdoff(board, nec_priv); + + retval = fifo_read(board, cb_priv, &buffer[*bytes_read], length - *bytes_read - 1, + end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + return retval; + if (*end) + return 0; + + retval = cb7210_read(board, &buffer[*bytes_read], 1, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + return retval; + + return 0; +} + +static int output_fifo_empty(const struct cb7210_priv *cb_priv) +{ + if ((cb7210_read_byte(cb_priv, HS_STATUS) & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY)) + == 0) + return 1; + else + return 0; +} + +static inline void output_fifo_enable(gpib_board_t *board, int enable) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + + if (enable) { + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); + + cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT | + HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits, + HS_MODE); + + cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; + cb_priv->hs_mode_bits |= HS_TX_ENABLE; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); + + cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL); + + clear_bit(WRITE_READY_BN, &nec_priv->state); + + } else { + cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); + + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE); + } + + spin_unlock_irqrestore(&board->spinlock, flags); +} + +static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + size_t count = 0; + ssize_t retval = 0; + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + unsigned int num_bytes, i; + unsigned long flags; + + *bytes_written = 0; + if (cb_priv->fifo_iobase == 0) { + pr_err("cb7210: fifo iobase is zero!\n"); + return -EINVAL; + } + if (length == 0) + return 0; + + clear_bit(DEV_CLEAR_BN, &nec_priv->state); + clear_bit(BUS_ERROR_BN, &nec_priv->state); + + output_fifo_enable(board, 1); + + while (count < length) { + // wait until byte is ready to be sent + if (wait_event_interruptible(board->wait, + cb_priv->out_fifo_half_empty || + output_fifo_empty(cb_priv) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_warn("cb7210: fifo wait interrupted\n"); + retval = -ERESTARTSYS; + break; + } + if (test_bit(TIMO_NUM, &board->status) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(BUS_ERROR_BN, &nec_priv->state)) + break; + + if (output_fifo_empty(cb_priv)) + num_bytes = cb7210_fifo_size - cb7210_fifo_width; + else + num_bytes = cb7210_fifo_size / 2; + if (num_bytes + count > length) + num_bytes = length - count; + if (num_bytes % cb7210_fifo_width) { + pr_err("cb7210: bug! %s with odd number of bytes\n", __func__); + retval = -EINVAL; + break; + } + + spin_lock_irqsave(&board->spinlock, flags); + for (i = 0; i < num_bytes / cb7210_fifo_width; i++) { + u16 word; + + word = buffer[count++] & 0xff; + word |= (buffer[count++] << 8) & 0xff00; + outw(word, cb_priv->fifo_iobase + CDOR); + } + cb_priv->out_fifo_half_empty = 0; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits | + HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE); + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); + spin_unlock_irqrestore(&board->spinlock, flags); + } + // wait last byte has been sent + if (wait_event_interruptible(board->wait, + output_fifo_empty(cb_priv) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_err("cb7210: wait for last byte interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_bit(BUS_ERROR_BN, &nec_priv->state)) + retval = -EIO; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + + output_fifo_enable(board, 0); + + *bytes_written = count; + return retval; +} + +int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + unsigned long fast_chunk_size, leftover; + int retval; + size_t num_bytes; + + *bytes_written = 0; + if (length > cb7210_fifo_width) + fast_chunk_size = length - 1; + else + fast_chunk_size = 0; + fast_chunk_size -= fast_chunk_size % cb7210_fifo_width; + leftover = length - fast_chunk_size; + + retval = fifo_write(board, buffer, fast_chunk_size, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + + retval = nec7210_write(board, nec_priv, buffer + fast_chunk_size, leftover, + send_eoi, &num_bytes); + *bytes_written += num_bytes; + return retval; +} + +int cb7210_line_status(const gpib_board_t *board) +{ + int status = ValidALL; + int bsr_bits; + struct cb7210_priv *cb_priv; + struct nec7210_priv *nec_priv; + + cb_priv = board->private_data; + nec_priv = &cb_priv->nec7210_priv; + + bsr_bits = cb7210_paged_read_byte(cb_priv, BUS_STATUS, BUS_STATUS_PAGE); + + if ((bsr_bits & BSR_REN_BIT) == 0) + status |= BusREN; + if ((bsr_bits & BSR_IFC_BIT) == 0) + status |= BusIFC; + if ((bsr_bits & BSR_SRQ_BIT) == 0) + status |= BusSRQ; + if ((bsr_bits & BSR_EOI_BIT) == 0) + status |= BusEOI; + if ((bsr_bits & BSR_NRFD_BIT) == 0) + status |= BusNRFD; + if ((bsr_bits & BSR_NDAC_BIT) == 0) + status |= BusNDAC; + if ((bsr_bits & BSR_DAV_BIT) == 0) + status |= BusDAV; + if ((bsr_bits & BSR_ATN_BIT) == 0) + status |= BusATN; + + return status; +} + +unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + unsigned int retval; + + retval = nec7210_t1_delay(board, nec_priv, nano_sec); + + if (nano_sec <= 350) { + write_byte(nec_priv, AUX_HI_SPEED, AUXMR); + retval = 350; + } else { + write_byte(nec_priv, AUX_LO_SPEED, AUXMR); + } + return retval; +} + +irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board); + +/* + * GPIB interrupt service routines + */ + +irqreturn_t cb_pci_interrupt(int irq, void *arg) +{ + int bits; + gpib_board_t *board = arg; + struct cb7210_priv *priv = board->private_data; + + // first task check if this is really our interrupt in a shared irq environment + switch (priv->pci_chip) { + case PCI_CHIP_AMCC_S5933: + if ((inl(priv->amcc_iobase + INTCSR_REG) & + (INBOX_INTR_CS_BIT | INTR_ASSERTED_BIT)) == 0) + return IRQ_NONE; + + // read incoming mailbox to clear mailbox full flag + inl(priv->amcc_iobase + INCOMING_MAILBOX_REG(3)); + // clear amccs5933 interrupt + bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) | + INBOX_SELECT_BITS(3) | INBOX_INTR_CS_BIT; + outl(bits, priv->amcc_iobase + INTCSR_REG); + break; + case PCI_CHIP_QUANCOM: + if ((inb(nec7210_iobase(priv) + QUANCOM_IRQ_CONTROL_STATUS_REG) & + QUANCOM_IRQ_ASSERTED_BIT)) + outb(QUANCOM_IRQ_ENABLE_BIT, nec7210_iobase(priv) + + QUANCOM_IRQ_CONTROL_STATUS_REG); + break; + default: + break; + } + return cb7210_locked_internal_interrupt(arg); +} + +irqreturn_t cb7210_internal_interrupt(gpib_board_t *board) +{ + int hs_status, status1, status2; + struct cb7210_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + int clear_bits; + + if ((priv->hs_mode_bits & HS_ENABLE_MASK)) { + status1 = 0; + hs_status = cb7210_read_byte(priv, HS_STATUS); + } else { + hs_status = 0; + status1 = read_byte(nec_priv, ISR1); + } + status2 = read_byte(nec_priv, ISR2); + nec7210_interrupt_have_status(board, nec_priv, status1, status2); + + dev_dbg(board->gpib_dev, "cb7210: status 0x%x, mode 0x%x\n", hs_status, priv->hs_mode_bits); + + clear_bits = 0; + + if (hs_status & HS_HALF_FULL) { + if (priv->hs_mode_bits & HS_TX_ENABLE) + priv->out_fifo_half_empty = 1; + else if (priv->hs_mode_bits & HS_RX_ENABLE) + priv->in_fifo_half_full = 1; + clear_bits |= HS_CLR_HF_INT; + } + + if (hs_status & HS_SRQ_INT) { + set_bit(SRQI_NUM, &board->status); + clear_bits |= HS_CLR_SRQ_INT; + } + + if ((hs_status & HS_EOI_INT)) { + clear_bits |= HS_CLR_EOI_EMPTY_INT; + set_bit(RECEIVED_END_BN, &nec_priv->state); + if ((nec_priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE) + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + } + + if ((priv->hs_mode_bits & HS_TX_ENABLE) && + (hs_status & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY)) == 0) + clear_bits |= HS_CLR_EOI_EMPTY_INT; + + if (clear_bits) { + cb7210_write_byte(priv, priv->hs_mode_bits | clear_bits, HS_MODE); + cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE); + wake_up_interruptible(&board->wait); + } + + return IRQ_HANDLED; +} + +irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board) +{ + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = cb7210_internal_interrupt(board); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +irqreturn_t cb7210_interrupt(int irq, void *arg) +{ + return cb7210_internal_interrupt(arg); +} + +static int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void cb_pci_detach(gpib_board_t *board); +static void cb_isa_detach(gpib_board_t *board); + +// wrappers for interface functions +int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); +} + +int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +int cb7210_take_control(gpib_board_t *board, int synchronous) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +int cb7210_go_to_standby(gpib_board_t *board) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +void cb7210_request_system_control(gpib_board_t *board, int request_control) +{ + struct cb7210_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + if (request_control) + priv->hs_mode_bits |= HS_SYS_CONTROL; + else + priv->hs_mode_bits &= ~HS_SYS_CONTROL; + + cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE); + nec7210_request_system_control(board, nec_priv, request_control); +} + +void cb7210_interface_clear(gpib_board_t *board, int assert) +{ + struct cb7210_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +void cb7210_remote_enable(gpib_board_t *board, int enable) +{ + struct cb7210_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +void cb7210_disable_eos(gpib_board_t *board) +{ + struct cb7210_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); +} + +int cb7210_primary_address(gpib_board_t *board, unsigned int address) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +int cb7210_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_parallel_poll(board, &priv->nec7210_priv, result); +} + +void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration) +{ + struct cb7210_priv *priv = board->private_data; + + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); +} + +void cb7210_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct cb7210_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct cb7210_priv *priv = board->private_data; + + nec7210_serial_poll_response(board, &priv->nec7210_priv, status); +} + +uint8_t cb7210_serial_poll_status(gpib_board_t *board) +{ + struct cb7210_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +void cb7210_return_to_local(gpib_board_t *board) +{ + struct cb7210_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + write_byte(nec_priv, AUX_RTL2, AUXMR); + udelay(1); + write_byte(nec_priv, AUX_RTL, AUXMR); +} + +gpib_interface_t cb_pci_unaccel_interface = { +name: "cbi_pci_unaccel", +attach : cb_pci_attach, +detach : cb_pci_detach, +read : cb7210_read, +write : cb7210_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_pci_accel_interface = { +name: "cbi_pci_accel", +attach : cb_pci_attach, +detach : cb_pci_detach, +read : cb7210_accel_read, +write : cb7210_accel_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_pci_interface = { +name: "cbi_pci", +attach : cb_pci_attach, +detach : cb_pci_detach, +read : cb7210_accel_read, +write : cb7210_accel_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_isa_unaccel_interface = { +name: "cbi_isa_unaccel", +attach : cb_isa_attach, +detach : cb_isa_detach, +read : cb7210_read, +write : cb7210_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_isa_interface = { +name: "cbi_isa", +attach : cb_isa_attach, +detach : cb_isa_detach, +read : cb7210_accel_read, +write : cb7210_accel_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_isa_accel_interface = { +name: "cbi_isa_accel", +attach : cb_isa_attach, +detach : cb_isa_detach, +read : cb7210_accel_read, +write : cb7210_accel_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +static int cb7210_allocate_private(gpib_board_t *board) +{ + struct cb7210_priv *priv; + + board->private_data = kmalloc(sizeof(struct cb7210_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + priv = board->private_data; + memset(priv, 0, sizeof(struct cb7210_priv)); + init_nec7210_private(&priv->nec7210_priv); + return 0; +} + +void cb7210_generic_detach(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +// generic part of attach functions shared by all cb7210 boards +int cb7210_generic_attach(gpib_board_t *board) +{ + struct cb7210_priv *cb_priv; + struct nec7210_priv *nec_priv; + + board->status = 0; + + if (cb7210_allocate_private(board)) + return -ENOMEM; + cb_priv = board->private_data; + nec_priv = &cb_priv->nec7210_priv; + nec_priv->read_byte = nec7210_locking_ioport_read_byte; + nec_priv->write_byte = nec7210_locking_ioport_write_byte; + nec_priv->offset = cb7210_reg_offset; + nec_priv->type = CB7210; + return 0; +} + +int cb7210_init(struct cb7210_priv *cb_priv, gpib_board_t *board) +{ + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + + cb7210_write_byte(cb_priv, HS_RESET7210, HS_INT_LEVEL); + cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL); + + nec7210_board_reset(nec_priv, board); + cb7210_write_byte(cb_priv, HS_TX_ENABLE | HS_RX_ENABLE | HS_CLR_SRQ_INT | + HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE); + + cb_priv->hs_mode_bits = HS_HF_INT_EN; + cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); + + write_byte(nec_priv, AUX_LO_SPEED, AUXMR); + /* set clock register for maximum (20 MHz) driving frequency + * ICR should be set to clock in megahertz (1-15) and to zero + * for clocks faster than 15 MHz (max 20MHz) + */ + write_byte(nec_priv, ICR | 0, AUXMR); + + if (cb_priv->pci_chip == PCI_CHIP_QUANCOM) { + /* change interrupt polarity */ + nec_priv->auxb_bits |= HR_INV; + write_byte(nec_priv, nec_priv->auxb_bits, AUXMR); + } + nec7210_board_online(nec_priv, board); + + /* poll so we can detect assertion of ATN */ + if (gpib_request_pseudo_irq(board, cb_pci_interrupt)) { + pr_err("pc2_gpib: failed to allocate pseudo_irq\n"); + return -1; + } + return 0; +} + +int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct cb7210_priv *cb_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + int bits; + int retval; + + retval = cb7210_generic_attach(board); + if (retval) + return retval; + + cb_priv = board->private_data; + nec_priv = &cb_priv->nec7210_priv; + + cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS, + PCI_DEVICE_ID_CBOARDS_PCI_GPIB, NULL); + if (cb_priv->pci_device) + cb_priv->pci_chip = PCI_CHIP_AMCC_S5933; + if (!cb_priv->pci_device) { + cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS, + PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, NULL); + if (cb_priv->pci_device) + cb_priv->pci_chip = PCI_CHIP_AMCC_S5933; + } + if (!cb_priv->pci_device) { + cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_QUANCOM, + PCI_DEVICE_ID_QUANCOM_GPIB, NULL); + if (cb_priv->pci_device) { + cb_priv->pci_chip = PCI_CHIP_QUANCOM; + nec_priv->offset = 4; + } + } + if (!cb_priv->pci_device) { + pr_warn("cb7210: no supported boards found.\n"); + return -1; + } + + if (pci_enable_device(cb_priv->pci_device)) { + pr_err("cb7210: error enabling pci device\n"); + return -1; + } + + if (pci_request_regions(cb_priv->pci_device, "cb7210")) + return -1; + switch (cb_priv->pci_chip) { + case PCI_CHIP_AMCC_S5933: + cb_priv->amcc_iobase = pci_resource_start(cb_priv->pci_device, 0); + nec_priv->iobase = (void *)(pci_resource_start(cb_priv->pci_device, 1)); + cb_priv->fifo_iobase = pci_resource_start(cb_priv->pci_device, 2); + break; + case PCI_CHIP_QUANCOM: + nec_priv->iobase = (void *)(pci_resource_start(cb_priv->pci_device, 0)); + cb_priv->fifo_iobase = (unsigned long)nec_priv->iobase; + break; + default: + pr_err("cb7210: bug! unhandled pci_chip=%i\n", cb_priv->pci_chip); + return -EIO; + } + isr_flags |= IRQF_SHARED; + if (request_irq(cb_priv->pci_device->irq, cb_pci_interrupt, isr_flags, "cb7210", board)) { + pr_err("cb7210: can't request IRQ %d\n", cb_priv->pci_device->irq); + return -1; + } + cb_priv->irq = cb_priv->pci_device->irq; + + switch (cb_priv->pci_chip) { + case PCI_CHIP_AMCC_S5933: + // make sure mailbox flags are clear + inl(cb_priv->amcc_iobase + INCOMING_MAILBOX_REG(3)); + // enable interrupts on amccs5933 chip + bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) | INBOX_SELECT_BITS(3) | + INBOX_INTR_CS_BIT; + outl(bits, cb_priv->amcc_iobase + INTCSR_REG); + break; + default: + break; + } + return cb7210_init(cb_priv, board); +} + +void cb_pci_detach(gpib_board_t *board) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (cb_priv) { + gpib_free_pseudo_irq(board); + nec_priv = &cb_priv->nec7210_priv; + if (cb_priv->irq) { + // disable amcc interrupts + outl(0, cb_priv->amcc_iobase + INTCSR_REG); + free_irq(cb_priv->irq, board); + } + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + pci_release_regions(cb_priv->pci_device); + } + if (cb_priv->pci_device) + pci_dev_put(cb_priv->pci_device); + } + cb7210_generic_detach(board); +} + +int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + int isr_flags = 0; + struct cb7210_priv *cb_priv; + struct nec7210_priv *nec_priv; + unsigned int bits; + int retval; + + retval = cb7210_generic_attach(board); + if (retval) + return retval; + cb_priv = board->private_data; + nec_priv = &cb_priv->nec7210_priv; + if (request_region((unsigned long)config->ibbase, cb7210_iosize, "cb7210") == 0) { + pr_err("gpib: ioports starting at 0x%p are already in use\n", config->ibbase); + return -EIO; + } + nec_priv->iobase = config->ibbase; + cb_priv->fifo_iobase = nec7210_iobase(cb_priv); + + bits = irq_bits(config->ibirq); + if (bits == 0) + pr_err("board incapable of using irq %i, try 2-5, 7, 10, or 11\n", config->ibirq); + + // install interrupt handler + if (request_irq(config->ibirq, cb7210_interrupt, isr_flags, "cb7210", board)) { + pr_err("gpib: can't request IRQ %d\n", config->ibirq); + return -EBUSY; + } + cb_priv->irq = config->ibirq; + + return cb7210_init(cb_priv, board); +} + +void cb_isa_detach(gpib_board_t *board) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (cb_priv) { + gpib_free_pseudo_irq(board); + nec_priv = &cb_priv->nec7210_priv; + if (cb_priv->irq) + free_irq(cb_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + release_region(nec7210_iobase(cb_priv), cb7210_iosize); + } + } + cb7210_generic_detach(board); +} + +static int cb7210_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return 0; +} + +static const struct pci_device_id cb7210_pci_table[] = { + {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_PCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + {PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, cb7210_pci_table); + +static struct pci_driver cb7210_pci_driver = { + .name = "cb7210", + .id_table = cb7210_pci_table, + .probe = &cb7210_pci_probe +}; + +/*************************************************************************** + * Support for computer boards pcmcia-gpib card + * + * Based on gpib PCMCIA client driver written by Claus Schroeter + * (clausi@chemie.fu-berlin.de), which was adapted from the + * pcmcia skeleton example (presumably David Hinds) + ***************************************************************************/ + +#ifdef GPIB_PCMCIA + +#include <linux/kernel.h> +#include <linux/ptrace.h> +#include <linux/timer.h> +#include <linux/io.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> + +/* + * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + * you do not define PCMCIA_DEBUG at all, all the debug code will be + * left out. If you compile with PCMCIA_DEBUG=0, the debug code will + * be present but disabled -- but it can then be enabled for specific + * modules at load time with a 'pc_debug=#' option to insmod. + */ + +#define PCMCIA_DEBUG 1 + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args); } while (0) +#else +#define DEBUG(args...) +#endif + +/* + * The event() function is this driver's Card Services event handler. + * It will be called by Card Services when an appropriate card status + * event is received. The config() and release() entry points are + * used to configure or release a socket, in response to card insertion + * and ejection events. They are invoked from the gpib event + * handler. + */ + +static int cb_gpib_config(struct pcmcia_device *link); +static void cb_gpib_release(struct pcmcia_device *link); +static int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); +static void cb_pcmcia_detach(gpib_board_t *board); + +/* + * A linked list of "instances" of the gpib device. Each actual + * PCMCIA card corresponds to one device instance, and is described + * by one dev_link_t structure (defined in ds.h). + * + * You may not want to use a linked list for this -- for example, the + * memory card driver uses an array of dev_link_t pointers, where minor + * device numbers are used to derive the corresponding array index. + */ + +static struct pcmcia_device *curr_dev; + +/* + * A dev_link_t structure has fields for most things that are needed + * to keep track of a socket, but there will usually be some device + * specific information that also needs to be kept track of. The + * 'priv' pointer in a dev_link_t structure can be used to point to + * a device-specific private data structure, like this. + * + * A driver needs to provide a dev_node_t structure for each device + * on a card. In some cases, there is only one device per card (for + * example, ethernet cards, modems). In other cases, there may be + * many actual or logical devices (SCSI adapters, memory cards with + * multiple partitions). The dev_node_t structures need to be kept + * in a linked list starting at the 'dev' field of a dev_link_t + * structure. We allocate them in the card's private data structure, + * because they generally can't be allocated dynamically. + */ + +struct local_info { + struct pcmcia_device *p_dev; + gpib_board_t *dev; +}; + +/* + * gpib_attach() creates an "instance" of the driver, allocating + * local data structures for one device. The device is registered + * with Card Services. + * + * The dev_link structure is initialized, but we don't actually + * configure the card at this point -- we wait until we receive a + * card insertion event. + */ + +static int cb_gpib_probe(struct pcmcia_device *link) +{ + struct local_info *info; + +// int ret, i; + + DEBUG(0, "%s(0x%p)\n", __func__, link); + + /* Allocate space for private device-specific data */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->p_dev = link; + link->priv = info; + + /* The io structure describes IO port mapping */ + link->resource[0]->end = 16; + link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + link->resource[1]->end = 16; + link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; + link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; + link->io_lines = 10; + + /* General socket configuration */ + link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + link->config_index = 1; + link->config_regs = PRESENT_OPTION; + + /* Register with Card Services */ + curr_dev = link; + return cb_gpib_config(link); +} /* gpib_attach */ + +/* + * This deletes a driver "instance". The device is de-registered + * with Card Services. If it has been released, all local data + * structures are freed. Otherwise, the structures will be freed + * when the device is released. + */ + +static void cb_gpib_remove(struct pcmcia_device *link) +{ + struct local_info *info = link->priv; + //struct gpib_board_t *dev = info->dev; + + DEBUG(0, "%s(0x%p)\n", __func__, link); + + if (info->dev) + cb_pcmcia_detach(info->dev); + cb_gpib_release(link); + + //free_netdev(dev); + kfree(info); +} + +static int cb_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) +{ + return pcmcia_request_io(link); +} + +/* + * gpib_config() is scheduled to run after a CARD_INSERTION event + * is received, to configure the PCMCIA socket, and to make the + * ethernet device available to the system. + */ + +static int cb_gpib_config(struct pcmcia_device *link) +{ + struct pcmcia_device *handle; + struct local_info *dev; + int retval; + + handle = link; + dev = link->priv; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + retval = pcmcia_loop_config(link, &cb_gpib_config_iteration, NULL); + if (retval) { + dev_warn(&link->dev, "no configuration found\n"); + cb_gpib_release(link); + return -ENODEV; + } + + DEBUG(0, "gpib_cs: manufacturer: 0x%x card: 0x%x\n", link->manf_id, link->card_id); + + /* + * This actually configures the PCMCIA socket -- setting up + * the I/O windows and the interrupt mapping. + */ + retval = pcmcia_enable_device(link); + if (retval) { + dev_warn(&link->dev, "pcmcia_enable_device failed\n"); + cb_gpib_release(link); + return -ENODEV; + } + + pr_info("gpib device loaded\n"); + return 0; +} /* gpib_config */ + +/* + * After a card is removed, gpib_release() will unregister the net + * device, and release the PCMCIA configuration. If the device is + * still open, this will be postponed until it is closed. + */ + +static void cb_gpib_release(struct pcmcia_device *link) +{ + DEBUG(0, "%s(0x%p)\n", __func__, link); + pcmcia_disable_device(link); +} + +static int cb_gpib_suspend(struct pcmcia_device *link) +{ + //struct local_info *info = link->priv; + //struct gpib_board_t *dev = info->dev; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + if (link->open) + pr_warn("Device still open ???\n"); + //netif_device_detach(dev); + + return 0; +} + +static int cb_gpib_resume(struct pcmcia_device *link) +{ + //struct local_info *info = link->priv; + //struct gpib_board_t *dev = info->dev; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + /*if (link->open) { + * ni_gpib_probe(dev); / really? + * printk("Gpib resumed ???\n"); + * //netif_device_attach(dev); + * + */ + return cb_gpib_config(link); +} + +/*====================================================================*/ + +static struct pcmcia_device_id cb_pcmcia_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0005), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, cb_pcmcia_ids); + +static struct pcmcia_driver cb_gpib_cs_driver = { + .owner = THIS_MODULE, + .drv = { .name = "cb_gpib_cs", }, + .id_table = cb_pcmcia_ids, + .probe = cb_gpib_probe, + .remove = cb_gpib_remove, + .suspend = cb_gpib_suspend, + .resume = cb_gpib_resume, +}; + +int cb_pcmcia_init_module(void) +{ + pcmcia_register_driver(&cb_gpib_cs_driver); + return 0; +} + +void cb_pcmcia_cleanup_module(void) +{ + DEBUG(0, "cb_gpib_cs: unloading\n"); + pcmcia_unregister_driver(&cb_gpib_cs_driver); +} + +gpib_interface_t cb_pcmcia_unaccel_interface = { +name: "cbi_pcmcia_unaccel", +attach : cb_pcmcia_attach, +detach : cb_pcmcia_detach, +read : cb7210_read, +write : cb7210_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_pcmcia_interface = { +name: "cbi_pcmcia", +attach : cb_pcmcia_attach, +detach : cb_pcmcia_detach, +read : cb7210_accel_read, +write : cb7210_accel_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +gpib_interface_t cb_pcmcia_accel_interface = { +name: "cbi_pcmcia_accel", +attach : cb_pcmcia_attach, +detach : cb_pcmcia_detach, +read : cb7210_accel_read, +write : cb7210_accel_write, +command : cb7210_command, +take_control : cb7210_take_control, +go_to_standby : cb7210_go_to_standby, +request_system_control : cb7210_request_system_control, +interface_clear : cb7210_interface_clear, +remote_enable : cb7210_remote_enable, +enable_eos : cb7210_enable_eos, +disable_eos : cb7210_disable_eos, +parallel_poll : cb7210_parallel_poll, +parallel_poll_configure : cb7210_parallel_poll_configure, +parallel_poll_response : cb7210_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : cb7210_line_status, +update_status : cb7210_update_status, +primary_address : cb7210_primary_address, +secondary_address : cb7210_secondary_address, +serial_poll_response : cb7210_serial_poll_response, +serial_poll_status : cb7210_serial_poll_status, +t1_delay : cb7210_t1_delay, +return_to_local : cb7210_return_to_local, +}; + +int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct cb7210_priv *cb_priv; + struct nec7210_priv *nec_priv; + int retval; + + if (!curr_dev) { + pr_err("no cb pcmcia cards found\n"); + return -1; + } + + retval = cb7210_generic_attach(board); + if (retval) + return retval; + + cb_priv = board->private_data; + nec_priv = &cb_priv->nec7210_priv; + + if (request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), + "cb7210") == 0) { + pr_err("gpib: ioports starting at 0x%lx are already in use\n", + (unsigned long)curr_dev->resource[0]->start); + return -EIO; + } + nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start; + cb_priv->fifo_iobase = curr_dev->resource[0]->start; + + if (request_irq(curr_dev->irq, cb7210_interrupt, IRQF_SHARED, + "cb7210", board)) { + pr_err("cb7210: failed to request IRQ %d\n", curr_dev->irq); + return -1; + } + cb_priv->irq = curr_dev->irq; + + return cb7210_init(cb_priv, board); +} + +void cb_pcmcia_detach(gpib_board_t *board) +{ + struct cb7210_priv *cb_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (cb_priv) { + nec_priv = &cb_priv->nec7210_priv; + gpib_free_pseudo_irq(board); + if (cb_priv->irq) + free_irq(cb_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + release_region(nec7210_iobase(cb_priv), cb7210_iosize); + } + } + cb7210_generic_detach(board); +} + +#endif /* GPIB_PCMCIA */ + +static int __init cb7210_init_module(void) +{ + int err = 0; + int result; + + result = pci_register_driver(&cb7210_pci_driver); + if (result) { + pr_err("cb7210: pci_driver_register failed!\n"); + return result; + } + + gpib_register_driver(&cb_pci_interface, THIS_MODULE); + gpib_register_driver(&cb_isa_interface, THIS_MODULE); + gpib_register_driver(&cb_pci_accel_interface, THIS_MODULE); + gpib_register_driver(&cb_pci_unaccel_interface, THIS_MODULE); + gpib_register_driver(&cb_isa_accel_interface, THIS_MODULE); + gpib_register_driver(&cb_isa_unaccel_interface, THIS_MODULE); + +#ifdef GPIB__PCMCIA + gpib_register_driver(&cb_pcmcia_interface, THIS_MODULE); + gpib_register_driver(&cb_pcmcia_accel_interface, THIS_MODULE); + gpib_register_driver(&cb_pcmcia_unaccel_interface, THIS_MODULE); + err += cb_pcmcia_init_module(); +#endif + if (err) + return -1; + + return 0; +} + +static void __exit cb7210_exit_module(void) +{ + gpib_unregister_driver(&cb_pci_interface); + gpib_unregister_driver(&cb_isa_interface); + gpib_unregister_driver(&cb_pci_accel_interface); + gpib_unregister_driver(&cb_pci_unaccel_interface); + gpib_unregister_driver(&cb_isa_accel_interface); + gpib_unregister_driver(&cb_isa_unaccel_interface); +#ifdef GPIB_PCMCIA + gpib_unregister_driver(&cb_pcmcia_interface); + gpib_unregister_driver(&cb_pcmcia_accel_interface); + gpib_unregister_driver(&cb_pcmcia_unaccel_interface); + cb_pcmcia_cleanup_module(); +#endif + + pci_unregister_driver(&cb7210_pci_driver); +} + +module_init(cb7210_init_module); +module_exit(cb7210_exit_module); diff --git a/drivers/staging/gpib/cb7210/cb7210.h b/drivers/staging/gpib/cb7210/cb7210.h new file mode 100644 index 0000000000000000000000000000000000000000..4ad976de2b68400a37408e289b51ee2c76d05a80 --- /dev/null +++ b/drivers/staging/gpib/cb7210/cb7210.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "nec7210.h" +#include "gpibP.h" +#include "amccs5933.h" + +#include <linux/delay.h> +#include <linux/interrupt.h> + +enum { + PCI_DEVICE_ID_CBOARDS_PCI_GPIB = 0x6, + PCI_DEVICE_ID_CBOARDS_CPCI_GPIB = 0xe, +}; + +enum pci_chip { + PCI_CHIP_NONE = 0, + PCI_CHIP_AMCC_S5933, + PCI_CHIP_QUANCOM +}; + +// struct which defines private_data for cb7210 boards +struct cb7210_priv { + struct nec7210_priv nec7210_priv; + struct pci_dev *pci_device; + // base address of amccs5933 pci chip + unsigned long amcc_iobase; + unsigned long fifo_iobase; + unsigned int irq; + enum pci_chip pci_chip; + u8 hs_mode_bits; + unsigned out_fifo_half_empty : 1; + unsigned in_fifo_half_full : 1; +}; + +// interfaces +extern gpib_interface_t cb_pcmcia_interface; +extern gpib_interface_t cb_pcmcia_accel_interface; +extern gpib_interface_t cb_pcmcia_unaccel_interface; + +// interrupt service routines +irqreturn_t cb_pci_interrupt(int irq, void *arg); +irqreturn_t cb7210_interrupt(int irq, void *arg); +irqreturn_t cb7210_internal_interrupt(gpib_board_t *board); + +// interface functions +int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read); +int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read); +int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); +int cb7210_take_control(gpib_board_t *board, int synchronous); +int cb7210_go_to_standby(gpib_board_t *board); +void cb7210_request_system_control(gpib_board_t *board, int request_control); +void cb7210_interface_clear(gpib_board_t *board, int assert); +void cb7210_remote_enable(gpib_board_t *board, int enable); +int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte, + int compare_8_bits); +void cb7210_disable_eos(gpib_board_t *board); +unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask); +int cb7210_primary_address(gpib_board_t *board, unsigned int address); +int cb7210_secondary_address(gpib_board_t *board, unsigned int address, + int enable); +int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result); +void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status); +uint8_t cb7210_serial_poll_status(gpib_board_t *board); +void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration); +void cb7210_parallel_poll_response(gpib_board_t *board, int ist); +int cb7210_line_status(const gpib_board_t *board); +unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec); +void cb7210_return_to_local(gpib_board_t *board); + +// utility functions +void cb7210_generic_detach(gpib_board_t *board); +int cb7210_generic_attach(gpib_board_t *board); +int cb7210_init(struct cb7210_priv *priv, gpib_board_t *board); + +// pcmcia init/cleanup +int cb_pcmcia_init_module(void); +void cb_pcmcia_cleanup_module(void); + +// pci-gpib register offset +static const int cb7210_reg_offset = 1; + +// uses 10 ioports +static const int cb7210_iosize = 10; + +// fifo size in bytes +static const int cb7210_fifo_size = 2048; +static const int cb7210_fifo_width = 2; + +// cb7210 specific registers and bits +enum cb7210_regs { + BUS_STATUS = 0x7, +}; + +enum cb7210_page_in { + BUS_STATUS_PAGE = 1, +}; + +enum hs_regs { + //write registers + HS_MODE = 0x8, /* HS_MODE register */ + HS_INT_LEVEL = 0x9, /* HS_INT_LEVEL register */ + //read registers + HS_STATUS = 0x8, /* HS_STATUS register */ +}; + +static inline unsigned long nec7210_iobase(const struct cb7210_priv *cb_priv) +{ + return (unsigned long)(cb_priv->nec7210_priv.iobase); +} + +static inline int cb7210_page_in_bits(unsigned int page) +{ + return 0x50 | (page & 0xf); +} + +static inline uint8_t cb7210_paged_read_byte(struct cb7210_priv *cb_priv, + unsigned int register_num, unsigned int page) +{ + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + u8 retval; + unsigned long flags; + + spin_lock_irqsave(&nec_priv->register_page_lock, flags); + outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset); + udelay(1); + retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset); + spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); + return retval; +} + +// don't use for register_num < 8, since it doesn't lock +static inline uint8_t cb7210_read_byte(const struct cb7210_priv *cb_priv, + enum hs_regs register_num) +{ + const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + u8 retval; + + retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset); + return retval; +} + +static inline void cb7210_paged_write_byte(struct cb7210_priv *cb_priv, uint8_t data, + unsigned int register_num, unsigned int page) +{ + struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + unsigned long flags; + + spin_lock_irqsave(&nec_priv->register_page_lock, flags); + outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset); + udelay(1); + outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset); + spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); +} + +// don't use for register_num < 8, since it doesn't lock +static inline void cb7210_write_byte(const struct cb7210_priv *cb_priv, uint8_t data, + enum hs_regs register_num) +{ + const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; + + outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset); +} + +enum bus_status_bits { + BSR_ATN_BIT = 0x1, + BSR_EOI_BIT = 0x2, + BSR_SRQ_BIT = 0x4, + BSR_IFC_BIT = 0x8, + BSR_REN_BIT = 0x10, + BSR_DAV_BIT = 0x20, + BSR_NRFD_BIT = 0x40, + BSR_NDAC_BIT = 0x80, +}; + +/* CBI 488.2 HS control */ + +/* when both bit 0 and 1 are set, it + * 1 clears the transmit state machine to an initial condition + * 2 clears any residual interrupts left latched on cbi488.2 + * 3 resets all control bits in HS_MODE to zero + * 4 enables TX empty interrupts + * when both bit 0 and 1 are zero, then the high speed mode is disabled + */ +enum hs_mode_bits { + HS_ENABLE_MASK = 0x3, + HS_TX_ENABLE = (1 << 0), + HS_RX_ENABLE = (1 << 1), + HS_HF_INT_EN = (1 << 3), + HS_CLR_SRQ_INT = (1 << 4), + HS_CLR_EOI_EMPTY_INT = (1 << 5), + HS_CLR_HF_INT = (1 << 6), + HS_SYS_CONTROL = (1 << 7), +}; + +/* CBI 488.2 status */ +enum hs_status_bits { + HS_FIFO_FULL = (1 << 0), + HS_HALF_FULL = (1 << 1), + HS_SRQ_INT = (1 << 2), + HS_EOI_INT = (1 << 3), + HS_TX_MSB_NOT_EMPTY = (1 << 4), + HS_RX_MSB_NOT_EMPTY = (1 << 5), + HS_TX_LSB_NOT_EMPTY = (1 << 6), + HS_RX_LSB_NOT_EMPTY = (1 << 7), +}; + +/* CBI488.2 hs_int_level register */ +enum hs_int_level_bits { + HS_RESET7210 = (1 << 7), +}; + +static inline unsigned int irq_bits(unsigned int irq) +{ + switch (irq) { + case 2: + case 3: + case 4: + case 5: + return irq - 1; + case 7: + return 0x5; + case 10: + return 0x6; + case 11: + return 0x7; + default: + return 0; + } +} + +enum cb7210_aux_cmds { +/* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert + * (and keep asserted) local rtl message. This is used in conjunction + * with the (stupid) cb7210 implementation + * of the normal nec7210 AUX_RTL aux command, which + * causes the rtl message to toggle between on and off. + */ + AUX_RTL2 = 0xd, + AUX_LO_SPEED = 0x40, + AUX_HI_SPEED = 0x41, +}; diff --git a/drivers/staging/gpib/cec/Makefile b/drivers/staging/gpib/cec/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f4638628ff294599e223f2531943dadad0d6ee55 --- /dev/null +++ b/drivers/staging/gpib/cec/Makefile @@ -0,0 +1,3 @@ + +obj-m += cec_gpib.o + diff --git a/drivers/staging/gpib/cec/cec.h b/drivers/staging/gpib/cec/cec.h new file mode 100644 index 0000000000000000000000000000000000000000..352cf83d8328f77ca079f4bb8842f01220b83efc --- /dev/null +++ b/drivers/staging/gpib/cec/cec.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "nec7210.h" +#include "gpibP.h" +#include "plx9050.h" + +struct cec_priv { + struct nec7210_priv nec7210_priv; + struct pci_dev *pci_device; + // base address for plx9052 pci chip + unsigned long plx_iobase; + unsigned int irq; +}; + +// interfaces +extern gpib_interface_t cec_pci_interface; +extern gpib_interface_t cec_pcmcia_interface; + +// interface functions +int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); +int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); +int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); +int cec_take_control(gpib_board_t *board, int synchronous); +int cec_go_to_standby(gpib_board_t *board); +void cec_request_system_control(gpib_board_t *board, int request_control); +void cec_interface_clear(gpib_board_t *board, int assert); +void cec_remote_enable(gpib_board_t *board, int enable); +int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits); +void cec_disable_eos(gpib_board_t *board); +unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask); +int cec_primary_address(gpib_board_t *board, unsigned int address); +int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable); +int cec_parallel_poll(gpib_board_t *board, uint8_t *result); +void cec_parallel_poll_configure(gpib_board_t *board, uint8_t configuration); +void cec_parallel_poll_response(gpib_board_t *board, int ist); +void cec_serial_poll_response(gpib_board_t *board, uint8_t status); +void cec_return_to_local(gpib_board_t *board); + +// interrupt service routines +irqreturn_t cec_interrupt(int irq, void *arg); + +// utility functions +void cec_free_private(gpib_board_t *board); +int cec_generic_attach(gpib_board_t *board); +void cec_init(struct cec_priv *priv, const gpib_board_t *board); + +// offset between consecutive nec7210 registers +static const int cec_reg_offset = 1; diff --git a/drivers/staging/gpib/cec/cec_gpib.c b/drivers/staging/gpib/cec/cec_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..3dc933deb40180bcf4c5b19e021e016283692d5a --- /dev/null +++ b/drivers/staging/gpib/cec/cec_gpib.c @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "cec.h" +#include <linux/pci.h> +#include <linux/io.h> +#include <linux/bitops.h> +#include <asm/dma.h> +#include <linux/module.h> +#include <linux/slab.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for CEC PCI and PCMCIA boards"); + +/* + * GPIB interrupt service routines + */ + +irqreturn_t cec_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct cec_priv *priv = board->private_data; + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = nec7210_interrupt(board, &priv->nec7210_priv); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +#define CEC_VENDOR_ID 0x12fc +#define CEC_DEV_ID 0x5cec +#define CEC_SUBID 0x9050 + +static int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void cec_pci_detach(gpib_board_t *board); + +// wrappers for interface functions +int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); +} + +int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +int cec_take_control(gpib_board_t *board, int synchronous) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +int cec_go_to_standby(gpib_board_t *board) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +void cec_request_system_control(gpib_board_t *board, int request_control) +{ + struct cec_priv *priv = board->private_data; + + nec7210_request_system_control(board, &priv->nec7210_priv, request_control); +} + +void cec_interface_clear(gpib_board_t *board, int assert) +{ + struct cec_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +void cec_remote_enable(gpib_board_t *board, int enable) +{ + struct cec_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +void cec_disable_eos(gpib_board_t *board) +{ + struct cec_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); +} + +int cec_primary_address(gpib_board_t *board, unsigned int address) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +int cec_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_parallel_poll(board, &priv->nec7210_priv, result); +} + +void cec_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + struct cec_priv *priv = board->private_data; + + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); +} + +void cec_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct cec_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +void cec_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct cec_priv *priv = board->private_data; + + nec7210_serial_poll_response(board, &priv->nec7210_priv, status); +} + +static uint8_t cec_serial_poll_status(gpib_board_t *board) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +static unsigned int cec_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct cec_priv *priv = board->private_data; + + return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec); +} + +void cec_return_to_local(gpib_board_t *board) +{ + struct cec_priv *priv = board->private_data; + + nec7210_return_to_local(board, &priv->nec7210_priv); +} + +gpib_interface_t cec_pci_interface = { +name: "cec_pci", +attach : cec_pci_attach, +detach : cec_pci_detach, +read : cec_read, +write : cec_write, +command : cec_command, +take_control : cec_take_control, +go_to_standby : cec_go_to_standby, +request_system_control : cec_request_system_control, +interface_clear : cec_interface_clear, +remote_enable : cec_remote_enable, +enable_eos : cec_enable_eos, +disable_eos : cec_disable_eos, +parallel_poll : cec_parallel_poll, +parallel_poll_configure : cec_parallel_poll_configure, +parallel_poll_response : cec_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, //XXX +update_status : cec_update_status, +primary_address : cec_primary_address, +secondary_address : cec_secondary_address, +serial_poll_response : cec_serial_poll_response, +serial_poll_status : cec_serial_poll_status, +t1_delay : cec_t1_delay, +return_to_local : cec_return_to_local, +}; + +static int cec_allocate_private(gpib_board_t *board) +{ + struct cec_priv *priv; + + board->private_data = kmalloc(sizeof(struct cec_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + priv = board->private_data; + memset(priv, 0, sizeof(struct cec_priv)); + init_nec7210_private(&priv->nec7210_priv); + return 0; +} + +void cec_free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +int cec_generic_attach(gpib_board_t *board) +{ + struct cec_priv *cec_priv; + struct nec7210_priv *nec_priv; + + board->status = 0; + + if (cec_allocate_private(board)) + return -ENOMEM; + cec_priv = board->private_data; + nec_priv = &cec_priv->nec7210_priv; + nec_priv->read_byte = nec7210_ioport_read_byte; + nec_priv->write_byte = nec7210_ioport_write_byte; + nec_priv->offset = cec_reg_offset; + nec_priv->type = NEC7210; // guess + return 0; +} + +void cec_init(struct cec_priv *cec_priv, const gpib_board_t *board) +{ + struct nec7210_priv *nec_priv = &cec_priv->nec7210_priv; + + nec7210_board_reset(nec_priv, board); + + /* set internal counter register for 8 MHz input clock */ + write_byte(nec_priv, ICR | 8, AUXMR); + + nec7210_board_online(nec_priv, board); +} + +int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct cec_priv *cec_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + int retval; + + retval = cec_generic_attach(board); + if (retval) + return retval; + + cec_priv = board->private_data; + nec_priv = &cec_priv->nec7210_priv; + + // find board + cec_priv->pci_device = NULL; + while ((cec_priv->pci_device = + gpib_pci_get_device(config, CEC_VENDOR_ID, + CEC_DEV_ID, cec_priv->pci_device))) { + // check for board with plx9050 controller + if (cec_priv->pci_device->subsystem_device == CEC_SUBID) + break; + } + if (!cec_priv->pci_device) { + pr_err("gpib: no cec PCI board found\n"); + return -1; + } + + if (pci_enable_device(cec_priv->pci_device)) { + pr_err("error enabling pci device\n"); + return -1; + } + + if (pci_request_regions(cec_priv->pci_device, "cec-gpib")) + return -1; + + cec_priv->plx_iobase = pci_resource_start(cec_priv->pci_device, 1); + pr_info(" plx9050 base address 0x%lx\n", cec_priv->plx_iobase); + nec_priv->iobase = (void *)(pci_resource_start(cec_priv->pci_device, 3)); + pr_info(" nec7210 base address 0x%p\n", nec_priv->iobase); + + isr_flags |= IRQF_SHARED; + if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, "pci-gpib", board)) { + pr_err("gpib: can't request IRQ %d\n", cec_priv->pci_device->irq); + return -1; + } + cec_priv->irq = cec_priv->pci_device->irq; + if (gpib_request_pseudo_irq(board, cec_interrupt)) { + pr_err("cec: failed to allocate pseudo irq\n"); + return -1; + } + cec_init(cec_priv, board); + + // enable interrupts on plx chip + outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT, + cec_priv->plx_iobase + PLX9050_INTCSR_REG); + + return 0; +} + +void cec_pci_detach(gpib_board_t *board) +{ + struct cec_priv *cec_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (cec_priv) { + nec_priv = &cec_priv->nec7210_priv; + gpib_free_pseudo_irq(board); + if (cec_priv->irq) { + // disable plx9050 interrupts + outl(0, cec_priv->plx_iobase + PLX9050_INTCSR_REG); + free_irq(cec_priv->irq, board); + } + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + pci_release_regions(cec_priv->pci_device); + } + if (cec_priv->pci_device) + pci_dev_put(cec_priv->pci_device); + } + cec_free_private(board); +} + +static int cec_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return 0; +} + +static const struct pci_device_id cec_pci_table[] = { + {CEC_VENDOR_ID, CEC_DEV_ID, PCI_ANY_ID, CEC_SUBID, 0, 0, 0 }, + {0} +}; +MODULE_DEVICE_TABLE(pci, cec_pci_table); + +static struct pci_driver cec_pci_driver = { + .name = "cec_gpib", + .id_table = cec_pci_table, + .probe = &cec_pci_probe +}; + +static int __init cec_init_module(void) +{ + int result; + + result = pci_register_driver(&cec_pci_driver); + if (result) { + pr_err("cec_gpib: pci_driver_register failed!\n"); + return result; + } + + gpib_register_driver(&cec_pci_interface, THIS_MODULE); + + return 0; +} + +static void cec_exit_module(void) +{ + gpib_unregister_driver(&cec_pci_interface); + + pci_unregister_driver(&cec_pci_driver); +} + +module_init(cec_init_module); +module_exit(cec_exit_module); diff --git a/drivers/staging/gpib/common/Makefile b/drivers/staging/gpib/common/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0c4c77bea75b3e14c8c79f2210ac057f0dc93589 --- /dev/null +++ b/drivers/staging/gpib/common/Makefile @@ -0,0 +1,6 @@ + +obj-m += gpib_common.o + +gpib_common-objs := gpib_os.o iblib.o + + diff --git a/drivers/staging/gpib/common/gpib_os.c b/drivers/staging/gpib/common/gpib_os.c new file mode 100644 index 0000000000000000000000000000000000000000..405237d8cb479f25a01e6988f13ee47c8ffed822 --- /dev/null +++ b/drivers/staging/gpib/common/gpib_os.c @@ -0,0 +1,2328 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2001, 2004 by Frank Mori Hess + *************************************************************************** + */ + +#include "ibsys.h" +#include <linux/module.h> +#include <linux/wait.h> +#include <linux/list.h> +#include <linux/fs.h> +#include <linux/pci.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/vmalloc.h> +#include <linux/fcntl.h> +#include <linux/kmod.h> +#include <linux/uaccess.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB base support"); +MODULE_ALIAS_CHARDEV_MAJOR(GPIB_CODE); + +static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg); +static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, + unsigned long arg); +static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, + unsigned long arg); +static int command_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, + unsigned long arg); +static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg); +static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg); +static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg); +static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg); +static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg); +static int online_ioctl(gpib_board_t *board, unsigned long arg); +static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg); +static int take_control_ioctl(gpib_board_t *board, unsigned long arg); +static int line_status_ioctl(gpib_board_t *board, unsigned long arg); +static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg); +static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg); +static int eos_ioctl(gpib_board_t *board, unsigned long arg); +static int request_service_ioctl(gpib_board_t *board, unsigned long arg); +static int request_service2_ioctl(gpib_board_t *board, unsigned long arg); +static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg); +static int irq_ioctl(gpib_board_config_t *config, unsigned long arg); +static int dma_ioctl(gpib_board_config_t *config, unsigned long arg); +static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg); +static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg); +static int timeout_ioctl(gpib_board_t *board, unsigned long arg); +static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg); +static int board_info_ioctl(const gpib_board_t *board, unsigned long arg); +static int ppc_ioctl(gpib_board_t *board, unsigned long arg); +static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg); +static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg); +static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg); +static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg); +static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg); +static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg); +static int event_ioctl(gpib_board_t *board, unsigned long arg); +static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg); +static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg); + +static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board); + +static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type); + +/* + * Timer functions + */ + +/* Watchdog timeout routine */ + +static void watchdog_timeout(struct timer_list *t) +{ + gpib_board_t *board = from_timer(board, t, timer); + + set_bit(TIMO_NUM, &board->status); + wake_up_interruptible(&board->wait); +} + +/* install timer interrupt handler */ +void os_start_timer(gpib_board_t *board, unsigned int usec_timeout) +/* Starts the timeout task */ +{ + if (timer_pending(&board->timer)) { + pr_err("gpib: bug! timer already running?\n"); + return; + } + clear_bit(TIMO_NUM, &board->status); + + if (usec_timeout > 0) { + board->timer.function = watchdog_timeout; + /* set number of ticks */ + mod_timer(&board->timer, jiffies + usec_to_jiffies(usec_timeout)); + } +} + +void os_remove_timer(gpib_board_t *board) +/* Removes the timeout task */ +{ + if (timer_pending(&board->timer)) + del_timer_sync(&board->timer); +} + +int io_timed_out(gpib_board_t *board) +{ + if (test_bit(TIMO_NUM, &board->status)) + return 1; + return 0; +} + +void writeb_wrapper(unsigned int value, void *address) +{ + writeb(value, address); +}; +EXPORT_SYMBOL(writeb_wrapper); + +void writew_wrapper(unsigned int value, void *address) +{ + writew(value, address); +}; +EXPORT_SYMBOL(writew_wrapper); + +unsigned int readb_wrapper(void *address) +{ + return readb(address); +}; +EXPORT_SYMBOL(readb_wrapper); + +unsigned int readw_wrapper(void *address) +{ + return readw(address); +}; +EXPORT_SYMBOL(readw_wrapper); + +#ifdef CONFIG_HAS_IOPORT +void outb_wrapper(unsigned int value, void *address) +{ + outb(value, (unsigned long)(address)); +}; +EXPORT_SYMBOL(outb_wrapper); + +void outw_wrapper(unsigned int value, void *address) +{ + outw(value, (unsigned long)(address)); +}; +EXPORT_SYMBOL(outw_wrapper); + +unsigned int inb_wrapper(void *address) +{ + return inb((unsigned long)(address)); +}; +EXPORT_SYMBOL(inb_wrapper); + +unsigned int inw_wrapper(void *address) +{ + return inw((unsigned long)(address)); +}; +EXPORT_SYMBOL(inw_wrapper); +#endif + +/* this is a function instead of a constant because of Suse + * defining HZ to be a function call to get_hz() + */ +static inline int pseudo_irq_period(void) +{ + return (HZ + 99) / 100; +} + +static void pseudo_irq_handler(struct timer_list *t) +{ + struct gpib_pseudo_irq *pseudo_irq = from_timer(pseudo_irq, t, timer); + + if (pseudo_irq->handler) + pseudo_irq->handler(0, pseudo_irq->board); + else + pr_err("gpib: bug! pseudo_irq.handler is NULL\n"); + + if (atomic_read(&pseudo_irq->active)) + mod_timer(&pseudo_irq->timer, jiffies + pseudo_irq_period()); +} + +int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *)) +{ + if (timer_pending(&board->pseudo_irq.timer) || board->pseudo_irq.handler) { + pr_err("gpib: only one pseudo interrupt per board allowed\n"); + return -1; + } + + board->pseudo_irq.handler = handler; + board->pseudo_irq.timer.function = pseudo_irq_handler; + board->pseudo_irq.board = board; + + atomic_set(&board->pseudo_irq.active, 1); + + mod_timer(&board->pseudo_irq.timer, jiffies + pseudo_irq_period()); + + return 0; +} +EXPORT_SYMBOL(gpib_request_pseudo_irq); + +void gpib_free_pseudo_irq(gpib_board_t *board) +{ + atomic_set(&board->pseudo_irq.active, 0); + + del_timer_sync(&board->pseudo_irq.timer); + board->pseudo_irq.handler = NULL; +} +EXPORT_SYMBOL(gpib_free_pseudo_irq); + +static const unsigned int serial_timeout = 1000000; + +unsigned int num_status_bytes(const gpib_status_queue_t *dev) +{ + if (!dev) + return 0; + return dev->num_status_bytes; +} + +// push status byte onto back of status byte fifo +int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 poll_byte) +{ + struct list_head *head = &device->status_bytes; + status_byte_t *status; + static const unsigned int max_num_status_bytes = 1024; + int retval; + + if (num_status_bytes(device) >= max_num_status_bytes) { + u8 lost_byte; + + device->dropped_byte = 1; + retval = pop_status_byte(board, device, &lost_byte); + if (retval < 0) + return retval; + } + + status = kmalloc(sizeof(status_byte_t), GFP_KERNEL); + if (!status) + return -ENOMEM; + + INIT_LIST_HEAD(&status->list); + status->poll_byte = poll_byte; + + list_add_tail(&status->list, head); + + device->num_status_bytes++; + + dev_dbg(board->gpib_dev, "pushed status byte 0x%x, %i in queue\n", + (int)poll_byte, num_status_bytes(device)); + + return 0; +} + +// pop status byte from front of status byte fifo +int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 *poll_byte) +{ + struct list_head *head = &device->status_bytes; + struct list_head *front = head->next; + status_byte_t *status; + + if (num_status_bytes(device) == 0) + return -EIO; + + if (front == head) + return -EIO; + + if (device->dropped_byte) { + device->dropped_byte = 0; + return -EPIPE; + } + + status = list_entry(front, status_byte_t, list); + *poll_byte = status->poll_byte; + + list_del(front); + kfree(status); + + device->num_status_bytes--; + + dev_dbg(board->gpib_dev, "popped status byte 0x%x, %i in queue\n", + (int)*poll_byte, num_status_bytes(device)); + + return 0; +} + +gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad) +{ + gpib_status_queue_t *device; + struct list_head *list_ptr; + const struct list_head *head = &board->device_list; + + for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { + device = list_entry(list_ptr, gpib_status_queue_t, list); + if (gpib_address_equal(device->pad, device->sad, pad, sad)) + return device; + } + + return NULL; +} + +int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, unsigned int usec_timeout, + uint8_t *poll_byte) +{ + gpib_status_queue_t *device; + + dev_dbg(board->gpib_dev, "%s:()\n", __func__); + + device = get_gpib_status_queue(board, pad, sad); + if (num_status_bytes(device)) + return pop_status_byte(board, device, poll_byte); + else + return dvrsp(board, pad, sad, usec_timeout, poll_byte); +} + +int autopoll_all_devices(gpib_board_t *board) +{ + int retval; + + dev_dbg(board->gpib_dev, "entering %s()\n", __func__); + if (mutex_lock_interruptible(&board->user_mutex)) + return -ERESTARTSYS; + if (mutex_lock_interruptible(&board->big_gpib_mutex)) { + mutex_unlock(&board->user_mutex); + return -ERESTARTSYS; + } + + dev_dbg(board->gpib_dev, "autopoll has board lock\n"); + + retval = serial_poll_all(board, serial_timeout); + if (retval < 0) { + mutex_unlock(&board->big_gpib_mutex); + mutex_unlock(&board->user_mutex); + return retval; + } + + dev_dbg(board->gpib_dev, "%s complete\n", __func__); + /* need to wake wait queue in case someone is + * waiting on RQS + */ + wake_up_interruptible(&board->wait); + mutex_unlock(&board->big_gpib_mutex); + mutex_unlock(&board->user_mutex); + + return retval; +} + +static int setup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) +{ + u8 cmd_string[8]; + int i; + size_t bytes_written; + int ret; + + dev_dbg(board->gpib_dev, "entering %s()\n", __func__); + + os_start_timer(board, usec_timeout); + ret = ibcac(board, 1, 1); + if (ret < 0) { + os_remove_timer(board); + return ret; + } + + i = 0; + cmd_string[i++] = UNL; + cmd_string[i++] = MLA(board->pad); /* controller's listen address */ + if (board->sad >= 0) + cmd_string[i++] = MSA(board->sad); + cmd_string[i++] = SPE; //serial poll enable + + ret = board->interface->command(board, cmd_string, i, &bytes_written); + if (ret < 0 || bytes_written < i) { + pr_err("gpib: failed to setup serial poll\n"); + os_remove_timer(board); + return -EIO; + } + os_remove_timer(board); + + return 0; +} + +static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad, + int sad, unsigned int usec_timeout, uint8_t *result) +{ + u8 cmd_string[8]; + int end_flag; + int ret; + int i; + size_t nbytes; + + dev_dbg(board->gpib_dev, "entering %s(), pad=%i sad=%i\n", __func__, pad, sad); + + os_start_timer(board, usec_timeout); + ret = ibcac(board, 1, 1); + if (ret < 0) { + os_remove_timer(board); + return ret; + } + + i = 0; + // send talk address + cmd_string[i++] = MTA(pad); + if (sad >= 0) + cmd_string[i++] = MSA(sad); + + ret = board->interface->command(board, cmd_string, i, &nbytes); + if (ret < 0 || nbytes < i) { + pr_err("gpib: failed to setup serial poll\n"); + os_remove_timer(board); + return -EIO; + } + + ibgts(board); + + // read poll result + ret = board->interface->read(board, result, 1, &end_flag, &nbytes); + if (ret < 0 || nbytes < 1) { + pr_err("gpib: serial poll failed\n"); + os_remove_timer(board); + return -EIO; + } + os_remove_timer(board); + + return 0; +} + +static int cleanup_serial_poll(gpib_board_t *board, unsigned int usec_timeout) +{ + u8 cmd_string[8]; + int ret; + size_t bytes_written; + + dev_dbg(board->gpib_dev, "entering %s()\n", __func__); + + os_start_timer(board, usec_timeout); + ret = ibcac(board, 1, 1); + if (ret < 0) { + os_remove_timer(board); + return ret; + } + + cmd_string[0] = SPD; /* disable serial poll bytes */ + cmd_string[1] = UNT; + ret = board->interface->command(board, cmd_string, 2, &bytes_written); + if (ret < 0 || bytes_written < 2) { + pr_err("gpib: failed to disable serial poll\n"); + os_remove_timer(board); + return -EIO; + } + os_remove_timer(board); + + return 0; +} + +static int serial_poll_single(gpib_board_t *board, unsigned int pad, int sad, + unsigned int usec_timeout, uint8_t *result) +{ + int retval, cleanup_retval; + + retval = setup_serial_poll(board, usec_timeout); + if (retval < 0) + return retval; + retval = read_serial_poll_byte(board, pad, sad, usec_timeout, result); + cleanup_retval = cleanup_serial_poll(board, usec_timeout); + if (retval < 0) + return retval; + if (cleanup_retval < 0) + return retval; + + return 0; +} + +int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout) +{ + int retval = 0; + struct list_head *cur; + const struct list_head *head = NULL; + gpib_status_queue_t *device; + u8 result; + unsigned int num_bytes = 0; + + dev_dbg(board->gpib_dev, "entering %s()\n", __func__); + + head = &board->device_list; + if (head->next == head) + return 0; + + retval = setup_serial_poll(board, usec_timeout); + if (retval < 0) + return retval; + + for (cur = head->next; cur != head; cur = cur->next) { + device = list_entry(cur, gpib_status_queue_t, list); + retval = read_serial_poll_byte(board, + device->pad, device->sad, usec_timeout, &result); + if (retval < 0) + continue; + if (result & request_service_bit) { + retval = push_status_byte(board, device, result); + if (retval < 0) + continue; + num_bytes++; + } + } + + retval = cleanup_serial_poll(board, usec_timeout); + if (retval < 0) + return retval; + + return num_bytes; +} + +/* + * DVRSP + * This function performs a serial poll of the device with primary + * address pad and secondary address sad. If the device has no + * secondary address, pass a negative number in for this argument. At the + * end of a successful serial poll the response is returned in result. + * SPD and UNT are sent at the completion of the poll. + */ + +int dvrsp(gpib_board_t *board, unsigned int pad, int sad, + unsigned int usec_timeout, uint8_t *result) +{ + int status = ibstatus(board); + int retval; + + if ((status & CIC) == 0) { + pr_err("gpib: not CIC during serial poll\n"); + return -1; + } + + if (pad > MAX_GPIB_PRIMARY_ADDRESS || sad > MAX_GPIB_SECONDARY_ADDRESS) { + pr_err("gpib: bad address for serial poll"); + return -1; + } + + retval = serial_poll_single(board, pad, sad, usec_timeout, result); + if (io_timed_out(board)) + retval = -ETIMEDOUT; + + return retval; +} + +static gpib_descriptor_t *handle_to_descriptor(const gpib_file_private_t *file_priv, + int handle) +{ + if (handle < 0 || handle >= GPIB_MAX_NUM_DESCRIPTORS) { + pr_err("gpib: invalid handle %i\n", handle); + return NULL; + } + + return file_priv->descriptors[handle]; +} + +static int init_gpib_file_private(gpib_file_private_t *priv) +{ + memset(priv, 0, sizeof(*priv)); + atomic_set(&priv->holding_mutex, 0); + priv->descriptors[0] = kmalloc(sizeof(gpib_descriptor_t), GFP_KERNEL); + if (!priv->descriptors[0]) { + pr_err("gpib: failed to allocate default board descriptor\n"); + return -ENOMEM; + } + init_gpib_descriptor(priv->descriptors[0]); + priv->descriptors[0]->is_board = 1; + mutex_init(&priv->descriptors_mutex); + return 0; +} + +int ibopen(struct inode *inode, struct file *filep) +{ + unsigned int minor = iminor(inode); + gpib_board_t *board; + gpib_file_private_t *priv; + + if (minor >= GPIB_MAX_NUM_BOARDS) { + pr_err("gpib: invalid minor number of device file\n"); + return -ENXIO; + } + + board = &board_array[minor]; + + filep->private_data = kmalloc(sizeof(gpib_file_private_t), GFP_KERNEL); + if (!filep->private_data) + return -ENOMEM; + + priv = filep->private_data; + init_gpib_file_private((gpib_file_private_t *)filep->private_data); + + dev_dbg(board->gpib_dev, "pid %i, gpib: opening minor %d\n", current->pid, minor); + + if (board->use_count == 0) { + int retval; + + retval = request_module("gpib%i", minor); + if (retval) { + dev_dbg(board->gpib_dev, "pid %i, gpib: request module returned %i\n", + current->pid, retval); + } + } + if (board->interface) { + if (!try_module_get(board->provider_module)) { + pr_err("gpib: try_module_get() failed\n"); + return -EIO; + } + board->use_count++; + priv->got_module = 1; + } + return 0; +} + +int ibclose(struct inode *inode, struct file *filep) +{ + unsigned int minor = iminor(inode); + gpib_board_t *board; + gpib_file_private_t *priv = filep->private_data; + gpib_descriptor_t *desc; + + if (minor >= GPIB_MAX_NUM_BOARDS) { + pr_err("gpib: invalid minor number of device file\n"); + return -ENODEV; + } + + board = &board_array[minor]; + + dev_dbg(board->gpib_dev, "pid %i, closing minor %d\n", current->pid, minor); + + if (priv) { + desc = handle_to_descriptor(priv, 0); + if (desc) { + if (desc->autopoll_enabled) { + dev_dbg(board->gpib_dev, "pid %i, decrementing autospollers\n", + current->pid); + if (board->autospollers > 0) + board->autospollers--; + else + pr_err("gpib: Attempt to decrement zero autospollers\n"); + } + } else { + pr_err("gpib: Unexpected null gpib_descriptor\n"); + } + + cleanup_open_devices(priv, board); + + if (atomic_read(&priv->holding_mutex)) + mutex_unlock(&board->user_mutex); + + if (priv->got_module && board->use_count) { + module_put(board->provider_module); + --board->use_count; + } + + kfree(filep->private_data); + filep->private_data = NULL; + } + + return 0; +} + +long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + unsigned int minor = iminor(filep->f_path.dentry->d_inode); + gpib_board_t *board; + gpib_file_private_t *file_priv = filep->private_data; + long retval = -ENOTTY; + + if (minor >= GPIB_MAX_NUM_BOARDS) { + pr_err("gpib: invalid minor number of device file\n"); + return -ENODEV; + } + board = &board_array[minor]; + + if (mutex_lock_interruptible(&board->big_gpib_mutex)) + return -ERESTARTSYS; + + dev_dbg(board->gpib_dev, "pid %i, ioctl %d, interface=%s, use=%d, onl=%d\n", + current->pid, cmd & 0xff, + board->interface ? board->interface->name : "", + board->use_count, + board->online); + + switch (cmd) { + case CFCBOARDTYPE: + retval = board_type_ioctl(file_priv, board, arg); + goto done; + case IBONL: + retval = online_ioctl(board, arg); + goto done; + default: + break; + } + if (!board->interface) { + pr_err("gpib: no gpib board configured on /dev/gpib%i\n", minor); + retval = -ENODEV; + goto done; + } + if (file_priv->got_module == 0) { + if (!try_module_get(board->provider_module)) { + pr_err("gpib: try_module_get() failed\n"); + retval = -EIO; + goto done; + } + file_priv->got_module = 1; + board->use_count++; + } + switch (cmd) { + case CFCBASE: + retval = iobase_ioctl(&board->config, arg); + goto done; + case CFCIRQ: + retval = irq_ioctl(&board->config, arg); + goto done; + case CFCDMA: + retval = dma_ioctl(&board->config, arg); + goto done; + case IBAUTOSPOLL: + retval = autospoll_ioctl(board, file_priv, arg); + goto done; + case IBBOARD_INFO: + retval = board_info_ioctl(board, arg); + goto done; + case IBMUTEX: + /* Need to unlock board->big_gpib_mutex before potentially locking board->user_mutex + * to maintain consistent locking order + */ + mutex_unlock(&board->big_gpib_mutex); + return mutex_ioctl(board, file_priv, arg); + case IBPAD: + retval = pad_ioctl(board, file_priv, arg); + goto done; + case IBSAD: + retval = sad_ioctl(board, file_priv, arg); + goto done; + case IBSELECT_PCI: + retval = select_pci_ioctl(&board->config, arg); + goto done; + case IBSELECT_DEVICE_PATH: + retval = select_device_path_ioctl(&board->config, arg); + goto done; + default: + break; + } + + if (!board->online) { + pr_err("gpib: ioctl %i invalid for offline board\n", + cmd & 0xff); + retval = -EINVAL; + goto done; + } + + switch (cmd) { + case IBEVENT: + retval = event_ioctl(board, arg); + goto done; + case IBCLOSEDEV: + retval = close_dev_ioctl(filep, board, arg); + goto done; + case IBOPENDEV: + retval = open_dev_ioctl(filep, board, arg); + goto done; + case IBSPOLL_BYTES: + retval = status_bytes_ioctl(board, arg); + goto done; + case IBWAIT: + retval = wait_ioctl(file_priv, board, arg); + if (retval == -ERESTARTSYS) + return retval; + goto done; + case IBLINES: + retval = line_status_ioctl(board, arg); + goto done; + case IBLOC: + board->interface->return_to_local(board); + retval = 0; + goto done; + default: + break; + } + + spin_lock(&board->locking_pid_spinlock); + if (current->pid != board->locking_pid) { + spin_unlock(&board->locking_pid_spinlock); + pr_err("gpib: need to hold board lock to perform ioctl %i\n", + cmd & 0xff); + retval = -EPERM; + goto done; + } + spin_unlock(&board->locking_pid_spinlock); + + switch (cmd) { + case IB_T1_DELAY: + retval = t1_delay_ioctl(board, arg); + goto done; + case IBCAC: + retval = take_control_ioctl(board, arg); + goto done; + case IBCMD: + /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex + * before we call them. + */ + mutex_unlock(&board->big_gpib_mutex); + return command_ioctl(file_priv, board, arg); + case IBEOS: + retval = eos_ioctl(board, arg); + goto done; + case IBGTS: + retval = ibgts(board); + goto done; + case IBPPC: + retval = ppc_ioctl(board, arg); + goto done; + case IBPP2_SET: + retval = set_local_ppoll_mode_ioctl(board, arg); + goto done; + case IBPP2_GET: + retval = get_local_ppoll_mode_ioctl(board, arg); + goto done; + case IBQUERY_BOARD_RSV: + retval = query_board_rsv_ioctl(board, arg); + goto done; + case IBRD: + /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex + * before we call them. + */ + mutex_unlock(&board->big_gpib_mutex); + return read_ioctl(file_priv, board, arg); + case IBRPP: + retval = parallel_poll_ioctl(board, arg); + goto done; + case IBRSC: + retval = request_system_control_ioctl(board, arg); + goto done; + case IBRSP: + retval = serial_poll_ioctl(board, arg); + goto done; + case IBRSV: + retval = request_service_ioctl(board, arg); + goto done; + case IBRSV2: + retval = request_service2_ioctl(board, arg); + goto done; + case IBSIC: + retval = interface_clear_ioctl(board, arg); + goto done; + case IBSRE: + retval = remote_enable_ioctl(board, arg); + goto done; + case IBTMO: + retval = timeout_ioctl(board, arg); + goto done; + case IBWRT: + /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex + * before we call them. + */ + mutex_unlock(&board->big_gpib_mutex); + return write_ioctl(file_priv, board, arg); + default: + retval = -ENOTTY; + goto done; + } + +done: + mutex_unlock(&board->big_gpib_mutex); + dev_dbg(board->gpib_dev, "ioctl done status = 0x%lx\n", board->status); + return retval; +} + +static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg) +{ + struct list_head *list_ptr; + board_type_ioctl_t cmd; + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (board->online) { + pr_err("gpib: can't change board type while board is online.\n"); + return -EBUSY; + } + + retval = copy_from_user(&cmd, (void *)arg, sizeof(board_type_ioctl_t)); + if (retval) + return retval; + + for (list_ptr = registered_drivers.next; list_ptr != ®istered_drivers; + list_ptr = list_ptr->next) { + gpib_interface_list_t *entry; + + entry = list_entry(list_ptr, gpib_interface_list_t, list); + if (strcmp(entry->interface->name, cmd.name) == 0) { + int i; + int had_module = file_priv->got_module; + + if (board->use_count) { + for (i = 0; i < board->use_count; ++i) + module_put(board->provider_module); + board->interface = NULL; + file_priv->got_module = 0; + } + board->interface = entry->interface; + board->provider_module = entry->module; + for (i = 0; i < board->use_count; ++i) { + if (!try_module_get(entry->module)) { + board->use_count = i; + return -EIO; + } + } + if (had_module == 0) { + if (!try_module_get(entry->module)) + return -EIO; + ++board->use_count; + } + file_priv->got_module = 1; + return 0; + } + } + + return -EINVAL; +} + +static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, + unsigned long arg) +{ + read_write_ioctl_t read_cmd; + u8 *userbuf; + unsigned long remain; + int end_flag = 0; + int retval; + ssize_t read_ret = 0; + gpib_descriptor_t *desc; + size_t nbytes; + + retval = copy_from_user(&read_cmd, (void *)arg, sizeof(read_cmd)); + if (retval) + return -EFAULT; + + if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count) + return -EINVAL; + + desc = handle_to_descriptor(file_priv, read_cmd.handle); + if (!desc) + return -EINVAL; + + if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr))) + return -EFAULT; + + userbuf = (u8 *)(unsigned long)read_cmd.buffer_ptr; + userbuf += read_cmd.completed_transfer_count; + + remain = read_cmd.requested_transfer_count - read_cmd.completed_transfer_count; + + /* Check write access to buffer */ + if (!access_ok(userbuf, remain)) + return -EFAULT; + + atomic_set(&desc->io_in_progress, 1); + + /* Read buffer loads till we fill the user supplied buffer */ + while (remain > 0 && end_flag == 0) { + nbytes = 0; + read_ret = ibrd(board, board->buffer, (board->buffer_length < remain) ? + board->buffer_length : remain, &end_flag, &nbytes); + if (nbytes == 0) + break; + retval = copy_to_user(userbuf, board->buffer, nbytes); + if (retval) { + retval = -EFAULT; + break; + } + remain -= nbytes; + userbuf += nbytes; + if (read_ret < 0) + break; + } + read_cmd.completed_transfer_count = read_cmd.requested_transfer_count - remain; + read_cmd.end = end_flag; + /* suppress errors (for example due to timeout or interruption by device clear) + * if all bytes got sent. This prevents races that can occur in the various drivers + * if a device receives a device clear immediately after a transfer completes and + * the driver code wasn't careful enough to handle that case. + */ + if (remain == 0 || end_flag) + read_ret = 0; + if (retval == 0) + retval = copy_to_user((void *)arg, &read_cmd, sizeof(read_cmd)); + + atomic_set(&desc->io_in_progress, 0); + + wake_up_interruptible(&board->wait); + if (retval) + return -EFAULT; + + return read_ret; +} + +static int command_ioctl(gpib_file_private_t *file_priv, + gpib_board_t *board, unsigned long arg) +{ + read_write_ioctl_t cmd; + u8 *userbuf; + unsigned long remain; + int retval; + int fault = 0; + gpib_descriptor_t *desc; + size_t bytes_written; + int no_clear_io_in_prog; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + if (cmd.completed_transfer_count > cmd.requested_transfer_count) + return -EINVAL; + + desc = handle_to_descriptor(file_priv, cmd.handle); + if (!desc) + return -EINVAL; + + userbuf = (u8 *)(unsigned long)cmd.buffer_ptr; + userbuf += cmd.completed_transfer_count; + + no_clear_io_in_prog = cmd.end; + cmd.end = 0; + + remain = cmd.requested_transfer_count - cmd.completed_transfer_count; + + /* Check read access to buffer */ + if (!access_ok(userbuf, remain)) + return -EFAULT; + + /* Write buffer loads till we empty the user supplied buffer. + * Call drivers at least once, even if remain is zero, in + * order to allow them to insure previous commands were + * completely finished, in the case of a restarted ioctl. + */ + + atomic_set(&desc->io_in_progress, 1); + + do { + fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ? + board->buffer_length : remain); + if (fault) { + retval = -EFAULT; + bytes_written = 0; + } else { + retval = ibcmd(board, board->buffer, (board->buffer_length < remain) ? + board->buffer_length : remain, &bytes_written); + } + remain -= bytes_written; + userbuf += bytes_written; + if (retval < 0) { + atomic_set(&desc->io_in_progress, 0); + + wake_up_interruptible(&board->wait); + break; + } + } while (remain > 0); + + cmd.completed_transfer_count = cmd.requested_transfer_count - remain; + + if (fault == 0) + fault = copy_to_user((void *)arg, &cmd, sizeof(cmd)); + + /* + * no_clear_io_in_prog (cmd.end) is true when io_in_progress should + * not be set to zero because the cmd in progress is the address setup + * operation for an async read or write. This causes CMPL not to be set + * in general_ibstatus until the async read or write completes. + */ + if (!no_clear_io_in_prog || fault) + atomic_set(&desc->io_in_progress, 0); + + wake_up_interruptible(&board->wait); + if (fault) + return -EFAULT; + + return retval; +} + +static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, + unsigned long arg) +{ + read_write_ioctl_t write_cmd; + u8 *userbuf; + unsigned long remain; + int retval = 0; + int fault; + gpib_descriptor_t *desc; + + fault = copy_from_user(&write_cmd, (void *)arg, sizeof(write_cmd)); + if (fault) + return -EFAULT; + + if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count) + return -EINVAL; + + desc = handle_to_descriptor(file_priv, write_cmd.handle); + if (!desc) + return -EINVAL; + + userbuf = (u8 *)(unsigned long)write_cmd.buffer_ptr; + userbuf += write_cmd.completed_transfer_count; + + remain = write_cmd.requested_transfer_count - write_cmd.completed_transfer_count; + + /* Check read access to buffer */ + if (!access_ok(userbuf, remain)) + return -EFAULT; + + atomic_set(&desc->io_in_progress, 1); + + /* Write buffer loads till we empty the user supplied buffer */ + while (remain > 0) { + int send_eoi; + size_t bytes_written = 0; + + send_eoi = remain <= board->buffer_length && write_cmd.end; + fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ? + board->buffer_length : remain); + if (fault) { + retval = -EFAULT; + break; + } + retval = ibwrt(board, board->buffer, (board->buffer_length < remain) ? + board->buffer_length : remain, send_eoi, &bytes_written); + remain -= bytes_written; + userbuf += bytes_written; + if (retval < 0) + break; + } + write_cmd.completed_transfer_count = write_cmd.requested_transfer_count - remain; + /* suppress errors (for example due to timeout or interruption by device clear) + * if all bytes got sent. This prevents races that can occur in the various drivers + * if a device receives a device clear immediately after a transfer completes and + * the driver code wasn't careful enough to handle that case. + */ + if (remain == 0) + retval = 0; + if (fault == 0) + fault = copy_to_user((void *)arg, &write_cmd, sizeof(write_cmd)); + + atomic_set(&desc->io_in_progress, 0); + + wake_up_interruptible(&board->wait); + if (fault) + return -EFAULT; + + return retval; +} + +static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg) +{ + gpib_status_queue_t *device; + spoll_bytes_ioctl_t cmd; + int retval; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + device = get_gpib_status_queue(board, cmd.pad, cmd.sad); + if (!device) + cmd.num_bytes = 0; + else + cmd.num_bytes = num_status_bytes(device); + + retval = copy_to_user((void *)arg, &cmd, sizeof(cmd)); + if (retval) + return -EFAULT; + + return 0; +} + +static int increment_open_device_count(gpib_board_t *board, struct list_head *head, + unsigned int pad, int sad) +{ + struct list_head *list_ptr; + gpib_status_queue_t *device; + + /* first see if address has already been opened, then increment + * open count + */ + for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { + device = list_entry(list_ptr, gpib_status_queue_t, list); + if (gpib_address_equal(device->pad, device->sad, pad, sad)) { + dev_dbg(board->gpib_dev, "pid %i, incrementing open count for pad %i, sad %i\n", + current->pid, device->pad, device->sad); + device->reference_count++; + return 0; + } + } + + /* otherwise we need to allocate a new gpib_status_queue_t */ + device = kmalloc(sizeof(gpib_status_queue_t), GFP_ATOMIC); + if (!device) + return -ENOMEM; + init_gpib_status_queue(device); + device->pad = pad; + device->sad = sad; + device->reference_count = 1; + + list_add(&device->list, head); + + dev_dbg(board->gpib_dev, "pid %i, opened pad %i, sad %i\n", + current->pid, device->pad, device->sad); + + return 0; +} + +static int subtract_open_device_count(gpib_board_t *board, struct list_head *head, + unsigned int pad, int sad, unsigned int count) +{ + gpib_status_queue_t *device; + struct list_head *list_ptr; + + for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { + device = list_entry(list_ptr, gpib_status_queue_t, list); + if (gpib_address_equal(device->pad, device->sad, pad, sad)) { + dev_dbg(board->gpib_dev, "pid %i, decrementing open count for pad %i, sad %i\n", + current->pid, device->pad, device->sad); + if (count > device->reference_count) { + pr_err("gpib: bug! in %s()\n", __func__); + return -EINVAL; + } + device->reference_count -= count; + if (device->reference_count == 0) { + dev_dbg(board->gpib_dev, "pid %i, closing pad %i, sad %i\n", + current->pid, device->pad, device->sad); + list_del(list_ptr); + kfree(device); + } + return 0; + } + } + pr_err("gpib: bug! tried to close address that was never opened!\n"); + return -EINVAL; +} + +static inline int decrement_open_device_count(gpib_board_t *board, struct list_head *head, + unsigned int pad, int sad) +{ + return subtract_open_device_count(board, head, pad, sad, 1); +} + +static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board) +{ + int retval = 0; + int i; + + for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++) { + gpib_descriptor_t *desc; + + desc = file_priv->descriptors[i]; + if (!desc) + continue; + + if (desc->is_board == 0) { + retval = decrement_open_device_count(board, &board->device_list, desc->pad, + desc->sad); + if (retval < 0) + return retval; + } + kfree(desc); + file_priv->descriptors[i] = NULL; + } + + return 0; +} + +static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg) +{ + open_dev_ioctl_t open_dev_cmd; + int retval; + gpib_file_private_t *file_priv = filep->private_data; + int i; + + retval = copy_from_user(&open_dev_cmd, (void *)arg, sizeof(open_dev_cmd)); + if (retval) + return -EFAULT; + + if (mutex_lock_interruptible(&file_priv->descriptors_mutex)) + return -ERESTARTSYS; + for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++) + if (!file_priv->descriptors[i]) + break; + if (i == GPIB_MAX_NUM_DESCRIPTORS) { + mutex_unlock(&file_priv->descriptors_mutex); + return -ERANGE; + } + file_priv->descriptors[i] = kmalloc(sizeof(gpib_descriptor_t), GFP_KERNEL); + if (!file_priv->descriptors[i]) { + mutex_unlock(&file_priv->descriptors_mutex); + return -ENOMEM; + } + init_gpib_descriptor(file_priv->descriptors[i]); + + file_priv->descriptors[i]->pad = open_dev_cmd.pad; + file_priv->descriptors[i]->sad = open_dev_cmd.sad; + file_priv->descriptors[i]->is_board = open_dev_cmd.is_board; + mutex_unlock(&file_priv->descriptors_mutex); + + retval = increment_open_device_count(board, &board->device_list, open_dev_cmd.pad, + open_dev_cmd.sad); + if (retval < 0) + return retval; + + /* clear stuck srq state, since we may be able to find service request on + * the new device + */ + atomic_set(&board->stuck_srq, 0); + + open_dev_cmd.handle = i; + retval = copy_to_user((void *)arg, &open_dev_cmd, sizeof(open_dev_cmd)); + if (retval) + return -EFAULT; + + return 0; +} + +static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg) +{ + close_dev_ioctl_t cmd; + gpib_file_private_t *file_priv = filep->private_data; + int retval; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS) + return -EINVAL; + if (!file_priv->descriptors[cmd.handle]) + return -EINVAL; + + retval = decrement_open_device_count(board, &board->device_list, + file_priv->descriptors[cmd.handle]->pad, + file_priv->descriptors[cmd.handle]->sad); + if (retval < 0) + return retval; + + kfree(file_priv->descriptors[cmd.handle]); + file_priv->descriptors[cmd.handle] = NULL; + + return 0; +} + +static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg) +{ + serial_poll_ioctl_t serial_cmd; + int retval; + + dev_dbg(board->gpib_dev, "pid %i, entering %s()\n", current->pid, __func__); + + retval = copy_from_user(&serial_cmd, (void *)arg, sizeof(serial_cmd)); + if (retval) + return -EFAULT; + + retval = get_serial_poll_byte(board, serial_cmd.pad, serial_cmd.sad, board->usec_timeout, + &serial_cmd.status_byte); + if (retval < 0) + return retval; + + retval = copy_to_user((void *)arg, &serial_cmd, sizeof(serial_cmd)); + if (retval) + return -EFAULT; + + return 0; +} + +static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, + unsigned long arg) +{ + wait_ioctl_t wait_cmd; + int retval; + gpib_descriptor_t *desc; + + retval = copy_from_user(&wait_cmd, (void *)arg, sizeof(wait_cmd)); + if (retval) + return -EFAULT; + + desc = handle_to_descriptor(file_priv, wait_cmd.handle); + if (!desc) + return -EINVAL; + + retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask, + wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc); + if (retval < 0) + return retval; + + retval = copy_to_user((void *)arg, &wait_cmd, sizeof(wait_cmd)); + if (retval) + return -EFAULT; + + return 0; +} + +static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg) +{ + u8 poll_byte; + int retval; + + retval = ibrpp(board, &poll_byte); + if (retval < 0) + return retval; + + retval = copy_to_user((void *)arg, &poll_byte, sizeof(poll_byte)); + if (retval) + return -EFAULT; + + return 0; +} + +static int online_ioctl(gpib_board_t *board, unsigned long arg) +{ + online_ioctl_t online_cmd; + int retval; + void *init_data = NULL; + + board->config.init_data = NULL; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + retval = copy_from_user(&online_cmd, (void *)arg, sizeof(online_cmd)); + if (retval) + return -EFAULT; + if (online_cmd.init_data_length > 0) { + board->config.init_data = vmalloc(online_cmd.init_data_length); + if (!board->config.init_data) + return -ENOMEM; + if (WARN_ON_ONCE(sizeof(init_data) > sizeof(online_cmd.init_data_ptr))) + return -EFAULT; + init_data = (void *)(unsigned long)(online_cmd.init_data_ptr); + retval = copy_from_user(board->config.init_data, init_data, + online_cmd.init_data_length); + if (retval) { + vfree(board->config.init_data); + return -EFAULT; + } + board->config.init_data_length = online_cmd.init_data_length; + } else { + board->config.init_data = NULL; + board->config.init_data_length = 0; + } + if (online_cmd.online) + retval = ibonline(board); + else + retval = iboffline(board); + if (board->config.init_data) { + vfree(board->config.init_data); + board->config.init_data = NULL; + board->config.init_data_length = 0; + } + return retval; +} + +static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg) +{ + int enable; + int retval; + + retval = copy_from_user(&enable, (void *)arg, sizeof(enable)); + if (retval) + return -EFAULT; + + return ibsre(board, enable); +} + +static int take_control_ioctl(gpib_board_t *board, unsigned long arg) +{ + int synchronous; + int retval; + + retval = copy_from_user(&synchronous, (void *)arg, sizeof(synchronous)); + if (retval) + return -EFAULT; + + return ibcac(board, synchronous, 1); +} + +static int line_status_ioctl(gpib_board_t *board, unsigned long arg) +{ + short lines; + int retval; + + retval = iblines(board, &lines); + if (retval < 0) + return retval; + + retval = copy_to_user((void *)arg, &lines, sizeof(lines)); + if (retval) + return -EFAULT; + + return 0; +} + +static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg) +{ + pad_ioctl_t cmd; + int retval; + gpib_descriptor_t *desc; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + desc = handle_to_descriptor(file_priv, cmd.handle); + if (!desc) + return -EINVAL; + + if (desc->is_board) { + retval = ibpad(board, cmd.pad); + if (retval < 0) + return retval; + } else { + retval = decrement_open_device_count(board, &board->device_list, desc->pad, + desc->sad); + if (retval < 0) + return retval; + + desc->pad = cmd.pad; + + retval = increment_open_device_count(board, &board->device_list, desc->pad, + desc->sad); + if (retval < 0) + return retval; + } + + return 0; +} + +static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg) +{ + sad_ioctl_t cmd; + int retval; + gpib_descriptor_t *desc; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + desc = handle_to_descriptor(file_priv, cmd.handle); + if (!desc) + return -EINVAL; + + if (desc->is_board) { + retval = ibsad(board, cmd.sad); + if (retval < 0) + return retval; + } else { + retval = decrement_open_device_count(board, &board->device_list, desc->pad, + desc->sad); + if (retval < 0) + return retval; + + desc->sad = cmd.sad; + + retval = increment_open_device_count(board, &board->device_list, desc->pad, + desc->sad); + if (retval < 0) + return retval; + } + return 0; +} + +static int eos_ioctl(gpib_board_t *board, unsigned long arg) +{ + eos_ioctl_t eos_cmd; + int retval; + + retval = copy_from_user(&eos_cmd, (void *)arg, sizeof(eos_cmd)); + if (retval) + return -EFAULT; + + return ibeos(board, eos_cmd.eos, eos_cmd.eos_flags); +} + +static int request_service_ioctl(gpib_board_t *board, unsigned long arg) +{ + u8 status_byte; + int retval; + + retval = copy_from_user(&status_byte, (void *)arg, sizeof(status_byte)); + if (retval) + return -EFAULT; + + return ibrsv2(board, status_byte, status_byte & request_service_bit); +} + +static int request_service2_ioctl(gpib_board_t *board, unsigned long arg) +{ + request_service2_t request_service2_cmd; + int retval; + + retval = copy_from_user(&request_service2_cmd, (void *)arg, sizeof(request_service2_t)); + if (retval) + return -EFAULT; + + return ibrsv2(board, request_service2_cmd.status_byte, + request_service2_cmd.new_reason_for_service); +} + +static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg) +{ + u64 base_addr; + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + retval = copy_from_user(&base_addr, (void *)arg, sizeof(base_addr)); + if (retval) + return -EFAULT; + + if (WARN_ON_ONCE(sizeof(void *) > sizeof(base_addr))) + return -EFAULT; + config->ibbase = (void *)(unsigned long)(base_addr); + + return 0; +} + +static int irq_ioctl(gpib_board_config_t *config, unsigned long arg) +{ + unsigned int irq; + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + retval = copy_from_user(&irq, (void *)arg, sizeof(irq)); + if (retval) + return -EFAULT; + + config->ibirq = irq; + + return 0; +} + +static int dma_ioctl(gpib_board_config_t *config, unsigned long arg) +{ + unsigned int dma_channel; + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + retval = copy_from_user(&dma_channel, (void *)arg, sizeof(dma_channel)); + if (retval) + return -EFAULT; + + config->ibdma = dma_channel; + + return 0; +} + +static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg) +{ + autospoll_ioctl_t enable; + int retval; + gpib_descriptor_t *desc; + + retval = copy_from_user(&enable, (void *)arg, sizeof(enable)); + if (retval) + return -EFAULT; + + desc = handle_to_descriptor(file_priv, 0); /* board handle is 0 */ + + if (enable) { + if (!desc->autopoll_enabled) { + board->autospollers++; + desc->autopoll_enabled = 1; + } + retval = 0; + } else { + if (desc->autopoll_enabled) { + desc->autopoll_enabled = 0; + if (board->autospollers > 0) { + board->autospollers--; + retval = 0; + } else { + pr_err("gpib: tried to set number of autospollers negative\n"); + retval = -EINVAL; + } + } else { + pr_err("gpib: autopoll disable requested before enable\n"); + retval = -EINVAL; + } + } + return retval; +} + +static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv, + unsigned long arg) +{ + int retval, lock_mutex; + + retval = copy_from_user(&lock_mutex, (void *)arg, sizeof(lock_mutex)); + if (retval) + return -EFAULT; + + if (lock_mutex) { + retval = mutex_lock_interruptible(&board->user_mutex); + if (retval) { + pr_warn("gpib: ioctl interrupted while waiting on lock\n"); + return -ERESTARTSYS; + } + + spin_lock(&board->locking_pid_spinlock); + board->locking_pid = current->pid; + spin_unlock(&board->locking_pid_spinlock); + + atomic_set(&file_priv->holding_mutex, 1); + + dev_dbg(board->gpib_dev, "pid %i, locked board %d mutex\n", + current->pid, board->minor); + } else { + spin_lock(&board->locking_pid_spinlock); + if (current->pid != board->locking_pid) { + pr_err("gpib: bug! pid %i tried to release mutex held by pid %i\n", + current->pid, board->locking_pid); + spin_unlock(&board->locking_pid_spinlock); + return -EPERM; + } + board->locking_pid = 0; + spin_unlock(&board->locking_pid_spinlock); + + atomic_set(&file_priv->holding_mutex, 0); + + mutex_unlock(&board->user_mutex); + dev_dbg(board->gpib_dev, "pid %i, unlocked board %i mutex\n", + current->pid, board->minor); + } + return 0; +} + +static int timeout_ioctl(gpib_board_t *board, unsigned long arg) +{ + unsigned int timeout; + int retval; + + retval = copy_from_user(&timeout, (void *)arg, sizeof(timeout)); + if (retval) + return -EFAULT; + + board->usec_timeout = timeout; + dev_dbg(board->gpib_dev, "pid %i, timeout set to %i usec\n", current->pid, timeout); + + return 0; +} + +static int ppc_ioctl(gpib_board_t *board, unsigned long arg) +{ + ppoll_config_ioctl_t cmd; + int retval; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + if (cmd.set_ist) { + board->ist = 1; + board->interface->parallel_poll_response(board, board->ist); + } else if (cmd.clear_ist) { + board->ist = 0; + board->interface->parallel_poll_response(board, board->ist); + } + + if (cmd.config) { + retval = ibppc(board, cmd.config); + if (retval < 0) + return retval; + } + + return 0; +} + +static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg) +{ + local_ppoll_mode_ioctl_t cmd; + int retval; + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + if (!board->interface->local_parallel_poll_mode) { + pr_warn("gpib: local/remote parallel poll mode not supported by driver."); + return -EIO; + } + board->local_ppoll_mode = cmd != 0; + board->interface->local_parallel_poll_mode(board, board->local_ppoll_mode); + + return 0; +} + +static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg) +{ + local_ppoll_mode_ioctl_t cmd; + int retval; + + cmd = board->local_ppoll_mode; + retval = copy_to_user((void *)arg, &cmd, sizeof(cmd)); + if (retval) + return -EFAULT; + + return 0; +} + +static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg) +{ + int status; + int retval; + + status = board->interface->serial_poll_status(board); + + retval = copy_to_user((void *)arg, &status, sizeof(status)); + if (retval) + return -EFAULT; + + return 0; +} + +static int board_info_ioctl(const gpib_board_t *board, unsigned long arg) +{ + board_info_ioctl_t info; + int retval; + + info.pad = board->pad; + info.sad = board->sad; + info.parallel_poll_configuration = board->parallel_poll_configuration; + info.is_system_controller = board->master; + if (board->autospollers) + info.autopolling = 1; + else + info.autopolling = 0; + info.t1_delay = board->t1_nano_sec; + info.ist = board->ist; + info.no_7_bit_eos = board->interface->no_7_bit_eos; + retval = copy_to_user((void *)arg, &info, sizeof(info)); + if (retval) + return -EFAULT; + + return 0; +} + +static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg) +{ + unsigned int usec_duration; + int retval; + + retval = copy_from_user(&usec_duration, (void *)arg, sizeof(usec_duration)); + if (retval) + return -EFAULT; + + return ibsic(board, usec_duration); +} + +static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg) +{ + select_pci_ioctl_t selection; + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + retval = copy_from_user(&selection, (void *)arg, sizeof(selection)); + if (retval) + return -EFAULT; + + config->pci_bus = selection.pci_bus; + config->pci_slot = selection.pci_slot; + + return 0; +} + +static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg) +{ + select_device_path_ioctl_t *selection; + int retval; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + selection = vmalloc(sizeof(select_device_path_ioctl_t)); + if (!selection) + return -ENOMEM; + + retval = copy_from_user(selection, (void *)arg, sizeof(select_device_path_ioctl_t)); + if (retval) { + vfree(selection); + return -EFAULT; + } + + selection->device_path[sizeof(selection->device_path) - 1] = '\0'; + kfree(config->device_path); + config->device_path = NULL; + if (strlen(selection->device_path) > 0) + config->device_path = kstrdup(selection->device_path, GFP_KERNEL); + + vfree(selection); + return 0; +} + +unsigned int num_gpib_events(const gpib_event_queue_t *queue) +{ + return queue->num_events; +} + +static int push_gpib_event_nolock(gpib_board_t *board, short event_type) +{ + gpib_event_queue_t *queue = &board->event_queue; + struct list_head *head = &queue->event_head; + gpib_event_t *event; + static const unsigned int max_num_events = 1024; + int retval; + + if (num_gpib_events(queue) >= max_num_events) { + short lost_event; + + queue->dropped_event = 1; + retval = pop_gpib_event_nolock(board, queue, &lost_event); + if (retval < 0) + return retval; + } + + event = kmalloc(sizeof(gpib_event_t), GFP_ATOMIC); + if (!event) { + queue->dropped_event = 1; + pr_err("gpib: failed to allocate memory for event\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&event->list); + event->event_type = event_type; + + list_add_tail(&event->list, head); + + queue->num_events++; + + dev_dbg(board->gpib_dev, "pushed event %i, %i in queue\n", + (int)event_type, num_gpib_events(queue)); + + return 0; +} + +// push event onto back of event queue +int push_gpib_event(gpib_board_t *board, short event_type) +{ + unsigned long flags; + int retval; + + spin_lock_irqsave(&board->event_queue.lock, flags); + retval = push_gpib_event_nolock(board, event_type); + spin_unlock_irqrestore(&board->event_queue.lock, flags); + + if (event_type == EventDevTrg) + board->status |= DTAS; + if (event_type == EventDevClr) + board->status |= DCAS; + + return retval; +} +EXPORT_SYMBOL(push_gpib_event); + +static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type) +{ + struct list_head *head = &queue->event_head; + struct list_head *front = head->next; + gpib_event_t *event; + + if (num_gpib_events(queue) == 0) { + *event_type = EventNone; + return 0; + } + + if (front == head) + return -EIO; + + if (queue->dropped_event) { + queue->dropped_event = 0; + return -EPIPE; + } + + event = list_entry(front, gpib_event_t, list); + *event_type = event->event_type; + + list_del(front); + kfree(event); + + queue->num_events--; + + dev_dbg(board->gpib_dev, "popped event %i, %i in queue\n", + (int)*event_type, num_gpib_events(queue)); + + return 0; +} + +// pop event from front of event queue +int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type) +{ + unsigned long flags; + int retval; + + spin_lock_irqsave(&queue->lock, flags); + retval = pop_gpib_event_nolock(board, queue, event_type); + spin_unlock_irqrestore(&queue->lock, flags); + return retval; +} + +static int event_ioctl(gpib_board_t *board, unsigned long arg) +{ + event_ioctl_t user_event; + int retval; + short event; + + retval = pop_gpib_event(board, &board->event_queue, &event); + if (retval < 0) + return retval; + + user_event = event; + + retval = copy_to_user((void *)arg, &user_event, sizeof(user_event)); + if (retval) + return -EFAULT; + + return 0; +} + +static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg) +{ + rsc_ioctl_t request_control; + int retval; + + retval = copy_from_user(&request_control, (void *)arg, sizeof(request_control)); + if (retval) + return -EFAULT; + + ibrsc(board, request_control); + + return 0; +} + +static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg) +{ + t1_delay_ioctl_t cmd; + unsigned int delay; + int retval; + + if (!board->interface->t1_delay) { + pr_warn("gpib: t1 delay not implemented in driver!\n"); + return -EIO; + } + + retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd)); + if (retval) + return -EFAULT; + + delay = cmd; + + board->t1_nano_sec = board->interface->t1_delay(board, delay); + + return 0; +} + +const struct file_operations ib_fops = { +owner: THIS_MODULE, +llseek : NULL, +unlocked_ioctl : &ibioctl, +compat_ioctl : &ibioctl, +open : &ibopen, +release : &ibclose, +}; + +gpib_board_t board_array[GPIB_MAX_NUM_BOARDS]; + +LIST_HEAD(registered_drivers); + +void init_gpib_descriptor(gpib_descriptor_t *desc) +{ + desc->pad = 0; + desc->sad = -1; + desc->is_board = 0; + desc->autopoll_enabled = 0; + atomic_set(&desc->io_in_progress, 0); +} + +void gpib_register_driver(gpib_interface_t *interface, struct module *provider_module) +{ + struct gpib_interface_list_struct *entry; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return; + + entry->interface = interface; + entry->module = provider_module; + list_add(&entry->list, ®istered_drivers); + pr_info("gpib: registered %s interface\n", interface->name); +} +EXPORT_SYMBOL(gpib_register_driver); + +void gpib_unregister_driver(gpib_interface_t *interface) +{ + int i; + struct list_head *list_ptr; + + for (i = 0; i < GPIB_MAX_NUM_BOARDS; i++) { + gpib_board_t *board = &board_array[i]; + + if (board->interface == interface) { + if (board->use_count > 0) + pr_warn("gpib: Warning: deregistered interface %s in use\n", + interface->name); + iboffline(board); + board->interface = NULL; + } + } + for (list_ptr = registered_drivers.next; list_ptr != ®istered_drivers;) { + gpib_interface_list_t *entry; + + entry = list_entry(list_ptr, gpib_interface_list_t, list); + list_ptr = list_ptr->next; + if (entry->interface == interface) { + list_del(&entry->list); + kfree(entry); + } + } + pr_info("gpib: unregistered %s interface\n", interface->name); +} +EXPORT_SYMBOL(gpib_unregister_driver); + +static void init_gpib_board_config(gpib_board_config_t *config) +{ + memset(config, 0, sizeof(gpib_board_config_t)); + config->pci_bus = -1; + config->pci_slot = -1; +} + +void init_gpib_board(gpib_board_t *board) +{ + board->interface = NULL; + board->provider_module = NULL; + board->buffer = NULL; + board->buffer_length = 0; + board->status = 0; + init_waitqueue_head(&board->wait); + mutex_init(&board->user_mutex); + mutex_init(&board->big_gpib_mutex); + board->locking_pid = 0; + spin_lock_init(&board->locking_pid_spinlock); + spin_lock_init(&board->spinlock); + timer_setup(&board->timer, NULL, 0); + board->dev = NULL; + board->gpib_dev = NULL; + init_gpib_board_config(&board->config); + board->private_data = NULL; + board->use_count = 0; + INIT_LIST_HEAD(&board->device_list); + board->pad = 0; + board->sad = -1; + board->usec_timeout = 3000000; + board->parallel_poll_configuration = 0; + board->online = 0; + board->autospollers = 0; + board->autospoll_task = NULL; + init_event_queue(&board->event_queue); + board->minor = -1; + init_gpib_pseudo_irq(&board->pseudo_irq); + board->master = 1; + atomic_set(&board->stuck_srq, 0); + board->local_ppoll_mode = 0; +} + +int gpib_allocate_board(gpib_board_t *board) +{ + if (!board->buffer) { + board->buffer_length = 0x4000; + board->buffer = vmalloc(board->buffer_length); + if (!board->buffer) { + board->buffer_length = 0; + return -ENOMEM; + } + } + return 0; +} + +void gpib_deallocate_board(gpib_board_t *board) +{ + short dummy; + + if (board->buffer) { + vfree(board->buffer); + board->buffer = NULL; + board->buffer_length = 0; + } + while (num_gpib_events(&board->event_queue)) + pop_gpib_event(board, &board->event_queue, &dummy); +} + +static void init_board_array(gpib_board_t *board_array, unsigned int length) +{ + int i; + + for (i = 0; i < length; i++) { + init_gpib_board(&board_array[i]); + board_array[i].minor = i; + } +} + +void init_gpib_status_queue(gpib_status_queue_t *device) +{ + INIT_LIST_HEAD(&device->list); + INIT_LIST_HEAD(&device->status_bytes); + device->num_status_bytes = 0; + device->reference_count = 0; + device->dropped_byte = 0; +} + +static struct class *gpib_class; + +static int __init gpib_common_init_module(void) +{ + int i; + + pr_info("Linux-GPIB core driver\n"); + init_board_array(board_array, GPIB_MAX_NUM_BOARDS); + if (register_chrdev(GPIB_CODE, "gpib", &ib_fops)) { + pr_err("gpib: can't get major %d\n", GPIB_CODE); + return -EIO; + } + gpib_class = class_create("gpib_common"); + if (IS_ERR(gpib_class)) { + pr_err("gpib: failed to create gpib class\n"); + unregister_chrdev(GPIB_CODE, "gpib"); + return PTR_ERR(gpib_class); + } + for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i) + board_array[i].gpib_dev = device_create(gpib_class, 0, + MKDEV(GPIB_CODE, i), NULL, "gpib%i", i); + + return 0; +} + +static void __exit gpib_common_exit_module(void) +{ + int i; + + for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i) + device_destroy(gpib_class, MKDEV(GPIB_CODE, i)); + + class_destroy(gpib_class); + unregister_chrdev(GPIB_CODE, "gpib"); +} + +int gpib_match_device_path(struct device *dev, const char *device_path_in) +{ + if (device_path_in) { + char *device_path; + + device_path = kobject_get_path(&dev->kobj, GFP_KERNEL); + if (!device_path) { + dev_err(dev, "kobject_get_path returned NULL."); + return 0; + } + if (strcmp(device_path_in, device_path) != 0) { + kfree(device_path); + return 0; + } + kfree(device_path); + } + return 1; +} +EXPORT_SYMBOL(gpib_match_device_path); + +struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id, + unsigned int device_id, struct pci_dev *from) +{ + struct pci_dev *pci_device = from; + + while ((pci_device = pci_get_device(vendor_id, device_id, pci_device))) { + if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number) + continue; + if (config->pci_slot >= 0 && config->pci_slot != + PCI_SLOT(pci_device->devfn)) + continue; + if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0) + continue; + return pci_device; + } + return NULL; +} +EXPORT_SYMBOL(gpib_pci_get_device); + +struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id, + unsigned int device_id, unsigned int ss_vendor, + unsigned int ss_device, + struct pci_dev *from) +{ + struct pci_dev *pci_device = from; + + while ((pci_device = pci_get_subsys(vendor_id, device_id, + ss_vendor, ss_device, pci_device))) { + if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number) + continue; + if (config->pci_slot >= 0 && config->pci_slot != + PCI_SLOT(pci_device->devfn)) + continue; + if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0) + continue; + return pci_device; + } + return NULL; +} +EXPORT_SYMBOL(gpib_pci_get_subsys); + +module_init(gpib_common_init_module); +module_exit(gpib_common_exit_module); + diff --git a/drivers/staging/gpib/common/iblib.c b/drivers/staging/gpib/common/iblib.c new file mode 100644 index 0000000000000000000000000000000000000000..db1911cc1b263836484f3e37e0e102745e7c3ce7 --- /dev/null +++ b/drivers/staging/gpib/common/iblib.c @@ -0,0 +1,740 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "ibsys.h" +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/vmalloc.h> + +/* + * IBCAC + * Return to the controller active state from the + * controller standby state, i.e., turn ATN on. Note + * that in order to enter the controller active state + * from the controller idle state, ibsic must be called. + * If sync is non-zero, attempt to take control synchronously. + * If fallback_to_async is non-zero, try to take control asynchronously + * if synchronous attempt fails. + */ +int ibcac(gpib_board_t *board, int sync, int fallback_to_async) +{ + int status = ibstatus(board); + int retval; + + if ((status & CIC) == 0) { + pr_err("gpib: not CIC during %s()\n", __func__); + return -1; + } + + if (status & ATN) + return 0; + + if (sync && (status & LACS) == 0) + /* tcs (take control synchronously) can only possibly work when + * controller is listener. Error code also needs to be -ETIMEDOUT + * or it will giveout without doing fallback. + */ + retval = -ETIMEDOUT; + else + retval = board->interface->take_control(board, sync); + + if (retval < 0 && fallback_to_async) { + if (sync && retval == -ETIMEDOUT) + retval = board->interface->take_control(board, 0); + } + board->interface->update_status(board, 0); + + return retval; +} + +/* After ATN is asserted, it should cause any connected devices + * to start listening for command bytes and leave acceptor idle state. + * So if ATN is asserted and neither NDAC or NRFD are asserted, + * then there are no devices and ibcmd should error out immediately. + * Some gpib hardware sees itself asserting NDAC/NRFD when it + * is controller in charge, in which case this check will + * do nothing useful (but shouldn't cause any harm either). + * Drivers that don't need this check (ni_usb for example) may + * set the skip_check_for_command_acceptors flag in their + * gpib_interface_struct to avoid useless overhead. + */ +static int check_for_command_acceptors(gpib_board_t *board) +{ + int lines; + + if (board->interface->skip_check_for_command_acceptors) + return 0; + if (!board->interface->line_status) + return 0; + + udelay(2); // allow time for devices to respond to ATN if it was just asserted + + lines = board->interface->line_status(board); + if (lines < 0) + return lines; + + if (lines & ValidATN) { + if ((lines & BusATN) == 0) { + pr_err("gpib: ATN not asserted in %s()?", __func__); + return 0; + } + } + + if ((lines & ValidNRFD) && (lines & ValidNDAC)) { + if ((lines & BusNRFD) == 0 && (lines & BusNDAC) == 0) + return -ENOTCONN; + } + + return 0; +} + +/* + * IBCMD + * Write cnt command bytes from buf to the GPIB. The + * command operation terminates only on I/O complete. + * + * NOTE: + * 1. Prior to beginning the command, the interface is + * placed in the controller active state. + * 2. Before calling ibcmd for the first time, ibsic + * must be called to initialize the GPIB and enable + * the interface to leave the controller idle state. + */ +int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written) +{ + ssize_t ret = 0; + int status; + + *bytes_written = 0; + + status = ibstatus(board); + + if ((status & CIC) == 0) { + pr_err("gpib: cannot send command when not controller-in-charge\n"); + return -EIO; + } + + os_start_timer(board, board->usec_timeout); + + ret = ibcac(board, 1, 1); + if (ret == 0) { + ret = check_for_command_acceptors(board); + if (ret == 0) + ret = board->interface->command(board, buf, length, bytes_written); + } + + os_remove_timer(board); + + if (io_timed_out(board)) + ret = -ETIMEDOUT; + + return ret; +} + +/* + * IBGTS + * Go to the controller standby state from the controller + * active state, i.e., turn ATN off. + */ + +int ibgts(gpib_board_t *board) +{ + int status = ibstatus(board); + int retval; + + if ((status & CIC) == 0) { + pr_err("gpib: not CIC during %s()\n", __func__); + return -1; + } + + retval = board->interface->go_to_standby(board); /* go to standby */ + if (retval < 0) + pr_err("gpib: error while going to standby\n"); + + board->interface->update_status(board, 0); + + return retval; +} + +static int autospoll_wait_should_wake_up(gpib_board_t *board) +{ + int retval; + + mutex_lock(&board->big_gpib_mutex); + + retval = board->master && board->autospollers > 0 && + !atomic_read(&board->stuck_srq) && + test_and_clear_bit(SRQI_NUM, &board->status); + + mutex_unlock(&board->big_gpib_mutex); + return retval; +} + +static int autospoll_thread(void *board_void) +{ + gpib_board_t *board = board_void; + int retval = 0; + + dev_dbg(board->gpib_dev, "entering autospoll thread\n"); + + while (1) { + wait_event_interruptible(board->wait, + kthread_should_stop() || + autospoll_wait_should_wake_up(board)); + dev_dbg(board->gpib_dev, "autospoll wait satisfied\n"); + if (kthread_should_stop()) + break; + + mutex_lock(&board->big_gpib_mutex); + /* make sure we are still good after we have lock */ + if (board->autospollers <= 0 || board->master == 0) { + mutex_unlock(&board->big_gpib_mutex); + continue; + } + mutex_unlock(&board->big_gpib_mutex); + + if (try_module_get(board->provider_module)) { + retval = autopoll_all_devices(board); + module_put(board->provider_module); + } else { + pr_err("gpib%i: %s: try_module_get() failed!\n", board->minor, __func__); + } + if (retval <= 0) { + pr_err("gpib%i: %s: stuck SRQ\n", board->minor, __func__); + + atomic_set(&board->stuck_srq, 1); // XXX could be better + set_bit(SRQI_NUM, &board->status); + } + } + pr_info("gpib%i: exiting autospoll thread\n", board->minor); + return retval; +} + +int ibonline(gpib_board_t *board) +{ + int retval; + + if (board->online) + return -EBUSY; + if (!board->interface) + return -ENODEV; + retval = gpib_allocate_board(board); + if (retval < 0) + return retval; + + board->dev = NULL; + board->local_ppoll_mode = 0; + retval = board->interface->attach(board, &board->config); + if (retval < 0) { + board->interface->detach(board); + pr_err("gpib: interface attach failed\n"); + return retval; + } + /* nios2nommu on 2.6.11 uclinux kernel has weird problems + * with autospoll thread causing huge slowdowns + */ +#ifndef CONFIG_NIOS2 + board->autospoll_task = kthread_run(&autospoll_thread, board, + "gpib%d_autospoll_kthread", board->minor); + retval = IS_ERR(board->autospoll_task); + if (retval) { + pr_err("gpib: failed to create autospoll thread\n"); + board->interface->detach(board); + return retval; + } +#endif + board->online = 1; + dev_dbg(board->gpib_dev, "gpib: board online\n"); + + return 0; +} + +/* XXX need to make sure board is generally not in use (grab board lock?) */ +int iboffline(gpib_board_t *board) +{ + int retval; + + if (board->online == 0) + return 0; + if (!board->interface) + return -ENODEV; + + if (board->autospoll_task && !IS_ERR(board->autospoll_task)) { + retval = kthread_stop(board->autospoll_task); + if (retval) + pr_err("gpib: kthread_stop returned %i\n", retval); + board->autospoll_task = NULL; + } + + board->interface->detach(board); + gpib_deallocate_board(board); + board->online = 0; + dev_dbg(board->gpib_dev, "gpib: board offline\n"); + + return 0; +} + +/* + * IBLINES + * Poll the GPIB control lines and return their status in buf. + * + * LSB (bits 0-7) - VALID lines mask (lines that can be monitored). + * Next LSB (bits 8-15) - STATUS lines mask (lines that are currently set). + * + */ +int iblines(const gpib_board_t *board, short *lines) +{ + int retval; + + *lines = 0; + if (!board->interface->line_status) + return 0; + retval = board->interface->line_status(board); + if (retval < 0) + return retval; + *lines = retval; + return 0; +} + +/* + * IBRD + * Read up to 'length' bytes of data from the GPIB into buf. End + * on detection of END (EOI and or EOS) and set 'end_flag'. + * + * NOTE: + * 1. The interface is placed in the controller standby + * state prior to beginning the read. + * 2. Prior to calling ibrd, the intended devices as well + * as the interface board itself must be addressed by + * calling ibcmd. + */ + +int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *nbytes) +{ + ssize_t ret = 0; + int retval; + size_t bytes_read; + + *nbytes = 0; + *end_flag = 0; + if (length == 0) { + pr_warn("gpib: %s() called with zero length?\n", __func__); + return 0; + } + + if (board->master) { + retval = ibgts(board); + if (retval < 0) + return retval; + } + /* XXX resetting timer here could cause timeouts take longer than they should, + * since read_ioctl calls this + * function in a loop, there is probably a similar problem with writes/commands + */ + os_start_timer(board, board->usec_timeout); + + do { + ret = board->interface->read(board, buf, length - *nbytes, end_flag, &bytes_read); + if (ret < 0) { + pr_err("gpib read error\n"); + goto ibrd_out; + } + buf += bytes_read; + *nbytes += bytes_read; + if (need_resched()) + schedule(); + } while (ret == 0 && *nbytes > 0 && *nbytes < length && *end_flag == 0); +ibrd_out: + os_remove_timer(board); + + return ret; +} + +/* + * IBRPP + * Conduct a parallel poll and return the byte in buf. + * + * NOTE: + * 1. Prior to conducting the poll the interface is placed + * in the controller active state. + */ +int ibrpp(gpib_board_t *board, uint8_t *result) +{ + int retval = 0; + + os_start_timer(board, board->usec_timeout); + retval = ibcac(board, 1, 1); + if (retval) + return -1; + + if (board->interface->parallel_poll(board, result)) { + pr_err("gpib: parallel poll failed\n"); + retval = -1; + } + os_remove_timer(board); + return retval; +} + +int ibppc(gpib_board_t *board, uint8_t configuration) +{ + configuration &= 0x1f; + board->interface->parallel_poll_configure(board, configuration); + board->parallel_poll_configuration = configuration; + + return 0; +} + +int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service) +{ + int board_status = ibstatus(board); + const unsigned int MSS = status_byte & request_service_bit; + + if ((board_status & CIC)) { + pr_err("gpib: interface requested service while CIC\n"); + return -EINVAL; + } + + if (MSS == 0 && new_reason_for_service) + return -EINVAL; + + if (board->interface->serial_poll_response2) { + board->interface->serial_poll_response2(board, status_byte, new_reason_for_service); + // fall back on simpler serial_poll_response if the behavior would be the same + } else if (board->interface->serial_poll_response && + (MSS == 0 || (MSS && new_reason_for_service))) { + board->interface->serial_poll_response(board, status_byte); + } else { + return -EOPNOTSUPP; + } + + return 0; +} + +/* + * IBSIC + * Send IFC for at least 100 microseconds. + * + * NOTE: + * 1. Ibsic must be called prior to the first call to + * ibcmd in order to initialize the bus and enable the + * interface to leave the controller idle state. + */ +int ibsic(gpib_board_t *board, unsigned int usec_duration) +{ + if (board->master == 0) { + pr_err("gpib: tried to assert IFC when not system controller\n"); + return -1; + } + + if (usec_duration < 100) + usec_duration = 100; + if (usec_duration > 1000) { + usec_duration = 1000; + pr_warn("gpib: warning, shortening long udelay\n"); + } + + dev_dbg(board->gpib_dev, "sending interface clear\n"); + board->interface->interface_clear(board, 1); + udelay(usec_duration); + board->interface->interface_clear(board, 0); + + return 0; +} + +void ibrsc(gpib_board_t *board, int request_control) +{ + board->master = request_control != 0; + if (!board->interface->request_system_control) { + pr_err("gpib: bug! driver does not implement request_system_control()\n"); + return; + } + board->interface->request_system_control(board, request_control); +} + +/* + * IBSRE + * Send REN true if v is non-zero or false if v is zero. + */ +int ibsre(gpib_board_t *board, int enable) +{ + if (board->master == 0) { + pr_err("gpib: tried to set REN when not system controller\n"); + return -1; + } + + board->interface->remote_enable(board, enable); /* set or clear REN */ + if (!enable) + usleep_range(100, 150); + + return 0; +} + +/* + * IBPAD + * change the GPIB address of the interface board. The address + * must be 0 through 30. ibonl resets the address to PAD. + */ +int ibpad(gpib_board_t *board, unsigned int addr) +{ + if (addr > MAX_GPIB_PRIMARY_ADDRESS) { + pr_err("gpib: invalid primary address %u\n", addr); + return -1; + } + board->pad = addr; + if (board->online) + board->interface->primary_address(board, board->pad); + dev_dbg(board->gpib_dev, "set primary addr to %i\n", board->pad); + return 0; +} + +/* + * IBSAD + * change the secondary GPIB address of the interface board. + * The address must be 0 through 30, or negative disables. ibonl resets the + * address to SAD. + */ +int ibsad(gpib_board_t *board, int addr) +{ + if (addr > MAX_GPIB_SECONDARY_ADDRESS) { + pr_err("gpib: invalid secondary address %i\n", addr); + return -1; + } + board->sad = addr; + if (board->online) { + if (board->sad >= 0) + board->interface->secondary_address(board, board->sad, 1); + else + board->interface->secondary_address(board, 0, 0); + } + dev_dbg(board->gpib_dev, "set secondary addr to %i\n", board->sad); + + return 0; +} + +/* + * IBEOS + * Set the end-of-string modes for I/O operations to v. + * + */ +int ibeos(gpib_board_t *board, int eos, int eosflags) +{ + int retval; + + if (eosflags & ~EOS_MASK) { + pr_err("bad EOS modes\n"); + return -EINVAL; + } + if (eosflags & REOS) { + retval = board->interface->enable_eos(board, eos, eosflags & BIN); + } else { + board->interface->disable_eos(board); + retval = 0; + } + return retval; +} + +int ibstatus(gpib_board_t *board) +{ + return general_ibstatus(board, NULL, 0, 0, NULL); +} + +int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device, + int clear_mask, int set_mask, gpib_descriptor_t *desc) +{ + int status = 0; + short line_status; + + if (board->private_data) { + status = board->interface->update_status(board, clear_mask); + /* XXX should probably stop having drivers use TIMO bit in + * board->status to avoid confusion + */ + status &= ~TIMO; + /* get real SRQI status if we can */ + if (iblines(board, &line_status) == 0) { + if ((line_status & ValidSRQ)) { + if ((line_status & BusSRQ)) + status |= SRQI; + else + status &= ~SRQI; + } + } + } + if (device) + if (num_status_bytes(device)) + status |= RQS; + + if (desc) { + if (set_mask & CMPL) + atomic_set(&desc->io_in_progress, 0); + else if (clear_mask & CMPL) + atomic_set(&desc->io_in_progress, 1); + + if (atomic_read(&desc->io_in_progress)) + status &= ~CMPL; + else + status |= CMPL; + } + if (num_gpib_events(&board->event_queue)) + status |= EVENT; + else + status &= ~EVENT; + + return status; +} + +struct wait_info { + gpib_board_t *board; + struct timer_list timer; + int timed_out; + unsigned long usec_timeout; +}; + +static void wait_timeout(struct timer_list *t) +{ + struct wait_info *winfo = from_timer(winfo, t, timer); + + winfo->timed_out = 1; + wake_up_interruptible(&winfo->board->wait); +} + +static void init_wait_info(struct wait_info *winfo) +{ + winfo->board = NULL; + winfo->timed_out = 0; + timer_setup_on_stack(&winfo->timer, wait_timeout, 0); +} + +static int wait_satisfied(struct wait_info *winfo, gpib_status_queue_t *status_queue, + int wait_mask, int *status, gpib_descriptor_t *desc) +{ + gpib_board_t *board = winfo->board; + int temp_status; + + if (mutex_lock_interruptible(&board->big_gpib_mutex)) + return -ERESTARTSYS; + + temp_status = general_ibstatus(board, status_queue, 0, 0, desc); + + mutex_unlock(&board->big_gpib_mutex); + + if (winfo->timed_out) + temp_status |= TIMO; + else + temp_status &= ~TIMO; + if (wait_mask & temp_status) { + *status = temp_status; + return 1; + } +//XXX does wait for END work? + return 0; +} + +/* install timer interrupt handler */ +static void start_wait_timer(struct wait_info *winfo) +/* Starts the timeout task */ +{ + winfo->timed_out = 0; + + if (winfo->usec_timeout > 0) + mod_timer(&winfo->timer, jiffies + usec_to_jiffies(winfo->usec_timeout)); +} + +static void remove_wait_timer(struct wait_info *winfo) +{ + del_timer_sync(&winfo->timer); + destroy_timer_on_stack(&winfo->timer); +} + +/* + * IBWAIT + * Check or wait for a GPIB event to occur. The mask argument + * is a bit vector corresponding to the status bit vector. It + * has a bit set for each condition which can terminate the wait + * If the mask is 0 then + * no condition is waited for. + */ +int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask, + int *status, unsigned long usec_timeout, gpib_descriptor_t *desc) +{ + int retval = 0; + gpib_status_queue_t *status_queue; + struct wait_info winfo; + + if (desc->is_board) + status_queue = NULL; + else + status_queue = get_gpib_status_queue(board, desc->pad, desc->sad); + + if (wait_mask == 0) { + *status = general_ibstatus(board, status_queue, clear_mask, set_mask, desc); + return 0; + } + + mutex_unlock(&board->big_gpib_mutex); + + init_wait_info(&winfo); + winfo.board = board; + winfo.usec_timeout = usec_timeout; + start_wait_timer(&winfo); + + if (wait_event_interruptible(board->wait, wait_satisfied(&winfo, status_queue, + wait_mask, status, desc))) { + dev_dbg(board->gpib_dev, "wait interrupted\n"); + retval = -ERESTARTSYS; + } + remove_wait_timer(&winfo); + + if (retval) + return retval; + if (mutex_lock_interruptible(&board->big_gpib_mutex)) + return -ERESTARTSYS; + + /* make sure we only clear status bits that we are reporting */ + if (*status & clear_mask || set_mask) + general_ibstatus(board, status_queue, *status & clear_mask, set_mask, 0); + + return 0; +} + +/* + * IBWRT + * Write cnt bytes of data from buf to the GPIB. The write + * operation terminates only on I/O complete. + * + * NOTE: + * 1. Prior to beginning the write, the interface is + * placed in the controller standby state. + * 2. Prior to calling ibwrt, the intended devices as + * well as the interface board itself must be + * addressed by calling ibcmd. + */ +int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written) +{ + int ret = 0; + int retval; + + if (cnt == 0) { + pr_warn("gpib: %s() called with zero length?\n", __func__); + return 0; + } + + if (board->master) { + retval = ibgts(board); + if (retval < 0) + return retval; + } + os_start_timer(board, board->usec_timeout); + ret = board->interface->write(board, buf, cnt, send_eoi, bytes_written); + + if (io_timed_out(board)) + ret = -ETIMEDOUT; + + os_remove_timer(board); + + return ret; +} + diff --git a/drivers/staging/gpib/common/ibsys.h b/drivers/staging/gpib/common/ibsys.h new file mode 100644 index 0000000000000000000000000000000000000000..da20971e9c7ee05e857dab4972f0f2fecf9f8a9f --- /dev/null +++ b/drivers/staging/gpib/common/ibsys.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include "gpibP.h" + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/timer.h> + +#include <linux/io.h> +#include <linux/uaccess.h> +#include <asm/irq.h> +#include <asm/dma.h> + +#define MAX_GPIB_PRIMARY_ADDRESS 30 +#define MAX_GPIB_SECONDARY_ADDRESS 31 + +int gpib_allocate_board(gpib_board_t *board); +void gpib_deallocate_board(gpib_board_t *board); + +unsigned int num_status_bytes(const gpib_status_queue_t *dev); +int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t poll_byte); +int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t *poll_byte); +gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad); +int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, + unsigned int usec_timeout, uint8_t *poll_byte); +int autopoll_all_devices(gpib_board_t *board); diff --git a/drivers/staging/gpib/eastwood/Makefile b/drivers/staging/gpib/eastwood/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c74056f959d034b0dda4ccde6984074c130593ee --- /dev/null +++ b/drivers/staging/gpib/eastwood/Makefile @@ -0,0 +1,3 @@ + +obj-m += fluke_gpib.o + diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.c b/drivers/staging/gpib/eastwood/fluke_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..3f938ab0c84d98a05b0080a8c32dd17640c6972d --- /dev/null +++ b/drivers/staging/gpib/eastwood/fluke_gpib.c @@ -0,0 +1,1179 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * GPIB Driver for Fluke cda devices. Basically, its a driver for a (bugfixed) + * cb7210 connected to channel 0 of a pl330 dma controller. + * Author: Frank Mori Hess <fmh6jj@gmail.com> + * copyright: (C) 2006, 2010, 2015 Fluke Corporation + ***************************************************************************/ + +#include "fluke_gpib.h" + +#include "gpibP.h" +#include <linux/dma-mapping.h> +#include <linux/ioport.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB Driver for Fluke cda devices"); + +static int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config); +static int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config); +static void fluke_detach(gpib_board_t *board); +static int fluke_config_dma(gpib_board_t *board, int output); +static irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board); + +static struct platform_device *fluke_gpib_pdev; + +static uint8_t fluke_locking_read_byte(struct nec7210_priv *nec_priv, unsigned int register_number) +{ + u8 retval; + unsigned long flags; + + spin_lock_irqsave(&nec_priv->register_page_lock, flags); + retval = fluke_read_byte_nolock(nec_priv, register_number); + spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); + return retval; +} + +static void fluke_locking_write_byte(struct nec7210_priv *nec_priv, uint8_t byte, + unsigned int register_number) +{ + unsigned long flags; + + spin_lock_irqsave(&nec_priv->register_page_lock, flags); + fluke_write_byte_nolock(nec_priv, byte, register_number); + spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); +} + +// wrappers for interface functions +static int fluke_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); +} + +static int fluke_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +static int fluke_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +static int fluke_take_control(gpib_board_t *board, int synchronous) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +static int fluke_go_to_standby(gpib_board_t *board) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +static void fluke_request_system_control(gpib_board_t *board, int request_control) +{ + struct fluke_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + nec7210_request_system_control(board, nec_priv, request_control); +} + +static void fluke_interface_clear(gpib_board_t *board, int assert) +{ + struct fluke_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +static void fluke_remote_enable(gpib_board_t *board, int enable) +{ + struct fluke_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +static int fluke_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +static void fluke_disable_eos(gpib_board_t *board) +{ + struct fluke_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +static unsigned int fluke_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); +} + +static int fluke_primary_address(gpib_board_t *board, unsigned int address) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +static int fluke_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +static int fluke_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_parallel_poll(board, &priv->nec7210_priv, result); +} + +static void fluke_parallel_poll_configure(gpib_board_t *board, uint8_t configuration) +{ + struct fluke_priv *priv = board->private_data; + + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); +} + +static void fluke_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct fluke_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +static void fluke_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct fluke_priv *priv = board->private_data; + + nec7210_serial_poll_response(board, &priv->nec7210_priv, status); +} + +static uint8_t fluke_serial_poll_status(gpib_board_t *board) +{ + struct fluke_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +static void fluke_return_to_local(gpib_board_t *board) +{ + struct fluke_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + write_byte(nec_priv, AUX_RTL2, AUXMR); + udelay(1); + write_byte(nec_priv, AUX_RTL, AUXMR); +} + +static int fluke_line_status(const gpib_board_t *board) +{ + int status = ValidALL; + int bsr_bits; + struct fluke_priv *e_priv; + struct nec7210_priv *nec_priv; + + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + + bsr_bits = fluke_paged_read_byte(e_priv, BUS_STATUS, BUS_STATUS_PAGE); + + if ((bsr_bits & BSR_REN_BIT) == 0) + status |= BusREN; + if ((bsr_bits & BSR_IFC_BIT) == 0) + status |= BusIFC; + if ((bsr_bits & BSR_SRQ_BIT) == 0) + status |= BusSRQ; + if ((bsr_bits & BSR_EOI_BIT) == 0) + status |= BusEOI; + if ((bsr_bits & BSR_NRFD_BIT) == 0) + status |= BusNRFD; + if ((bsr_bits & BSR_NDAC_BIT) == 0) + status |= BusNDAC; + if ((bsr_bits & BSR_DAV_BIT) == 0) + status |= BusDAV; + if ((bsr_bits & BSR_ATN_BIT) == 0) + status |= BusATN; + + return status; +} + +static unsigned int fluke_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned int retval; + + retval = nec7210_t1_delay(board, nec_priv, nano_sec); + + if (nano_sec <= 350) { + write_byte(nec_priv, AUX_HI_SPEED, AUXMR); + retval = 350; + } else { + write_byte(nec_priv, AUX_LO_SPEED, AUXMR); + } + return retval; +} + +static int lacs_or_read_ready(gpib_board_t *board) +{ + const struct fluke_priv *e_priv = board->private_data; + const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + int retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = test_bit(LACS_NUM, &board->status) || test_bit(READ_READY_BN, &nec_priv->state); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +/* Wait until it is possible for a read to do something useful. This + * is not essential, it only exists to prevent RFD holdoff from being released pointlessly. + */ +static int wait_for_read(gpib_board_t *board) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + + if (wait_event_interruptible(board->wait, + lacs_or_read_ready(board) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + return retval; +} + +/* Check if the SH state machine is in SGNS. We check twice since there is a very small chance + * we could be blowing through SGNS from SIDS to SDYS if there is already a + * byte available in the handshake state machine. We are interested + * in the case where the handshake is stuck in SGNS due to no byte being + * available to the chip (and thus we can be confident a dma transfer will + * result in at least one byte making it into the chip). This matters + * because we want to be confident before sending a "send eoi" auxilary + * command that we will be able to also put the associated data byte + * in the chip before any potential timeout. + */ +static int source_handshake_is_sgns(struct fluke_priv *e_priv) +{ + int i; + + for (i = 0; i < 2; ++i) { + if ((fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) & + SOURCE_HANDSHAKE_MASK) != SOURCE_HANDSHAKE_SGNS_BITS) { + return 0; + } + } + return 1; +} + +static int source_handshake_is_sids_or_sgns(struct fluke_priv *e_priv) +{ + unsigned int source_handshake_bits; + + source_handshake_bits = fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) & + SOURCE_HANDSHAKE_MASK; + + return (source_handshake_bits == SOURCE_HANDSHAKE_SGNS_BITS) || + (source_handshake_bits == SOURCE_HANDSHAKE_SIDS_BITS); +} + +/* Wait until the gpib chip is ready to accept a data out byte. + * If the chip is SGNS it is probably waiting for a a byte to + * be written to it. + */ +static int wait_for_data_out_ready(gpib_board_t *board) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; +// printk("%s: enter\n", __FUNCTION__); + + if (wait_event_interruptible(board->wait, + (test_bit(TACS_NUM, &board->status) && + source_handshake_is_sgns(e_priv)) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; +// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); + return retval; +} + +static int wait_for_sids_or_sgns(gpib_board_t *board) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; +// printk("%s: enter\n", __FUNCTION__); + + if (wait_event_interruptible(board->wait, + source_handshake_is_sids_or_sgns(e_priv) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) + retval = -ERESTARTSYS; + + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; +// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); + return retval; +} + +static void fluke_dma_callback(void *arg) +{ + gpib_board_t *board = arg; + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); +// printk("%s: enter\n", __FUNCTION__); + + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE); + wake_up_interruptible(&board->wait); + + fluke_gpib_internal_interrupt(board); + clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); + clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); +// printk("%s: exit\n", __FUNCTION__); + spin_unlock_irqrestore(&board->spinlock, flags); +} + +static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + int retval = 0; + dma_addr_t address; + struct dma_async_tx_descriptor *tx_desc; + + *bytes_written = 0; +// printk("%s: enter\n", __FUNCTION__); + if (WARN_ON_ONCE(length > e_priv->dma_buffer_size)) + return -EFAULT; + dmaengine_terminate_all(e_priv->dma_channel); + // write-clear counter + writel(0x0, e_priv->write_transfer_counter); + + memcpy(e_priv->dma_buffer, buffer, length); + address = dma_map_single(board->dev, e_priv->dma_buffer, + length, DMA_TO_DEVICE); + /* program dma controller */ + retval = fluke_config_dma(board, 1); + if (retval) + goto cleanup; + + tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx_desc) { + pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n"); + retval = -ENOMEM; + goto cleanup; + } + tx_desc->callback = fluke_dma_callback; + tx_desc->callback_param = board; + + spin_lock_irqsave(&board->spinlock, flags); + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); + dmaengine_submit(tx_desc); + dma_async_issue_pending(e_priv->dma_channel); + + clear_bit(WRITE_READY_BN, &nec_priv->state); + set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); + + // printk("%s: in spin lock\n", __FUNCTION__); + spin_unlock_irqrestore(&board->spinlock, flags); + +// printk("%s: waiting for write.\n", __FUNCTION__); + // suspend until message is sent + if (wait_event_interruptible(board->wait, + ((readl(e_priv->write_transfer_counter) & + write_transfer_counter_mask) == length) || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) + retval = -EIO; + // disable board's dma + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); + + dmaengine_terminate_all(e_priv->dma_channel); + // make sure fluke_dma_callback got called + if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state)) + fluke_dma_callback(board); + + /* if everything went fine, try to wait until last byte is actually + * transmitted across gpib (but don't try _too_ hard) + */ + if (retval == 0) + retval = wait_for_sids_or_sgns(board); + + *bytes_written = readl(e_priv->write_transfer_counter) & write_transfer_counter_mask; + if (WARN_ON_ONCE(*bytes_written > length)) + return -EFAULT; + +cleanup: + dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE); +// printk("%s: exit, retval=%d\n", __FUNCTION__, retval); + return retval; +} + +static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + size_t remainder = length; + size_t transfer_size; + ssize_t retval = 0; + size_t dma_remainder = remainder; + + if (!e_priv->dma_channel) { + pr_err("fluke_gpib: No dma channel available, cannot do accel write."); + return -ENXIO; + } + + *bytes_written = 0; + if (length < 1) + return 0; + + clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME + + if (send_eoi) + --dma_remainder; +// printk("%s: entering while loop\n", __FUNCTION__); + + while (dma_remainder > 0) { + size_t num_bytes; + + retval = wait_for_data_out_ready(board); + if (retval < 0) + break; + + transfer_size = (e_priv->dma_buffer_size < dma_remainder) ? + e_priv->dma_buffer_size : dma_remainder; + retval = fluke_dma_write(board, buffer, transfer_size, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + break; + dma_remainder -= num_bytes; + remainder -= num_bytes; + buffer += num_bytes; + if (need_resched()) + schedule(); + } + if (retval < 0) + return retval; + //handle sending of last byte with eoi + if (send_eoi) { + size_t num_bytes; + // printk("%s: handling last byte\n", __FUNCTION__); + if (WARN_ON_ONCE(remainder != 1)) + return -EFAULT; + + /* wait until we are sure we will be able to write the data byte + * into the chip before we send AUX_SEOI. This prevents a timeout + * scenerio where we send AUX_SEOI but then timeout without getting + * any bytes into the gpib chip. This will result in the first byte + * of the next write having a spurious EOI set on the first byte. + */ + retval = wait_for_data_out_ready(board); + if (retval < 0) + return retval; + + write_byte(nec_priv, AUX_SEOI, AUXMR); + retval = fluke_dma_write(board, buffer, remainder, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + remainder -= num_bytes; + } +// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder)); + return 0; +} + +static int fluke_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) +{ + struct dma_tx_state state; + int result; + + result = dmaengine_pause(chan); + if (result < 0) { + pr_err("fluke_gpib: dma pause failed?\n"); + return result; + } + dmaengine_tx_status(chan, cookie, &state); + // hardware doesn't support resume, so dont call this + // method unless the dma transfer is done. + return state.residue; +} + +static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + unsigned long flags; + int residue; + dma_addr_t bus_address; + struct dma_async_tx_descriptor *tx_desc; + dma_cookie_t dma_cookie; + int i; + static const int timeout = 10; + + // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__, + // (unsigned)bus_address, + // (int)length); + + *bytes_read = 0; + *end = 0; + if (length == 0) + return 0; + + bus_address = dma_map_single(board->dev, e_priv->dma_buffer, + length, DMA_FROM_DEVICE); + + /* program dma controller */ + retval = fluke_config_dma(board, 0); + if (retval) { + dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); + return retval; + } + tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, + bus_address, length, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx_desc) { + pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n"); + dma_unmap_single(NULL, bus_address, length, DMA_FROM_DEVICE); + return -EIO; + } + tx_desc->callback = fluke_dma_callback; + tx_desc->callback_param = board; + + spin_lock_irqsave(&board->spinlock, flags); + // enable nec7210 dma + nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); + + dma_cookie = dmaengine_submit(tx_desc); + dma_async_issue_pending(e_priv->dma_channel); + + set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); + clear_bit(READ_READY_BN, &nec_priv->state); + + spin_unlock_irqrestore(&board->spinlock, flags); +// printk("waiting for data transfer.\n"); + // wait for data to transfer + if (wait_event_interruptible(board->wait, + test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0 || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_warn("fluke: dma read wait interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + + /* If we woke up because of end, wait until the dma transfer has pulled + * the data byte associated with the end before we cancel the dma transfer. + */ + if (test_bit(RECEIVED_END_BN, &nec_priv->state)) { + for (i = 0; i < timeout; ++i) { + if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0) + break; + if ((read_byte(nec_priv, ADR0) & DATA_IN_STATUS) == 0) + break; + usleep_range(10, 15); + } + if (i == timeout) + pr_warn("fluke_gpib: timeout waiting for dma to transfer end data byte.\n"); + } + + // stop the dma transfer + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + /* delay a little just to make sure any bytes in dma controller's fifo get + * written to memory before we disable it + */ + usleep_range(10, 15); + residue = fluke_get_dma_residue(e_priv->dma_channel, dma_cookie); + if (WARN_ON_ONCE(residue > length || residue < 0)) + return -EFAULT; + *bytes_read += length - residue; + dmaengine_terminate_all(e_priv->dma_channel); + // make sure fluke_dma_callback got called + if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state)) + fluke_dma_callback(board); + + dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); + memcpy(buffer, e_priv->dma_buffer, *bytes_read); + + /* If we got an end interrupt, figure out if it was + * associated with the last byte we dma'd or with a + * byte still sitting on the cb7210. + */ + spin_lock_irqsave(&board->spinlock, flags); + if (test_bit(READ_READY_BN, &nec_priv->state) == 0) { + // There is no byte sitting on the cb7210. If we + // saw an end interrupt, we need to deal with it now + if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) + *end = 1; + } + spin_unlock_irqrestore(&board->spinlock, flags); + + return retval; +} + +static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + size_t remain = length; + size_t transfer_size; + int retval = 0; + size_t dma_nbytes; + +/* printk("%s: enter, buffer=0x%p, length=%i\n", __FUNCTION__, + * buffer, (int)length); + * printk("\t dma_buffer=0x%p\n", e_priv->dma_buffer); + */ + *end = 0; + *bytes_read = 0; + + smp_mb__before_atomic(); + clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME + smp_mb__after_atomic(); + + retval = wait_for_read(board); + if (retval < 0) + return retval; + + nec7210_release_rfd_holdoff(board, nec_priv); + +// printk("%s: entering while loop\n", __FUNCTION__); + while (remain > 0) { + transfer_size = (e_priv->dma_buffer_size < remain) ? + e_priv->dma_buffer_size : remain; + retval = fluke_dma_read(board, buffer, transfer_size, end, &dma_nbytes); + remain -= dma_nbytes; + buffer += dma_nbytes; + *bytes_read += dma_nbytes; + if (*end) + break; + if (retval < 0) { +// printk("%s: early exit, retval=%i\n", __FUNCTION__, (int)retval); + return retval; + } + if (need_resched()) + schedule(); + } +// printk("%s: exit, retval=%i\n", __FUNCTION__, (int)retval); + return retval; +} + +gpib_interface_t fluke_unaccel_interface = { +name: "fluke_unaccel", +attach : fluke_attach_holdoff_all, +detach : fluke_detach, +read : fluke_read, +write : fluke_write, +command : fluke_command, +take_control : fluke_take_control, +go_to_standby : fluke_go_to_standby, +request_system_control : fluke_request_system_control, +interface_clear : fluke_interface_clear, +remote_enable : fluke_remote_enable, +enable_eos : fluke_enable_eos, +disable_eos : fluke_disable_eos, +parallel_poll : fluke_parallel_poll, +parallel_poll_configure : fluke_parallel_poll_configure, +parallel_poll_response : fluke_parallel_poll_response, +line_status : fluke_line_status, +update_status : fluke_update_status, +primary_address : fluke_primary_address, +secondary_address : fluke_secondary_address, +serial_poll_response : fluke_serial_poll_response, +serial_poll_status : fluke_serial_poll_status, +t1_delay : fluke_t1_delay, +return_to_local : fluke_return_to_local, +}; + +/* fluke_hybrid uses dma for writes but not for reads. Added + * to deal with occasional corruption of bytes seen when doing dma + * reads. From looking at the cb7210 vhdl, I believe the corruption + * is due to a hardware bug triggered by the cpu reading a cb7210 + * } + * register just as the dma controller is also doing a read. + */ + +gpib_interface_t fluke_hybrid_interface = { +name: "fluke_hybrid", +attach : fluke_attach_holdoff_all, +detach : fluke_detach, +read : fluke_read, +write : fluke_accel_write, +command : fluke_command, +take_control : fluke_take_control, +go_to_standby : fluke_go_to_standby, +request_system_control : fluke_request_system_control, +interface_clear : fluke_interface_clear, +remote_enable : fluke_remote_enable, +enable_eos : fluke_enable_eos, +disable_eos : fluke_disable_eos, +parallel_poll : fluke_parallel_poll, +parallel_poll_configure : fluke_parallel_poll_configure, +parallel_poll_response : fluke_parallel_poll_response, +line_status : fluke_line_status, +update_status : fluke_update_status, +primary_address : fluke_primary_address, +secondary_address : fluke_secondary_address, +serial_poll_response : fluke_serial_poll_response, +serial_poll_status : fluke_serial_poll_status, +t1_delay : fluke_t1_delay, +return_to_local : fluke_return_to_local, +}; + +gpib_interface_t fluke_interface = { +name: "fluke", +attach : fluke_attach_holdoff_end, +detach : fluke_detach, +read : fluke_accel_read, +write : fluke_accel_write, +command : fluke_command, +take_control : fluke_take_control, +go_to_standby : fluke_go_to_standby, +request_system_control : fluke_request_system_control, +interface_clear : fluke_interface_clear, +remote_enable : fluke_remote_enable, +enable_eos : fluke_enable_eos, +disable_eos : fluke_disable_eos, +parallel_poll : fluke_parallel_poll, +parallel_poll_configure : fluke_parallel_poll_configure, +parallel_poll_response : fluke_parallel_poll_response, +line_status : fluke_line_status, +update_status : fluke_update_status, +primary_address : fluke_primary_address, +secondary_address : fluke_secondary_address, +serial_poll_response : fluke_serial_poll_response, +serial_poll_status : fluke_serial_poll_status, +t1_delay : fluke_t1_delay, +return_to_local : fluke_return_to_local, +}; + +irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board) +{ + int status0, status1, status2; + struct fluke_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + int retval = IRQ_NONE; + + if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) + set_bit(READ_READY_BN, &nec_priv->state); + + status0 = fluke_paged_read_byte(priv, ISR0_IMR0, ISR0_IMR0_PAGE); + status1 = read_byte(nec_priv, ISR1); + status2 = read_byte(nec_priv, ISR2); + + if (status0 & FLUKE_IFCI_BIT) { + push_gpib_event(board, EventIFC); + retval = IRQ_HANDLED; + } + + if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED) + retval = IRQ_HANDLED; +/* + * if((status1 & nec_priv->reg_bits[IMR1]) || + * (status2 & (nec_priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK))) + * { + * printk("fluke: status1 0x%x, status2 0x%x\n", status1, status2); + * } + */ + + if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) { + if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state)) + set_bit(READ_READY_BN, &nec_priv->state); + else + clear_bit(READ_READY_BN, &nec_priv->state); + } + + if (retval == IRQ_HANDLED) + wake_up_interruptible(&board->wait); + + return retval; +} + +static irqreturn_t fluke_gpib_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = fluke_gpib_internal_interrupt(board); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +static int fluke_allocate_private(gpib_board_t *board) +{ + struct fluke_priv *priv; + + board->private_data = kmalloc(sizeof(struct fluke_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + priv = board->private_data; + memset(priv, 0, sizeof(struct fluke_priv)); + init_nec7210_private(&priv->nec7210_priv); + priv->dma_buffer_size = 0x7ff; + priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL); + if (!priv->dma_buffer) + return -ENOMEM; + return 0; +} + +static void fluke_generic_detach(gpib_board_t *board) +{ + if (board->private_data) { + struct fluke_priv *e_priv = board->private_data; + + kfree(e_priv->dma_buffer); + kfree(board->private_data); + board->private_data = NULL; + } +} + +// generic part of attach functions shared by all cb7210 boards +static int fluke_generic_attach(gpib_board_t *board) +{ + struct fluke_priv *e_priv; + struct nec7210_priv *nec_priv; + int retval; + + board->status = 0; + + retval = fluke_allocate_private(board); + if (retval < 0) + return retval; + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + nec_priv->read_byte = fluke_locking_read_byte; + nec_priv->write_byte = fluke_locking_write_byte; + nec_priv->offset = fluke_reg_offset; + nec_priv->type = CB7210; + return 0; +} + +static int fluke_config_dma(gpib_board_t *board, int output) +{ + struct fluke_priv *e_priv = board->private_data; + struct dma_slave_config config; + + config.src_maxburst = 1; + config.dst_maxburst = 1; + config.device_fc = true; + + if (output) { + config.direction = DMA_MEM_TO_DEV; + config.src_addr = 0; + config.dst_addr = e_priv->dma_port_res->start; + config.src_addr_width = 1; + config.dst_addr_width = 1; + } else { + config.direction = DMA_DEV_TO_MEM; + config.src_addr = e_priv->dma_port_res->start; + config.dst_addr = 0; + config.src_addr_width = 1; + config.dst_addr_width = 1; + } + return dmaengine_slave_config(e_priv->dma_channel, &config); +} + +static int fluke_init(struct fluke_priv *e_priv, gpib_board_t *board, int handshake_mode) +{ + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + + nec7210_board_reset(nec_priv, board); + write_byte(nec_priv, AUX_LO_SPEED, AUXMR); + /* set clock register for driving frequency + * ICR should be set to clock in megahertz (1-15) and to zero + * for clocks faster than 15 MHz (max 20MHz) + */ + write_byte(nec_priv, ICR | 10, AUXMR); + nec7210_set_handshake_mode(board, nec_priv, handshake_mode); + + nec7210_board_online(nec_priv, board); + + /* poll so we can detect ATN changes */ + if (gpib_request_pseudo_irq(board, fluke_gpib_interrupt)) { + pr_err("fluke_gpib: failed to allocate pseudo_irq\n"); + return -EINVAL; + } + + fluke_paged_write_byte(e_priv, FLUKE_IFCIE_BIT, ISR0_IMR0, ISR0_IMR0_PAGE); + return 0; +} + +/* This function is passed to dma_request_channel() in order to + * select the pl330 dma channel which has been hardwired to + * the gpib controller. + */ +static bool gpib_dma_channel_filter(struct dma_chan *chan, void *filter_param) +{ + // select the channel which is wired to the gpib chip + return chan->chan_id == 0; +} + +static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *config, + unsigned int handshake_mode) +{ + struct fluke_priv *e_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + int retval; + int irq; + struct resource *res; + dma_cap_mask_t dma_cap; + + if (!fluke_gpib_pdev) { + pr_err("No gpib platform device was found, attach failed.\n"); + return -ENODEV; + } + + retval = fluke_generic_attach(board); + if (retval) + return retval; + + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + nec_priv->offset = fluke_reg_offset; + board->dev = &fluke_gpib_pdev->dev; + + res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for cb7210 gpib\n"); + return -ENODEV; + } + + if (request_mem_region(res->start, + resource_size(res), + fluke_gpib_pdev->name) == NULL) { + dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n"); + return -ENXIO; + } + e_priv->gpib_iomem_res = res; + + nec_priv->iobase = ioremap(e_priv->gpib_iomem_res->start, + resource_size(e_priv->gpib_iomem_res)); + pr_info("gpib: iobase %lx remapped to %p, length=%d\n", + (unsigned long)e_priv->gpib_iomem_res->start, + nec_priv->iobase, (int)resource_size(e_priv->gpib_iomem_res)); + if (!nec_priv->iobase) { + dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n"); + return -ENOMEM; + } + + res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for gpib dma port\n"); + return -ENODEV; + } + if (request_mem_region(res->start, + resource_size(res), + fluke_gpib_pdev->name) == NULL) { + dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n"); + return -ENXIO; + } + e_priv->dma_port_res = res; + + res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 2); + if (!res) { + dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for write transfer counter\n"); + return -ENODEV; + } + + if (request_mem_region(res->start, + resource_size(res), + fluke_gpib_pdev->name) == NULL) { + dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n"); + return -ENXIO; + } + e_priv->write_transfer_counter_res = res; + + e_priv->write_transfer_counter = ioremap(e_priv->write_transfer_counter_res->start, + resource_size(e_priv->write_transfer_counter_res)); + pr_info("gpib: write transfer counter %lx remapped to %p, length=%d\n", + (unsigned long)e_priv->write_transfer_counter_res->start, + e_priv->write_transfer_counter, + (int)resource_size(e_priv->write_transfer_counter_res)); + if (!e_priv->write_transfer_counter) { + dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n"); + return -ENOMEM; + } + + irq = platform_get_irq(fluke_gpib_pdev, 0); + pr_info("gpib: irq %d\n", irq); + if (irq < 0) { + dev_err(&fluke_gpib_pdev->dev, "fluke_gpib: request for IRQ failed\n"); + return -EBUSY; + } + retval = request_irq(irq, fluke_gpib_interrupt, isr_flags, fluke_gpib_pdev->name, board); + if (retval) { + dev_err(&fluke_gpib_pdev->dev, + "cannot register interrupt handler err=%d\n", + retval); + return retval; + } + e_priv->irq = irq; + + dma_cap_zero(dma_cap); + dma_cap_set(DMA_SLAVE, dma_cap); + e_priv->dma_channel = dma_request_channel(dma_cap, gpib_dma_channel_filter, NULL); + if (!e_priv->dma_channel) { + pr_err("fluke_gpib: failed to allocate a dma channel.\n"); + // we don't error out here because unaccel interface will still + // work without dma + } + + return fluke_init(e_priv, board, handshake_mode); +} + +int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config) +{ + return fluke_attach_impl(board, config, HR_HLDA); +} + +int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config) +{ + return fluke_attach_impl(board, config, HR_HLDE); +} + +void fluke_detach(gpib_board_t *board) +{ + struct fluke_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (e_priv) { + if (e_priv->dma_channel) + dma_release_channel(e_priv->dma_channel); + gpib_free_pseudo_irq(board); + nec_priv = &e_priv->nec7210_priv; + + if (nec_priv->iobase) { + fluke_paged_write_byte(e_priv, 0, ISR0_IMR0, ISR0_IMR0_PAGE); + nec7210_board_reset(nec_priv, board); + } + if (e_priv->irq) + free_irq(e_priv->irq, board); + if (e_priv->write_transfer_counter_res) { + release_mem_region(e_priv->write_transfer_counter_res->start, + resource_size(e_priv->write_transfer_counter_res)); + } + if (e_priv->dma_port_res) { + release_mem_region(e_priv->dma_port_res->start, + resource_size(e_priv->dma_port_res)); + } + if (e_priv->gpib_iomem_res) + release_mem_region(e_priv->gpib_iomem_res->start, + resource_size(e_priv->gpib_iomem_res)); + } + fluke_generic_detach(board); +} + +static int fluke_gpib_probe(struct platform_device *pdev) +{ + fluke_gpib_pdev = pdev; + return 0; +} + +static const struct of_device_id fluke_gpib_of_match[] = { + { .compatible = "flk,fgpib-4.0"}, + { {0} } +}; +MODULE_DEVICE_TABLE(of, fluke_gpib_of_match); + +static struct platform_driver fluke_gpib_platform_driver = { + .driver = { + .name = "fluke_gpib", + .owner = THIS_MODULE, + .of_match_table = fluke_gpib_of_match, + }, + .probe = &fluke_gpib_probe +}; + +static int __init fluke_init_module(void) +{ + int result; + + result = platform_driver_register(&fluke_gpib_platform_driver); + if (result) { + pr_err("fluke_gpib: platform_driver_register failed!\n"); + return result; + } + + gpib_register_driver(&fluke_unaccel_interface, THIS_MODULE); + gpib_register_driver(&fluke_hybrid_interface, THIS_MODULE); + gpib_register_driver(&fluke_interface, THIS_MODULE); + + pr_info("fluke_gpib\n"); + return 0; +} + +static void __exit fluke_exit_module(void) +{ + gpib_unregister_driver(&fluke_unaccel_interface); + gpib_unregister_driver(&fluke_hybrid_interface); + gpib_unregister_driver(&fluke_interface); + platform_driver_unregister(&fluke_gpib_platform_driver); +} + +module_init(fluke_init_module); +module_exit(fluke_exit_module); diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.h b/drivers/staging/gpib/eastwood/fluke_gpib.h new file mode 100644 index 0000000000000000000000000000000000000000..fcbd42f8f9af6144d57ff342c9adb51da6134bc6 --- /dev/null +++ b/drivers/staging/gpib/eastwood/fluke_gpib.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Author: Frank Mori Hess <fmh6jj@gmail.com> + * copyright: (C) 2006, 2010, 2015 Fluke Corporation + ***************************************************************************/ + +#include <linux/compiler.h> +#include <linux/dmaengine.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include "nec7210.h" + +struct fluke_priv { + struct nec7210_priv nec7210_priv; + struct resource *gpib_iomem_res; + struct resource *write_transfer_counter_res; + struct resource *dma_port_res; + int irq; + struct dma_chan *dma_channel; + u8 *dma_buffer; + int dma_buffer_size; + void *write_transfer_counter; +}; + +// cb7210 specific registers and bits +enum cb7210_regs { + STATE1_REG = 0x4, + ISR0_IMR0 = 0x6, + BUS_STATUS = 0x7 +}; + +enum cb7210_page_in { + ISR0_IMR0_PAGE = 1, + BUS_STATUS_PAGE = 1, + STATE1_PAGE = 1 +}; + +/* IMR0 -- Interrupt Mode Register 0 */ +enum imr0_bits { + FLUKE_IFCIE_BIT = 0x8, /* interface clear interrupt */ +}; + +/* ISR0 -- Interrupt Status Register 0 */ +enum isr0_bits { + FLUKE_IFCI_BIT = 0x8, /* interface clear interrupt */ +}; + +enum state1_bits { + SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */ + SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */ + SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */ + SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */ + SOURCE_HANDSHAKE_MASK = 0x7 +}; + +// we customized the cb7210 vhdl to give the "data in" status +// on the unused bit 7 of the address0 register. +enum cb7210_address0 { + DATA_IN_STATUS = 0x80 +}; + +static inline int cb7210_page_in_bits(unsigned int page) +{ + return 0x50 | (page & 0xf); +} + +// don't use without locking nec_priv->register_page_lock +static inline uint8_t fluke_read_byte_nolock(struct nec7210_priv *nec_priv, + int register_num) +{ + u8 retval; + + retval = readl(nec_priv->iobase + register_num * nec_priv->offset); + return retval; +} + +// don't use without locking nec_priv->register_page_lock +static inline void fluke_write_byte_nolock(struct nec7210_priv *nec_priv, uint8_t data, + int register_num) +{ + writel(data, nec_priv->iobase + register_num * nec_priv->offset); +} + +static inline uint8_t fluke_paged_read_byte(struct fluke_priv *e_priv, + unsigned int register_num, unsigned int page) +{ + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + u8 retval; + unsigned long flags; + + spin_lock_irqsave(&nec_priv->register_page_lock, flags); + fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR); + udelay(1); + /* chip auto clears the page after a read */ + retval = fluke_read_byte_nolock(nec_priv, register_num); + spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); + return retval; +} + +static inline void fluke_paged_write_byte(struct fluke_priv *e_priv, uint8_t data, + unsigned int register_num, unsigned int page) +{ + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + + spin_lock_irqsave(&nec_priv->register_page_lock, flags); + fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR); + udelay(1); + fluke_write_byte_nolock(nec_priv, data, register_num); + spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); +} + +enum bus_status_bits { + BSR_ATN_BIT = 0x1, + BSR_EOI_BIT = 0x2, + BSR_SRQ_BIT = 0x4, + BSR_IFC_BIT = 0x8, + BSR_REN_BIT = 0x10, + BSR_DAV_BIT = 0x20, + BSR_NRFD_BIT = 0x40, + BSR_NDAC_BIT = 0x80, +}; + +enum cb7210_aux_cmds { +/* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert + * (and keep asserted) local rtl message. This is used in conjunction + * with the (stupid) cb7210 implementation + * of the normal nec7210 AUX_RTL aux command, which + * causes the rtl message to toggle between on and off. + */ + AUX_RTL2 = 0xd, + AUX_NBAF = 0xe, // new byte available false (also clears seoi) + AUX_LO_SPEED = 0x40, + AUX_HI_SPEED = 0x41, +}; + +enum { + fluke_reg_offset = 4, + fluke_num_regs = 8, + write_transfer_counter_mask = 0x7ff, +}; diff --git a/drivers/staging/gpib/fmh_gpib/Makefile b/drivers/staging/gpib/fmh_gpib/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cc4d9e7cd5cdc674a82ad645bf7fde75e7fbc88d --- /dev/null +++ b/drivers/staging/gpib/fmh_gpib/Makefile @@ -0,0 +1,2 @@ + +obj-$(CONFIG_GPIB_FMH) += fmh_gpib.o diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..62791db1c34a4fc25978c1bea85fb079a8053e4e --- /dev/null +++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c @@ -0,0 +1,1725 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * GPIB Driver for fmh_gpib_core, see + * https://github.com/fmhess/fmh_gpib_core + * + * More specifically, it is a driver for the hardware arrangement described by + * src/examples/fmh_gpib_top.vhd in the fmh_gpib_core repository. + * + * Author: Frank Mori Hess <fmh6jj@gmail.com> + * Copyright: (C) 2006, 2010, 2015 Fluke Corporation + * (C) 2017 Frank Mori Hess + ***************************************************************************/ + +#include "fmh_gpib.h" + +#include "gpibP.h" +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +MODULE_LICENSE("GPL"); + +static irqreturn_t fmh_gpib_interrupt(int irq, void *arg); +static int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config); +static int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config); +static void fmh_gpib_detach(gpib_board_t *board); +static int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config); +static int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config); +static void fmh_gpib_pci_detach(gpib_board_t *board); +static int fmh_gpib_config_dma(gpib_board_t *board, int output); +static irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board); +static struct platform_driver fmh_gpib_platform_driver; +static struct pci_driver fmh_gpib_pci_driver; + +// wrappers for interface functions +static int fmh_gpib_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); +} + +static int fmh_gpib_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +static int fmh_gpib_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +static int fmh_gpib_take_control(gpib_board_t *board, int synchronous) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +static int fmh_gpib_go_to_standby(gpib_board_t *board) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +static void fmh_gpib_request_system_control(gpib_board_t *board, int request_control) +{ + struct fmh_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + nec7210_request_system_control(board, nec_priv, request_control); +} + +static void fmh_gpib_interface_clear(gpib_board_t *board, int assert) +{ + struct fmh_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +static void fmh_gpib_remote_enable(gpib_board_t *board, int enable) +{ + struct fmh_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +static int fmh_gpib_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +static void fmh_gpib_disable_eos(gpib_board_t *board) +{ + struct fmh_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +static unsigned int fmh_gpib_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); +} + +static int fmh_gpib_primary_address(gpib_board_t *board, unsigned int address) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +static int fmh_gpib_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +static int fmh_gpib_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_parallel_poll(board, &priv->nec7210_priv, result); +} + +static void fmh_gpib_parallel_poll_configure(gpib_board_t *board, uint8_t configuration) +{ + struct fmh_priv *priv = board->private_data; + + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); +} + +static void fmh_gpib_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct fmh_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +static void fmh_gpib_local_parallel_poll_mode(gpib_board_t *board, int local) +{ + struct fmh_priv *priv = board->private_data; + + if (local) { + write_byte(&priv->nec7210_priv, AUX_I_REG | LOCAL_PPOLL_MODE_BIT, AUXMR); + } else { + /* For fmh_gpib_core, remote parallel poll config mode is unaffected by the + * state of the disable bit of the parallel poll register (unlike the tnt4882). + * So, we don't need to worry about that. + */ + write_byte(&priv->nec7210_priv, AUX_I_REG | 0x0, AUXMR); + } +} + +static void fmh_gpib_serial_poll_response2(gpib_board_t *board, uint8_t status, + int new_reason_for_service) +{ + struct fmh_priv *priv = board->private_data; + unsigned long flags; + const int MSS = status & request_service_bit; + const int reqt = MSS && new_reason_for_service; + const int reqf = MSS == 0; + + spin_lock_irqsave(&board->spinlock, flags); + if (reqt) { + priv->nec7210_priv.srq_pending = 1; + clear_bit(SPOLL_NUM, &board->status); + } else if (reqf) { + priv->nec7210_priv.srq_pending = 0; + } + + if (reqt) { + /* It may seem like a race to issue reqt before updating + * the status byte, but it is not. The chip does not + * issue the reqt until the SPMR is written to at + * a later time. + */ + write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR); + } else if (reqf) { + write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR); + } + /* We need to always zero bit 6 of the status byte before writing it to + * the SPMR to insure we are using + * serial poll mode SP1, and not accidentally triggering mode SP3. + */ + write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR); + spin_unlock_irqrestore(&board->spinlock, flags); +} + +static uint8_t fmh_gpib_serial_poll_status(gpib_board_t *board) +{ + struct fmh_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +static void fmh_gpib_return_to_local(gpib_board_t *board) +{ + struct fmh_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + write_byte(nec_priv, AUX_RTL2, AUXMR); + udelay(1); + write_byte(nec_priv, AUX_RTL, AUXMR); +} + +static int fmh_gpib_line_status(const gpib_board_t *board) +{ + int status = ValidALL; + int bsr_bits; + struct fmh_priv *e_priv; + struct nec7210_priv *nec_priv; + + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + + bsr_bits = read_byte(nec_priv, BUS_STATUS_REG); + + if ((bsr_bits & BSR_REN_BIT) == 0) + status |= BusREN; + if ((bsr_bits & BSR_IFC_BIT) == 0) + status |= BusIFC; + if ((bsr_bits & BSR_SRQ_BIT) == 0) + status |= BusSRQ; + if ((bsr_bits & BSR_EOI_BIT) == 0) + status |= BusEOI; + if ((bsr_bits & BSR_NRFD_BIT) == 0) + status |= BusNRFD; + if ((bsr_bits & BSR_NDAC_BIT) == 0) + status |= BusNDAC; + if ((bsr_bits & BSR_DAV_BIT) == 0) + status |= BusDAV; + if ((bsr_bits & BSR_ATN_BIT) == 0) + status |= BusATN; + + return status; +} + +static unsigned int fmh_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned int retval; + + retval = nec7210_t1_delay(board, nec_priv, nano_sec); + + if (nano_sec <= 350) { + write_byte(nec_priv, AUX_HI_SPEED, AUXMR); + retval = 350; + } else { + write_byte(nec_priv, AUX_LO_SPEED, AUXMR); + } + return retval; +} + +static int lacs_or_read_ready(gpib_board_t *board) +{ + const struct fmh_priv *e_priv = board->private_data; + const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + retval = test_bit(LACS_NUM, &board->status) || + test_bit(READ_READY_BN, &nec_priv->state); + spin_unlock_irqrestore(&board->spinlock, flags); + + return retval; +} + +static int wait_for_read(gpib_board_t *board) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + + if (wait_event_interruptible(board->wait, + lacs_or_read_ready(board) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) + retval = -ERESTARTSYS; + + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + return retval; +} + +static int wait_for_rx_fifo_half_full_or_end(gpib_board_t *board) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + + if (wait_event_interruptible(board->wait, + (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & + RX_FIFO_HALF_FULL) || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) + retval = -ERESTARTSYS; + + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + return retval; +} + +/* Wait until the gpib chip is ready to accept a data out byte. + */ +static int wait_for_data_out_ready(gpib_board_t *board) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; +// printk("%s: enter\n", __FUNCTION__); + + if (wait_event_interruptible(board->wait, + (test_bit(TACS_NUM, &board->status) && + (read_byte(nec_priv, EXT_STATUS_1_REG) & + DATA_OUT_STATUS_BIT)) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) + retval = -ERESTARTSYS; + + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; +// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); + return retval; +} + +static void fmh_gpib_dma_callback(void *arg) +{ + gpib_board_t *board = arg; + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); +// printk("%s: enter\n", __FUNCTION__); + + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE); + wake_up_interruptible(&board->wait); + + fmh_gpib_internal_interrupt(board); + + clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); + clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); + + // printk("%s: exit\n", __FUNCTION__); + spin_unlock_irqrestore(&board->spinlock, flags); +} + +/* returns true when all the bytes of a write have been transferred to + * the chip and successfully transferred out over the gpib bus. + */ +static int fmh_gpib_all_bytes_are_sent(struct fmh_priv *e_priv) +{ + if (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & fifo_xfer_counter_mask) + return 0; + + if ((read_byte(&e_priv->nec7210_priv, EXT_STATUS_1_REG) & DATA_OUT_STATUS_BIT) == 0) + return 0; + + return 1; +} + +static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + int retval = 0; + dma_addr_t address; + struct dma_async_tx_descriptor *tx_desc; + + *bytes_written = 0; +// printk("%s: enter\n", __FUNCTION__); + if (WARN_ON_ONCE(length > e_priv->dma_buffer_size)) + return -EFAULT; + dmaengine_terminate_all(e_priv->dma_channel); + memcpy(e_priv->dma_buffer, buffer, length); + address = dma_map_single(board->dev, e_priv->dma_buffer, length, DMA_TO_DEVICE); + if (dma_mapping_error(board->dev, address)) + pr_err("dma mapping error in dma write!\n"); + /* program dma controller */ + retval = fmh_gpib_config_dma(board, 1); + if (retval) + goto cleanup; + + tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx_desc) { + pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n"); + retval = -ENOMEM; + goto cleanup; + } + tx_desc->callback = fmh_gpib_dma_callback; + tx_desc->callback_param = board; + + spin_lock_irqsave(&board->spinlock, flags); + fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); + fifos_write(e_priv, TX_FIFO_DMA_REQUEST_ENABLE | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); + + dmaengine_submit(tx_desc); + dma_async_issue_pending(e_priv->dma_channel); + clear_bit(WRITE_READY_BN, &nec_priv->state); + set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); +// printk("%s: in spin lock\n", __FUNCTION__); + spin_unlock_irqrestore(&board->spinlock, flags); + +// printk("%s: waiting for write.\n", __FUNCTION__); + // suspend until message is sent + if (wait_event_interruptible(board->wait, + fmh_gpib_all_bytes_are_sent(e_priv) || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) + retval = -EIO; + // disable board's dma + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); + fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); + + dmaengine_terminate_all(e_priv->dma_channel); + // make sure fmh_gpib_dma_callback got called + if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state)) + fmh_gpib_dma_callback(board); + + *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & + fifo_xfer_counter_mask); + if (WARN_ON_ONCE(*bytes_written > length)) + return -EFAULT; + /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n", + * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval); + */ +cleanup: + dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE); +// printk("%s: exit, retval=%d\n", __FUNCTION__, retval); + return retval; +} + +static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + size_t remainder = length; + size_t transfer_size; + ssize_t retval = 0; + size_t dma_remainder = remainder; + + if (!e_priv->dma_channel) { + pr_err("fmh_gpib_gpib: No dma channel available, cannot do accel write."); + return -ENXIO; + } + + *bytes_written = 0; + if (length < 1) + return 0; + + smp_mb__before_atomic(); + clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME + smp_mb__after_atomic(); + + if (send_eoi) + --dma_remainder; +// printk("%s: entering while loop\n", __FUNCTION__); + + while (dma_remainder > 0) { + size_t num_bytes; + + retval = wait_for_data_out_ready(board); + if (retval < 0) + break; + + transfer_size = (e_priv->dma_buffer_size < dma_remainder) ? + e_priv->dma_buffer_size : dma_remainder; + retval = fmh_gpib_dma_write(board, buffer, transfer_size, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + break; + dma_remainder -= num_bytes; + remainder -= num_bytes; + buffer += num_bytes; + if (need_resched()) + schedule(); + } + if (retval < 0) + return retval; + //handle sending of last byte with eoi + if (send_eoi) { + size_t num_bytes; + // printk("%s: handling last byte\n", __FUNCTION__); + if (WARN_ON_ONCE(remainder != 1)) + return -EFAULT; + + /* wait until we are sure we will be able to write the data byte + * into the chip before we send AUX_SEOI. This prevents a timeout + * scenario where we send AUX_SEOI but then timeout without getting + * any bytes into the gpib chip. This will result in the first byte + * of the next write having a spurious EOI set on the first byte. + */ + retval = wait_for_data_out_ready(board); + if (retval < 0) + return retval; + + write_byte(nec_priv, AUX_SEOI, AUXMR); + retval = fmh_gpib_dma_write(board, buffer, remainder, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + remainder -= num_bytes; + } +// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder)); + return 0; +} + +static int fmh_gpib_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) +{ + struct dma_tx_state state; + int result; + + result = dmaengine_pause(chan); + if (result < 0) { + pr_err("fmh_gpib_gpib: dma pause failed?\n"); + return result; + } + dmaengine_tx_status(chan, cookie, &state); + // dma330 hardware doesn't support resume, so dont call this + // method unless the dma transfer is done. + return state.residue; +} + +static int wait_for_tx_fifo_half_empty(gpib_board_t *board) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; +// printk("%s: enter\n", __FUNCTION__); + + if (wait_event_interruptible(board->wait, + (test_bit(TACS_NUM, &board->status) && + (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & + TX_FIFO_HALF_EMPTY)) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) + retval = -ERESTARTSYS; + + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; +// printk("%s: exit, retval=%i\n", __FUNCTION__, retval); + return retval; +} + +/* supports writing a chunk of data whose length must fit into the hardware'd xfer counter, + * called in a loop by fmh_gpib_fifo_write() + */ +static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + unsigned int remainder; + + *bytes_written = 0; +// printk("%s: enter\n", __FUNCTION__); + if (WARN_ON_ONCE(length > fifo_xfer_counter_mask)) + return -EFAULT; + + fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); + fifos_write(e_priv, TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); + + remainder = length; + while (remainder > 0) { + int i; + + fifos_write(e_priv, TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG); + retval = wait_for_tx_fifo_half_empty(board); + if (retval < 0) + goto cleanup; + + for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && remainder > 0; ++i) { + unsigned int data_value = *buffer; + + if (send_eoi && remainder == 1) + data_value |= FIFO_DATA_EOI_FLAG; + fifos_write(e_priv, data_value, FIFO_DATA_REG); + ++buffer; + --remainder; + } + } + + // suspend until last byte is sent + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE); + if (wait_event_interruptible(board->wait, + fmh_gpib_all_bytes_are_sent(e_priv) || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) + retval = -EIO; + +cleanup: + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); + fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); + + *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & + fifo_xfer_counter_mask); + if (WARN_ON_ONCE(*bytes_written > length)) + return -EFAULT; + /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n", + * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval); + */ + +// printk("%s: exit, retval=%d\n", __FUNCTION__, retval); + return retval; +} + +static int fmh_gpib_fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + size_t remainder = length; + size_t transfer_size; + ssize_t retval = 0; + + *bytes_written = 0; + if (length < 1) + return 0; + + clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME + +// printk("%s: entering while loop\n", __FUNCTION__); + + while (remainder > 0) { + size_t num_bytes; + int last_pass; + + retval = wait_for_data_out_ready(board); + if (retval < 0) + break; + + if (fifo_xfer_counter_mask < remainder) { + // round transfer size to a multiple of half fifo size + transfer_size = (fifo_xfer_counter_mask / + fmh_gpib_half_fifo_size(e_priv)) * + fmh_gpib_half_fifo_size(e_priv); + last_pass = 0; + } else { + transfer_size = remainder; + last_pass = 1; + } + retval = fmh_gpib_fifo_write_countable(board, buffer, transfer_size, + last_pass && send_eoi, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + break; + remainder -= num_bytes; + buffer += num_bytes; + if (need_resched()) + schedule(); + } +// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder)); + return retval; +} + +static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + unsigned long flags; + int residue; + int wait_retval; + dma_addr_t bus_address; + struct dma_async_tx_descriptor *tx_desc; + dma_cookie_t dma_cookie; + + // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__, + //(unsigned)bus_address, +// (int)length); + + *bytes_read = 0; + *end = 0; + if (length == 0) + return 0; + + bus_address = dma_map_single(board->dev, e_priv->dma_buffer, + length, DMA_FROM_DEVICE); + if (dma_mapping_error(board->dev, bus_address)) + pr_err("dma mapping error in dma read!"); + + /* program dma controller */ + retval = fmh_gpib_config_dma(board, 0); + if (retval) { + dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); + return retval; + } + tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, bus_address, + length, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!tx_desc) { + pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n"); + dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); + return -EIO; + } + tx_desc->callback = fmh_gpib_dma_callback; + tx_desc->callback_param = board; + + spin_lock_irqsave(&board->spinlock, flags); + // enable nec7210 dma + fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); + fifos_write(e_priv, RX_FIFO_DMA_REQUEST_ENABLE | RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); + nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); + + dma_cookie = dmaengine_submit(tx_desc); + dma_async_issue_pending(e_priv->dma_channel); + + set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); + + spin_unlock_irqrestore(&board->spinlock, flags); +// printk("waiting for data transfer.\n"); + // wait for data to transfer + wait_retval = wait_event_interruptible(board->wait, + test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) + == 0 || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status)); + if (wait_retval) { + pr_warn("fmh_gpib: dma read wait interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + retval = -EINTR; + // stop the dma transfer + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); + // give time for pl330 to transfer any in-flight data, since + // pl330 will throw it away when dmaengine_pause is called. + usleep_range(10, 15); + residue = fmh_gpib_get_dma_residue(e_priv->dma_channel, dma_cookie); + if (WARN_ON_ONCE(residue > length || residue < 0)) + return -EFAULT; + *bytes_read += length - residue; + dmaengine_terminate_all(e_priv->dma_channel); + // make sure fmh_gpib_dma_callback got called + if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state)) + fmh_gpib_dma_callback(board); + + dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); + memcpy(buffer, e_priv->dma_buffer, *bytes_read); + + /* Manually read any dregs out of fifo. */ + while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) { + if ((*bytes_read) >= length) { + dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d residue=%d\n", + (int)(*bytes_read), (int)length, (int)residue); + break; + } + buffer[(*bytes_read)++] = fifos_read(e_priv, FIFO_DATA_REG) & fifo_data_mask; + } + + /* If we got an end interrupt, figure out if it was + * associated with the last byte we dma'd or with a + * byte still sitting on the cb7210. + */ + spin_lock_irqsave(&board->spinlock, flags); + if (*bytes_read > 0 && test_bit(READ_READY_BN, &nec_priv->state) == 0) { + // If there is no byte sitting on the cb7210 and we + // saw an end, we need to deal with it now + if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) + *end = 1; + } + spin_unlock_irqrestore(&board->spinlock, flags); +// printk("\tbytes_read=%i, residue=%i, end=%i, retval=%i, wait_retval=%i\n", +// *bytes_read, residue, *end, retval, wait_retval); + + return retval; +} + +static void fmh_gpib_release_rfd_holdoff(gpib_board_t *board, struct fmh_priv *e_priv) +{ + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned int ext_status_1; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + + ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG); + + /* if there is an end byte sitting on the chip, don't release + * holdoff. We want it left set after we read out the end + * byte. + */ + if ((ext_status_1 & (DATA_IN_STATUS_BIT | END_STATUS_BIT)) != + (DATA_IN_STATUS_BIT | END_STATUS_BIT)) { + if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT) + write_byte(nec_priv, AUX_FH, AUXMR); + + /* Check if an end byte raced in before we executed the AUX_FH command. + * If it did, we want to make sure the rfd holdoff is in effect. The end + * byte can arrive since + * AUX_RFD_HOLDOFF_ASAP doesn't immediately force the acceptor handshake + * to leave ACRS. + */ + if ((read_byte(nec_priv, EXT_STATUS_1_REG) & + (RFD_HOLDOFF_STATUS_BIT | DATA_IN_STATUS_BIT | END_STATUS_BIT)) == + (DATA_IN_STATUS_BIT | END_STATUS_BIT)) { + write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + } else { + clear_bit(RFD_HOLDOFF_BN, &nec_priv->state); + } + } + spin_unlock_irqrestore(&board->spinlock, flags); +} + +static int fmh_gpib_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + size_t remain = length; + size_t transfer_size; + int retval = 0; + size_t dma_nbytes; + unsigned long flags; + + smp_mb__before_atomic(); + clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME + smp_mb__after_atomic(); + *end = 0; + *bytes_read = 0; + + retval = wait_for_read(board); + if (retval < 0) + return retval; + + fmh_gpib_release_rfd_holdoff(board, e_priv); + while (remain > 0) { + transfer_size = (e_priv->dma_buffer_size < remain) ? + e_priv->dma_buffer_size : remain; + retval = fmh_gpib_dma_read(board, buffer, transfer_size, end, &dma_nbytes); + remain -= dma_nbytes; + buffer += dma_nbytes; + *bytes_read += dma_nbytes; + if (*end) + break; + if (retval < 0) + break; + if (need_resched()) + schedule(); + } + + spin_lock_irqsave(&board->spinlock, flags); + if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state) == 0) { + write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + } + spin_unlock_irqrestore(&board->spinlock, flags); + + return retval; +} + +/* Read a chunk of data whose length is within the limits of the hardware's + * xfer counter. Called in a loop from fmh_gpib_fifo_read(). + */ +static int fmh_gpib_fifo_read_countable(gpib_board_t *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + int retval = 0; + + // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__, + // (unsigned)bus_address, +// (int)length); + + *bytes_read = 0; + *end = 0; + if (length == 0) + return 0; + + fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); + fifos_write(e_priv, RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); + nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); + + while (*bytes_read < length && *end == 0) { + int i; + + fifos_write(e_priv, RX_FIFO_HALF_FULL_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG); + retval = wait_for_rx_fifo_half_full_or_end(board); + if (retval < 0) + goto cleanup; + + for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && *end == 0; ++i) { + unsigned int data_value; + + data_value = fifos_read(e_priv, FIFO_DATA_REG); + buffer[(*bytes_read)++] = data_value & fifo_data_mask; + if (data_value & FIFO_DATA_EOI_FLAG) + *end = 1; + } + } + +cleanup: + // stop the transfer + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); + + /* Manually read any dregs out of fifo. */ + while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) { + unsigned int data_value; + + if ((*bytes_read) >= length) { + dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d\n", + (int)(*bytes_read), (int)length); + break; + } + data_value = fifos_read(e_priv, FIFO_DATA_REG); + buffer[(*bytes_read)++] = data_value & fifo_data_mask; + if (data_value & FIFO_DATA_EOI_FLAG) + *end = 1; + } + +// printk("\tbytes_read=%i, end=%i, retval=%i, wait_retval=%i\n", +// *bytes_read, *end, retval, wait_retval); + + return retval; +} + +static int fmh_gpib_fifo_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + size_t remain = length; + size_t transfer_size; + int retval = 0; + size_t nbytes; + unsigned long flags; + + clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME + *end = 0; + *bytes_read = 0; + + /* Do a little prep with data in interrupt so that following wait_for_read() + * will wake up if a data byte is received. + */ + nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, HR_DIIE); + fmh_gpib_interrupt(0, board); + + retval = wait_for_read(board); + if (retval < 0) + return retval; + + fmh_gpib_release_rfd_holdoff(board, e_priv); + while (remain > 0) { + if (fifo_xfer_counter_mask < remain) { + // round transfer size to a multiple of half fifo size + transfer_size = (fifo_xfer_counter_mask / + fmh_gpib_half_fifo_size(e_priv)) * + fmh_gpib_half_fifo_size(e_priv); + } else { + transfer_size = remain; + } + retval = fmh_gpib_fifo_read_countable(board, buffer, transfer_size, end, &nbytes); + remain -= nbytes; + buffer += nbytes; + *bytes_read += nbytes; + if (*end) + break; + if (retval < 0) + break; + if (need_resched()) + schedule(); + } + + if (*end == 0) { + spin_lock_irqsave(&board->spinlock, flags); + write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + spin_unlock_irqrestore(&board->spinlock, flags); + } + + return retval; +} + +gpib_interface_t fmh_gpib_unaccel_interface = { +name: "fmh_gpib_unaccel", +attach : fmh_gpib_attach_holdoff_all, +detach : fmh_gpib_detach, +read : fmh_gpib_read, +write : fmh_gpib_write, +command : fmh_gpib_command, +take_control : fmh_gpib_take_control, +go_to_standby : fmh_gpib_go_to_standby, +request_system_control : fmh_gpib_request_system_control, +interface_clear : fmh_gpib_interface_clear, +remote_enable : fmh_gpib_remote_enable, +enable_eos : fmh_gpib_enable_eos, +disable_eos : fmh_gpib_disable_eos, +parallel_poll : fmh_gpib_parallel_poll, +parallel_poll_configure : fmh_gpib_parallel_poll_configure, +parallel_poll_response : fmh_gpib_parallel_poll_response, +local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode, +line_status : fmh_gpib_line_status, +update_status : fmh_gpib_update_status, +primary_address : fmh_gpib_primary_address, +secondary_address : fmh_gpib_secondary_address, +serial_poll_response2 : fmh_gpib_serial_poll_response2, +serial_poll_status : fmh_gpib_serial_poll_status, +t1_delay : fmh_gpib_t1_delay, +return_to_local : fmh_gpib_return_to_local, +}; + +gpib_interface_t fmh_gpib_interface = { +name: "fmh_gpib", +attach : fmh_gpib_attach_holdoff_end, +detach : fmh_gpib_detach, +read : fmh_gpib_accel_read, +write : fmh_gpib_accel_write, +command : fmh_gpib_command, +take_control : fmh_gpib_take_control, +go_to_standby : fmh_gpib_go_to_standby, +request_system_control : fmh_gpib_request_system_control, +interface_clear : fmh_gpib_interface_clear, +remote_enable : fmh_gpib_remote_enable, +enable_eos : fmh_gpib_enable_eos, +disable_eos : fmh_gpib_disable_eos, +parallel_poll : fmh_gpib_parallel_poll, +parallel_poll_configure : fmh_gpib_parallel_poll_configure, +parallel_poll_response : fmh_gpib_parallel_poll_response, +local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode, +line_status : fmh_gpib_line_status, +update_status : fmh_gpib_update_status, +primary_address : fmh_gpib_primary_address, +secondary_address : fmh_gpib_secondary_address, +serial_poll_response2 : fmh_gpib_serial_poll_response2, +serial_poll_status : fmh_gpib_serial_poll_status, +t1_delay : fmh_gpib_t1_delay, +return_to_local : fmh_gpib_return_to_local, +}; + +gpib_interface_t fmh_gpib_pci_interface = { +name: "fmh_gpib_pci", +attach : fmh_gpib_pci_attach_holdoff_end, +detach : fmh_gpib_pci_detach, +read : fmh_gpib_fifo_read, +write : fmh_gpib_fifo_write, +command : fmh_gpib_command, +take_control : fmh_gpib_take_control, +go_to_standby : fmh_gpib_go_to_standby, +request_system_control : fmh_gpib_request_system_control, +interface_clear : fmh_gpib_interface_clear, +remote_enable : fmh_gpib_remote_enable, +enable_eos : fmh_gpib_enable_eos, +disable_eos : fmh_gpib_disable_eos, +parallel_poll : fmh_gpib_parallel_poll, +parallel_poll_configure : fmh_gpib_parallel_poll_configure, +parallel_poll_response : fmh_gpib_parallel_poll_response, +local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode, +line_status : fmh_gpib_line_status, +update_status : fmh_gpib_update_status, +primary_address : fmh_gpib_primary_address, +secondary_address : fmh_gpib_secondary_address, +serial_poll_response2 : fmh_gpib_serial_poll_response2, +serial_poll_status : fmh_gpib_serial_poll_status, +t1_delay : fmh_gpib_t1_delay, +return_to_local : fmh_gpib_return_to_local, +}; + +gpib_interface_t fmh_gpib_pci_unaccel_interface = { +name: "fmh_gpib_pci_unaccel", +attach : fmh_gpib_pci_attach_holdoff_all, +detach : fmh_gpib_pci_detach, +read : fmh_gpib_read, +write : fmh_gpib_write, +command : fmh_gpib_command, +take_control : fmh_gpib_take_control, +go_to_standby : fmh_gpib_go_to_standby, +request_system_control : fmh_gpib_request_system_control, +interface_clear : fmh_gpib_interface_clear, +remote_enable : fmh_gpib_remote_enable, +enable_eos : fmh_gpib_enable_eos, +disable_eos : fmh_gpib_disable_eos, +parallel_poll : fmh_gpib_parallel_poll, +parallel_poll_configure : fmh_gpib_parallel_poll_configure, +parallel_poll_response : fmh_gpib_parallel_poll_response, +local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode, +line_status : fmh_gpib_line_status, +update_status : fmh_gpib_update_status, +primary_address : fmh_gpib_primary_address, +secondary_address : fmh_gpib_secondary_address, +serial_poll_response2 : fmh_gpib_serial_poll_response2, +serial_poll_status : fmh_gpib_serial_poll_status, +t1_delay : fmh_gpib_t1_delay, +return_to_local : fmh_gpib_return_to_local, +}; + +irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board) +{ + unsigned int status0, status1, status2, ext_status_1, fifo_status; + struct fmh_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + int retval = IRQ_NONE; + + status0 = read_byte(nec_priv, ISR0_IMR0_REG); + status1 = read_byte(nec_priv, ISR1); + status2 = read_byte(nec_priv, ISR2); + fifo_status = fifos_read(priv, FIFO_CONTROL_STATUS_REG); + + if (status0 & IFC_INTERRUPT_BIT) { + push_gpib_event(board, EventIFC); + retval = IRQ_HANDLED; + } + + if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED) + retval = IRQ_HANDLED; + + ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG); + + if (ext_status_1 & DATA_IN_STATUS_BIT) + set_bit(READ_READY_BN, &nec_priv->state); + else + clear_bit(READ_READY_BN, &nec_priv->state); + + if (ext_status_1 & DATA_OUT_STATUS_BIT) + set_bit(WRITE_READY_BN, &nec_priv->state); + else + clear_bit(WRITE_READY_BN, &nec_priv->state); + + if (ext_status_1 & COMMAND_OUT_STATUS_BIT) + set_bit(COMMAND_READY_BN, &nec_priv->state); + else + clear_bit(COMMAND_READY_BN, &nec_priv->state); + + if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT) + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + else + clear_bit(RFD_HOLDOFF_BN, &nec_priv->state); + + if (ext_status_1 & END_STATUS_BIT) { + /* only set RECEIVED_END while there is still a data + * byte sitting in the chip, to avoid spuriously + * setting it multiple times after it has been cleared + * during a read. + */ + if (ext_status_1 & DATA_IN_STATUS_BIT) + set_bit(RECEIVED_END_BN, &nec_priv->state); + } else { + clear_bit(RECEIVED_END_BN, &nec_priv->state); + } + + if ((fifo_status & TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED) && + (fifo_status & TX_FIFO_HALF_EMPTY)) { + /* We really only want to clear the + * TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE bit in the + * FIFO_CONTROL_STATUS_REG. Since we are not being + * careful, this also has a side effect of disabling + * DMA requests and the RX fifo interrupt. That is + * fine though, since they should never be in use at + * the same time as the TX fifo interrupt. + */ + fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG); + retval = IRQ_HANDLED; + } + + if ((fifo_status & RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED) && + (fifo_status & RX_FIFO_HALF_FULL)) { + /* We really only want to clear the + * RX_FIFO_HALF_FULL_INTERRUPT_ENABLE bit in the + * FIFO_CONTROL_STATUS_REG. Since we are not being + * careful, this also has a side effect of disabling + * DMA requests and the TX fifo interrupt. That is + * fine though, since they should never be in use at + * the same time as the RX fifo interrupt. + */ + fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG); + retval = IRQ_HANDLED; + } + + if (retval == IRQ_HANDLED) + wake_up_interruptible(&board->wait); + + return retval; +} + +irqreturn_t fmh_gpib_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = fmh_gpib_internal_interrupt(board); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +static int fmh_gpib_allocate_private(gpib_board_t *board) +{ + struct fmh_priv *priv; + + board->private_data = kmalloc(sizeof(struct fmh_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + priv = board->private_data; + memset(priv, 0, sizeof(struct fmh_priv)); + init_nec7210_private(&priv->nec7210_priv); + priv->dma_buffer_size = 0x800; + priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL); + if (!priv->dma_buffer) + return -ENOMEM; + return 0; +} + +static void fmh_gpib_generic_detach(gpib_board_t *board) +{ + if (board->private_data) { + struct fmh_priv *e_priv = board->private_data; + + kfree(e_priv->dma_buffer); + kfree(board->private_data); + board->private_data = NULL; + } + if (board->dev) + dev_set_drvdata(board->dev, NULL); +} + +// generic part of attach functions +static int fmh_gpib_generic_attach(gpib_board_t *board) +{ + struct fmh_priv *e_priv; + struct nec7210_priv *nec_priv; + int retval; + + board->status = 0; + + retval = fmh_gpib_allocate_private(board); + if (retval < 0) + return retval; + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + nec_priv->read_byte = gpib_cs_read_byte; + nec_priv->write_byte = gpib_cs_write_byte; + nec_priv->offset = 1; + nec_priv->type = CB7210; + return 0; +} + +static int fmh_gpib_config_dma(gpib_board_t *board, int output) +{ + struct fmh_priv *e_priv = board->private_data; + struct dma_slave_config config; + + config.device_fc = true; + + if (e_priv->dma_burst_length < 1) { + config.src_maxburst = 1; + config.dst_maxburst = 1; + } else { + config.src_maxburst = e_priv->dma_burst_length; + config.dst_maxburst = e_priv->dma_burst_length; + } + + config.src_addr_width = 1; + config.dst_addr_width = 1; + + if (output) { + config.direction = DMA_MEM_TO_DEV; + config.src_addr = 0; + config.dst_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset; + } else { + config.direction = DMA_DEV_TO_MEM; + config.src_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset; + config.dst_addr = 0; + } + return dmaengine_slave_config(e_priv->dma_channel, &config); +} + +static int fmh_gpib_init(struct fmh_priv *e_priv, gpib_board_t *board, int handshake_mode) +{ + struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; + unsigned long flags; + unsigned int fifo_status_bits; + + fifos_write(e_priv, RX_FIFO_CLEAR | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); + + nec7210_board_reset(nec_priv, board); + write_byte(nec_priv, AUX_LO_SPEED, AUXMR); + nec7210_set_handshake_mode(board, nec_priv, handshake_mode); + + /* Hueristically check if hardware supports fifo half full/empty interrupts */ + fifo_status_bits = fifos_read(e_priv, FIFO_CONTROL_STATUS_REG); + e_priv->supports_fifo_interrupts = (fifo_status_bits & TX_FIFO_EMPTY) && + (fifo_status_bits & TX_FIFO_HALF_EMPTY); + + nec7210_board_online(nec_priv, board); + + write_byte(nec_priv, IFC_INTERRUPT_ENABLE_BIT | ATN_INTERRUPT_ENABLE_BIT, ISR0_IMR0_REG); + + spin_lock_irqsave(&board->spinlock, flags); + write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + spin_unlock_irqrestore(&board->spinlock, flags); + return 0; +} + +/* Match callback for driver_find_device */ +static int fmh_gpib_device_match(struct device *dev, const void *data) +{ + const gpib_board_config_t *config = data; + + if (dev_get_drvdata(dev)) + return 0; + + if (gpib_match_device_path(dev, config->device_path) == 0) + return 0; + + // driver doesn't support selection by serial number + if (config->serial_number) + return 0; + + dev_notice(dev, "matched: %s\n", of_node_full_name(dev_of_node((dev)))); + return 1; +} + +static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t *config, + unsigned int handshake_mode, int acquire_dma) +{ + struct fmh_priv *e_priv; + struct nec7210_priv *nec_priv; + int retval; + int irq; + struct resource *res; + struct platform_device *pdev; + + board->dev = driver_find_device(&fmh_gpib_platform_driver.driver, + NULL, (const void *)config, &fmh_gpib_device_match); + if (!board->dev) { + pr_err("No matching fmh_gpib_core device was found, attach failed."); + return -ENODEV; + } + // currently only used to mark the device as already attached + dev_set_drvdata(board->dev, board); + pdev = to_platform_device(board->dev); + + retval = fmh_gpib_generic_attach(board); + if (retval) + return retval; + + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpib_control_status"); + if (!res) { + dev_err(board->dev, "Unable to locate mmio resource for cb7210 gpib\n"); + return -ENODEV; + } + + if (request_mem_region(res->start, + resource_size(res), + pdev->name) == NULL) { + dev_err(board->dev, "cannot claim registers\n"); + return -ENXIO; + } + e_priv->gpib_iomem_res = res; + + nec_priv->iobase = ioremap(e_priv->gpib_iomem_res->start, + resource_size(e_priv->gpib_iomem_res)); + if (!nec_priv->iobase) { + dev_err(board->dev, "Could not map I/O memory for gpib\n"); + return -ENOMEM; + } + dev_info(board->dev, "iobase 0x%lx remapped to %p, length=%ld\n", + (unsigned long)e_priv->gpib_iomem_res->start, + nec_priv->iobase, (unsigned long)resource_size(e_priv->gpib_iomem_res)); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma_fifos"); + if (!res) { + dev_err(board->dev, "Unable to locate mmio resource for gpib dma port\n"); + return -ENODEV; + } + if (request_mem_region(res->start, + resource_size(res), + pdev->name) == NULL) { + dev_err(board->dev, "cannot claim registers\n"); + return -ENXIO; + } + e_priv->dma_port_res = res; + e_priv->fifo_base = ioremap(e_priv->dma_port_res->start, + resource_size(e_priv->dma_port_res)); + if (!e_priv->fifo_base) { + dev_err(board->dev, "Could not map I/O memory for fifos\n"); + return -ENOMEM; + } + dev_info(board->dev, "dma fifos 0x%lx remapped to %p, length=%ld\n", + (unsigned long)e_priv->dma_port_res->start, e_priv->fifo_base, + (unsigned long)resource_size(e_priv->dma_port_res)); + + irq = platform_get_irq(pdev, 0); + pr_info("gpib: irq %d\n", irq); + if (irq < 0) { + dev_err(board->dev, "fmh_gpib_gpib: request for IRQ failed\n"); + return -EBUSY; + } + retval = request_irq(irq, fmh_gpib_interrupt, IRQF_SHARED, pdev->name, board); + if (retval) { + dev_err(board->dev, + "cannot register interrupt handler err=%d\n", + retval); + return retval; + } + e_priv->irq = irq; + + if (acquire_dma) { + e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx"); + if (!e_priv->dma_channel) { + dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n"); + return -EIO; + } + } + /* in the future we might want to know the half-fifo size + * (dma_burst_length) even when not using dma, so go ahead an + * initialize it unconditionally. + */ + e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) & + fifo_max_burst_length_mask; + + return fmh_gpib_init(e_priv, board, handshake_mode); +} + +int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config) +{ + return fmh_gpib_attach_impl(board, config, HR_HLDA, 0); +} + +int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config) +{ + return fmh_gpib_attach_impl(board, config, HR_HLDE, 1); +} + +void fmh_gpib_detach(gpib_board_t *board) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (e_priv) { + if (e_priv->dma_channel) + dma_release_channel(e_priv->dma_channel); + nec_priv = &e_priv->nec7210_priv; + + if (e_priv->irq) + free_irq(e_priv->irq, board); + if (e_priv->fifo_base) + fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); + if (nec_priv->iobase) { + write_byte(nec_priv, 0, ISR0_IMR0_REG); + nec7210_board_reset(nec_priv, board); + } + if (e_priv->fifo_base) + iounmap(e_priv->fifo_base); + if (nec_priv->iobase) + iounmap(nec_priv->iobase); + if (e_priv->dma_port_res) { + release_mem_region(e_priv->dma_port_res->start, + resource_size(e_priv->dma_port_res)); + } + if (e_priv->gpib_iomem_res) + release_mem_region(e_priv->gpib_iomem_res->start, + resource_size(e_priv->gpib_iomem_res)); + } + fmh_gpib_generic_detach(board); +} + +static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config_t *config, + unsigned int handshake_mode) +{ + struct fmh_priv *e_priv; + struct nec7210_priv *nec_priv; + int retval; + struct pci_dev *pci_device; + + retval = fmh_gpib_generic_attach(board); + if (retval) + return retval; + + e_priv = board->private_data; + nec_priv = &e_priv->nec7210_priv; + + // find board + pci_device = gpib_pci_get_device(config, BOGUS_PCI_VENDOR_ID_FLUKE, + BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, NULL); + if (!pci_device) { + pr_err("No matching fmh_gpib_core pci device was found, attach failed."); + return -ENODEV; + } + board->dev = &pci_device->dev; + + // bladerunner prototype has offset of 4 between gpib control/status registers + nec_priv->offset = 4; + + if (pci_enable_device(pci_device)) { + dev_err(board->dev, "error enabling pci device\n"); + return -EIO; + } + if (pci_request_regions(pci_device, KBUILD_MODNAME)) { + dev_err(board->dev, "pci_request_regions failed\n"); + return -EIO; + } + e_priv->gpib_iomem_res = &pci_device->resource[gpib_control_status_pci_resource_index]; + e_priv->dma_port_res = &pci_device->resource[gpib_fifo_pci_resource_index]; + + nec_priv->iobase = ioremap(pci_resource_start(pci_device, + gpib_control_status_pci_resource_index), + pci_resource_len(pci_device, + gpib_control_status_pci_resource_index)); + dev_info(board->dev, "base address for gpib control/status registers remapped to 0x%p\n", + nec_priv->iobase); + + if (e_priv->dma_port_res->flags & IORESOURCE_MEM) { + e_priv->fifo_base = ioremap(pci_resource_start(pci_device, + gpib_fifo_pci_resource_index), + pci_resource_len(pci_device, + gpib_fifo_pci_resource_index)); + dev_info(board->dev, "base address for gpib fifo registers remapped to 0x%p\n", + e_priv->fifo_base); + } else { + e_priv->fifo_base = NULL; + dev_info(board->dev, "hardware has no gpib fifo registers.\n"); + } + + if (pci_device->irq) { + retval = request_irq(pci_device->irq, fmh_gpib_interrupt, IRQF_SHARED, + KBUILD_MODNAME, board); + if (retval) { + dev_err(board->dev, + "cannot register interrupt handler err=%d\n", + retval); + return retval; + } + } + e_priv->irq = pci_device->irq; + + e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) & + fifo_max_burst_length_mask; + + return fmh_gpib_init(e_priv, board, handshake_mode); +} + +int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config) +{ + return fmh_gpib_pci_attach_impl(board, config, HR_HLDA); +} + +int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config) +{ + int retval; + struct fmh_priv *e_priv; + + retval = fmh_gpib_pci_attach_impl(board, config, HR_HLDE); + e_priv = board->private_data; + if (retval == 0 && e_priv && e_priv->supports_fifo_interrupts == 0) { + pr_err("fmh_gpib: your fmh_gpib_core does not appear to support fifo interrupts. Try the fmh_gpib_pci_unaccel board type instead."); + return -EIO; + } + return retval; +} + +void fmh_gpib_pci_detach(gpib_board_t *board) +{ + struct fmh_priv *e_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (e_priv) { + nec_priv = &e_priv->nec7210_priv; + + if (e_priv->irq) + free_irq(e_priv->irq, board); + if (e_priv->fifo_base) + fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); + if (nec_priv->iobase) { + write_byte(nec_priv, 0, ISR0_IMR0_REG); + nec7210_board_reset(nec_priv, board); + } + if (e_priv->fifo_base) + iounmap(e_priv->fifo_base); + if (nec_priv->iobase) + iounmap(nec_priv->iobase); + if (e_priv->dma_port_res || e_priv->gpib_iomem_res) + pci_release_regions(to_pci_dev(board->dev)); + if (board->dev) + pci_dev_put(to_pci_dev(board->dev)); + } + fmh_gpib_generic_detach(board); +} + +static int fmh_gpib_platform_probe(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id fmh_gpib_of_match[] = { + { .compatible = "fmhess,fmh_gpib_core"}, + { {0} } +}; +MODULE_DEVICE_TABLE(of, fmh_gpib_of_match); + +static struct platform_driver fmh_gpib_platform_driver = { + .driver = { + .name = "fmh_gpib", + .owner = THIS_MODULE, + .of_match_table = fmh_gpib_of_match, + }, + .probe = &fmh_gpib_platform_probe +}; + +static int fmh_gpib_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return 0; +} + +static const struct pci_device_id fmh_gpib_pci_match[] = { + { BOGUS_PCI_VENDOR_ID_FLUKE, BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, 0, 0, 0 }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, fmh_gpib_pci_match); + +static struct pci_driver fmh_gpib_pci_driver = { + .name = "fmh_gpib", + .id_table = fmh_gpib_pci_match, + .probe = &fmh_gpib_pci_probe +}; + +static int __init fmh_gpib_init_module(void) +{ + int result; + + result = platform_driver_register(&fmh_gpib_platform_driver); + if (result) { + pr_err("fmh_gpib: platform_driver_register failed!\n"); + return result; + } + + result = pci_register_driver(&fmh_gpib_pci_driver); + if (result) { + pr_err("fmh_gpib: pci_driver_register failed!\n"); + return result; + } + + gpib_register_driver(&fmh_gpib_unaccel_interface, THIS_MODULE); + gpib_register_driver(&fmh_gpib_interface, THIS_MODULE); + gpib_register_driver(&fmh_gpib_pci_unaccel_interface, THIS_MODULE); + gpib_register_driver(&fmh_gpib_pci_interface, THIS_MODULE); + + pr_info("fmh_gpib\n"); + return 0; +} + +static void __exit fmh_gpib_exit_module(void) +{ + gpib_unregister_driver(&fmh_gpib_pci_interface); + gpib_unregister_driver(&fmh_gpib_pci_unaccel_interface); + gpib_unregister_driver(&fmh_gpib_unaccel_interface); + gpib_unregister_driver(&fmh_gpib_interface); + + pci_unregister_driver(&fmh_gpib_pci_driver); + platform_driver_unregister(&fmh_gpib_platform_driver); +} + +module_init(fmh_gpib_init_module); +module_exit(fmh_gpib_exit_module); diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.h b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h new file mode 100644 index 0000000000000000000000000000000000000000..43bfc89d2a6feb4c7fab742fa54c971cfa2c584f --- /dev/null +++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Author: Frank Mori Hess <fmh6jj@gmail.com> + * Copyright: (C) 2006, 2010, 2015 Fluke Corporation + * (C) 2017 Frank Mori Hess + ***************************************************************************/ + +#include <linux/dmaengine.h> +#include <linux/ioport.h> +#include <linux/pci.h> +#include <linux/io.h> +#include "nec7210.h" + +static const int fifo_reg_offset = 2; + +static const int gpib_control_status_pci_resource_index; +static const int gpib_fifo_pci_resource_index = 1; + +/* We don't have a real pci vendor/device id, the following will need to be + * patched to match prototype hardware. + */ +#define BOGUS_PCI_VENDOR_ID_FLUKE 0xffff +#define BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER 0x0 + +struct fmh_priv { + struct nec7210_priv nec7210_priv; + struct resource *gpib_iomem_res; + struct resource *write_transfer_counter_res; + struct resource *dma_port_res; + int irq; + struct dma_chan *dma_channel; + u8 *dma_buffer; + int dma_buffer_size; + int dma_burst_length; + void *fifo_base; + unsigned supports_fifo_interrupts : 1; +}; + +static inline int fmh_gpib_half_fifo_size(struct fmh_priv *priv) +{ + return priv->dma_burst_length; +} + +// registers beyond the nec7210 register set +enum fmh_gpib_regs { + EXT_STATUS_1_REG = 0x9, + STATE1_REG = 0xc, + ISR0_IMR0_REG = 0xe, + BUS_STATUS_REG = 0xf +}; + +/* IMR0 -- Interrupt Mode Register 0 */ +enum imr0_bits { + ATN_INTERRUPT_ENABLE_BIT = 0x4, + IFC_INTERRUPT_ENABLE_BIT = 0x8 +}; + +/* ISR0 -- Interrupt Status Register 0 */ +enum isr0_bits { + ATN_INTERRUPT_BIT = 0x4, + IFC_INTERRUPT_BIT = 0x8 +}; + +enum state1_bits { + SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */ + SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */ + SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */ + SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */ + SOURCE_HANDSHAKE_MASK = 0x7 +}; + +enum fmh_gpib_auxmr_bits { + AUX_I_REG = 0xe0, +}; + +enum aux_reg_i_bits { + LOCAL_PPOLL_MODE_BIT = 0x4 +}; + +enum ext_status_1_bits { + DATA_IN_STATUS_BIT = 0x01, + DATA_OUT_STATUS_BIT = 0x02, + COMMAND_OUT_STATUS_BIT = 0x04, + RFD_HOLDOFF_STATUS_BIT = 0x08, + END_STATUS_BIT = 0x10 +}; + +/* dma fifo reg and bits */ +enum dma_fifo_regs { + FIFO_DATA_REG = 0x0, + FIFO_CONTROL_STATUS_REG = 0x1, + FIFO_XFER_COUNTER_REG = 0x2, + FIFO_MAX_BURST_LENGTH_REG = 0x3 +}; + +enum fifo_data_bits { + FIFO_DATA_EOI_FLAG = 0x100 +}; + +enum fifo_control_bits { + TX_FIFO_DMA_REQUEST_ENABLE = 0x0001, + TX_FIFO_CLEAR = 0x0002, + TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE = 0x0008, + RX_FIFO_DMA_REQUEST_ENABLE = 0x0100, + RX_FIFO_CLEAR = 0x0200, + RX_FIFO_HALF_FULL_INTERRUPT_ENABLE = 0x0800 +}; + +enum fifo_status_bits { + TX_FIFO_EMPTY = 0x0001, + TX_FIFO_FULL = 0x0002, + TX_FIFO_HALF_EMPTY = 0x0004, + TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED = 0x0008, + TX_FIFO_DMA_REQUEST_IS_ENABLED = 0x0010, + RX_FIFO_EMPTY = 0x0100, + RX_FIFO_FULL = 0x0200, + RX_FIFO_HALF_FULL = 0x0400, + RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED = 0x0800, + RX_FIFO_DMA_REQUEST_IS_ENABLED = 0x1000 +}; + +static const unsigned int fifo_data_mask = 0x00ff; +static const unsigned int fifo_xfer_counter_mask = 0x0fff; +static const unsigned int fifo_max_burst_length_mask = 0x00ff; + +static inline uint8_t gpib_cs_read_byte(struct nec7210_priv *nec_priv, + unsigned int register_num) +{ + return readb(nec_priv->iobase + register_num * nec_priv->offset); +} + +static inline void gpib_cs_write_byte(struct nec7210_priv *nec_priv, uint8_t data, + unsigned int register_num) +{ + writeb(data, nec_priv->iobase + register_num * nec_priv->offset); +} + +static inline uint16_t fifos_read(struct fmh_priv *fmh_priv, int register_num) +{ + if (!fmh_priv->fifo_base) + return 0; + return readw(fmh_priv->fifo_base + register_num * fifo_reg_offset); +} + +static inline void fifos_write(struct fmh_priv *fmh_priv, uint16_t data, int register_num) +{ + if (!fmh_priv->fifo_base) + return; + writew(data, fmh_priv->fifo_base + register_num * fifo_reg_offset); +} + +enum bus_status_bits { + BSR_ATN_BIT = 0x01, + BSR_EOI_BIT = 0x02, + BSR_SRQ_BIT = 0x04, + BSR_IFC_BIT = 0x08, + BSR_REN_BIT = 0x10, + BSR_DAV_BIT = 0x20, + BSR_NRFD_BIT = 0x40, + BSR_NDAC_BIT = 0x80, +}; + +enum fmh_gpib_aux_cmds { + /* AUX_RTL2 is an auxiliary command which causes the cb7210 to assert + * (and keep asserted) the local rtl message. This is used in conjunction + * with the normal nec7210 AUX_RTL command, which + * pulses the rtl message, having the effect of clearing rtl if it was left + * asserted by AUX_RTL2. + */ + AUX_RTL2 = 0x0d, + AUX_RFD_HOLDOFF_ASAP = 0x15, + AUX_REQT = 0x18, + AUX_REQF = 0x19, + AUX_LO_SPEED = 0x40, + AUX_HI_SPEED = 0x41 +}; diff --git a/drivers/staging/gpib/gpio/Makefile b/drivers/staging/gpib/gpio/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a31ded6e59245e3ccd9ff308cf6179ad3a74353e --- /dev/null +++ b/drivers/staging/gpib/gpio/Makefile @@ -0,0 +1,4 @@ + +obj-m += gpib_bitbang.o + + diff --git a/drivers/staging/gpib/gpio/gpib_bitbang.c b/drivers/staging/gpib/gpio/gpib_bitbang.c new file mode 100644 index 0000000000000000000000000000000000000000..a2d562cbd65b43bd902c6ba6f1c117323423abf2 --- /dev/null +++ b/drivers/staging/gpib/gpio/gpib_bitbang.c @@ -0,0 +1,1476 @@ +// SPDX-License-Identifier: GPL-2.0 + +/************************************************************************* + * This code has been developed at the Institute of Sensor and Actuator * + * Systems (Technical University of Vienna, Austria) to enable the GPIO * + * lines (e.g. of a raspberry pi) to function as a GPIO master device * + * * + * authors : Thomas Klima * + * Marcello Carla' * + * Dave Penkler * + * * + * copyright : (C) 2016 Thomas Klima * + * * + *************************************************************************/ + +/* + * limitations: + * works only on RPi + * cannot function as non-CIC system controller with SN7516x because + * SN75161B cannot simultaneously make ATN input with IFC and REN as + * outputs. + * not implemented: + * parallel poll + * return2local + * device support (non master operation) + */ + +#define NAME KBUILD_MODNAME + +#define ENABLE_IRQ(IRQ, TYPE) irq_set_irq_type(IRQ, TYPE) +#define DISABLE_IRQ(IRQ) irq_set_irq_type(IRQ, IRQ_TYPE_NONE) + +/* Debug print levels: + * 0 = load/unload info and errors that make the driver fail; + * 1 = + warnings for unforeseen events that may break the current + * operation and lead to a timeout, but do not affect the + * driver integrity (mainly unexpected interrupts); + * 2 = + trace of function calls; + * 3 = + trace of protocol codes; + * 4 = + trace of interrupt operation. + */ +#define dbg_printk(level, frm, ...) \ + do { if (debug >= (level)) \ + pr_info("%s:%s - " frm, NAME, __func__, ## __VA_ARGS__); } \ + while (0) + +#define LINVAL gpiod_get_value(DAV), \ + gpiod_get_value(NRFD), \ + gpiod_get_value(NDAC), \ + gpiod_get_value(SRQ) +#define LINFMT "DAV: %d NRFD:%d NDAC: %d SRQ: %d" + +#include "gpibP.h" +#include "gpib_state_machines.h" +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/driver.h> +#include <linux/gpio/machine.h> +#include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/leds.h> + +static int sn7516x_used = 1, sn7516x; +module_param(sn7516x_used, int, 0660); + +#define PINMAP_0 "elektronomikon" +#define PINMAP_1 "gpib4pi-1.1" +#define PINMAP_2 "yoga" +static char *pin_map = PINMAP_0; +module_param(pin_map, charp, 0660); +MODULE_PARM_DESC(pin_map, " valid values: " PINMAP_0 " " PINMAP_1 " " PINMAP_2); + +/********************************************** + * Signal pairing and pin wiring between the * + * Raspberry-Pi connector and the GPIB bus * + * * + * signal pin wiring * + * GPIB Pi-gpio GPIB -> RPi * + ********************************************** + */ +enum lines_t { + D01_pin_nr = 20, /* 1 -> 38 */ + D02_pin_nr = 26, /* 2 -> 37 */ + D03_pin_nr = 16, /* 3 -> 36 */ + D04_pin_nr = 19, /* 4 -> 35 */ + D05_pin_nr = 13, /* 13 -> 33 */ + D06_pin_nr = 12, /* 14 -> 32 */ + D07_pin_nr = 6, /* 15 -> 31 */ + D08_pin_nr = 5, /* 16 -> 29 */ + EOI_pin_nr = 9, /* 5 -> 21 */ + DAV_pin_nr = 10, /* 6 -> 19 */ + NRFD_pin_nr = 24, /* 7 -> 18 */ + NDAC_pin_nr = 23, /* 8 -> 16 */ + IFC_pin_nr = 22, /* 9 -> 15 */ + SRQ_pin_nr = 11, /* 10 -> 23 */ + _ATN_pin_nr = 25, /* 11 -> 22 */ + REN_pin_nr = 27, /* 17 -> 13 */ +/* + * GROUND PINS + * 12,18,19,20,21,22,23,24 => 14,20,25,30,34,39 + */ + +/* + * These lines are used to control the external + * SN75160/161 driver chips when used. + * When not used there is reduced fan out; + * currently tested with up to 4 devices. + */ + +/* Pi GPIO RPI 75161B 75160B Description */ + PE_pin_nr = 7, /* 26 -> nc 11 Pullup Enable */ + DC_pin_nr = 8, /* 24 -> 12 nc Direction control */ + TE_pin_nr = 18, /* 12 -> 2 1 Talk Enable */ + ACT_LED_pin_nr = 4, /* 7 -> LED */ + +/* YOGA adapter uses different pinout to ease layout */ + YOGA_D03_pin_nr = 13, + YOGA_D04_pin_nr = 12, + YOGA_D05_pin_nr = 21, + YOGA_D06_pin_nr = 19, +}; + +/* + * GPIO descriptors and pins - WARNING: STRICTLY KEEP ITEMS ORDER + */ + +#define GPIB_PINS 16 +#define SN7516X_PINS 4 +#define NUM_PINS (GPIB_PINS + SN7516X_PINS) + +DEFINE_LED_TRIGGER(ledtrig_gpib); +#define ACT_LED_ON do { \ + if (ACT_LED) \ + gpiod_direction_output(ACT_LED, 1); \ + else \ + led_trigger_event(ledtrig_gpib, LED_FULL); } \ + while (0) +#define ACT_LED_OFF do { \ + if (ACT_LED) \ + gpiod_direction_output(ACT_LED, 0); \ + else \ + led_trigger_event(ledtrig_gpib, LED_OFF); } \ + while (0) + +struct gpio_desc *all_descriptors[GPIB_PINS + SN7516X_PINS]; + +#define D01 all_descriptors[0] +#define D02 all_descriptors[1] +#define D03 all_descriptors[2] +#define D04 all_descriptors[3] +#define D05 all_descriptors[4] +#define D06 all_descriptors[5] +#define D07 all_descriptors[6] +#define D08 all_descriptors[7] + +#define EOI all_descriptors[8] +#define NRFD all_descriptors[9] +#define IFC all_descriptors[10] +#define _ATN all_descriptors[11] +#define REN all_descriptors[12] +#define DAV all_descriptors[13] +#define NDAC all_descriptors[14] +#define SRQ all_descriptors[15] + +#define PE all_descriptors[16] +#define DC all_descriptors[17] +#define TE all_descriptors[18] +#define ACT_LED all_descriptors[19] + +/* YOGA dapter uses a global enable for the buffer chips, re-using the TE pin */ +#define YOGA_ENABLE TE + +int gpios_vector[] = { + D01_pin_nr, + D02_pin_nr, + D03_pin_nr, + D04_pin_nr, + D05_pin_nr, + D06_pin_nr, + D07_pin_nr, + D08_pin_nr, + + EOI_pin_nr, + NRFD_pin_nr, + IFC_pin_nr, + _ATN_pin_nr, + REN_pin_nr, + DAV_pin_nr, + NDAC_pin_nr, + SRQ_pin_nr, + + PE_pin_nr, + DC_pin_nr, + TE_pin_nr, + ACT_LED_pin_nr +}; + +/* Lookup table for general GPIOs */ + +static struct gpiod_lookup_table gpib_gpio_table_1 = { + // for bcm2835/6 + .dev_id = "", // device id of board device + .table = { + GPIO_LOOKUP_IDX("GPIO_GCLK", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("SPI_CE1_N", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("SPI_CE0_N", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("SPI_MISO", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("SPI_MOSI", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("SPI_SCLK", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH), + { } + }, +}; + +static struct gpiod_lookup_table gpib_gpio_table_0 = { + .dev_id = "", // device id of board device + .table = { + // for bcm27xx based pis (b b+ 2b 3b 3b+ 4 5) + GPIO_LOOKUP_IDX("GPIO4", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO7", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO8", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO9", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO10", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO11", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH), + { } + }, +}; + +static struct gpiod_lookup_table *lookup_tables[] = { + &gpib_gpio_table_0, + &gpib_gpio_table_1, + 0 +}; + +/* struct which defines private_data for gpio driver */ + +struct bb_priv { + int irq_NRFD; + int irq_NDAC; + int irq_DAV; + int irq_SRQ; + int dav_mode; /* dav interrupt mode 0/1 -> edge/levels */ + int nrfd_mode; /* nrfd interrupt mode 0/1 -> edge/levels */ + int ndac_mode; /* nrfd interrupt mode 0/1 -> edge/levels */ + int dav_tx; /* keep trace of DAV status while sending */ + int dav_rx; /* keep trace of DAV status while receiving */ + u8 eos; // eos character + short eos_flags; // eos mode + short eos_check; /* eos check required in current operation ... */ + short eos_check_8; /* ... with byte comparison */ + short eos_mask_7; /* ... with 7 bit masked character */ + short int end; + int request; + int count; + int direction; + int t1_delay; + u8 *rbuf; + u8 *wbuf; + int end_flag; + int r_busy; /* 0==idle 1==busy */ + int w_busy; + int write_done; + int cmd; /* 1 = cmd write in progress */ + size_t w_cnt; + size_t length; + u8 *w_buf; + spinlock_t rw_lock; // protect mods to rw_lock + int phase; + int ndac_idle; + int ndac_seq; + int nrfd_idle; + int nrfd_seq; + int dav_seq; + long all_irqs; + int dav_idle; + int atn_asserted; + + enum talker_function_state talker_state; + enum listener_function_state listener_state; +}; + +inline long usec_diff(struct timespec64 *a, struct timespec64 *b); +static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi); +static void set_data_lines(u8 byte); +static u8 get_data_lines(void); +static void set_data_lines_input(void); +static void set_data_lines_output(void); +static inline int check_for_eos(struct bb_priv *priv, uint8_t byte); +static void set_atn(struct bb_priv *priv, int atn_asserted); + +static inline void SET_DIR_WRITE(struct bb_priv *priv); +static inline void SET_DIR_READ(struct bb_priv *priv); + +#define DIR_READ 0 +#define DIR_WRITE 1 + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB helper functions for bitbanging I/O"); + +/**** global variables ****/ +#ifdef CONFIG_GPIB_DEBUG +static int debug = 1; +#else +static int debug; +#endif +module_param(debug, int, 0644); + +static char printable(char x) +{ + if (x < 32 || x > 126) + return ' '; + return x; +} + +/*************************************************************************** + * * + * READ * + * * + ***************************************************************************/ + +static int bb_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) +{ + struct bb_priv *priv = board->private_data; + unsigned long flags; + int retval = 0; + + ACT_LED_ON; + SET_DIR_READ(priv); + + dbg_printk(2, "board: %p lock %d length: %zu\n", + board, mutex_is_locked(&board->user_mutex), length); + + priv->end = 0; + priv->count = 0; + priv->rbuf = buffer; + if (length == 0) + goto read_end; + priv->request = length; + priv->eos_check = (priv->eos_flags & REOS) == 0; /* do eos check */ + priv->eos_check_8 = priv->eos_flags & BIN; /* over 8 bits */ + priv->eos_mask_7 = priv->eos & 0x7f; /* with this 7 bit eos */ + + dbg_printk(3, ".........." LINFMT "\n", LINVAL); + + spin_lock_irqsave(&priv->rw_lock, flags); + priv->dav_mode = 1; + priv->dav_rx = 1; + ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_LEVEL_LOW); + priv->end_flag = 0; + gpiod_set_value(NRFD, 1); // ready for data + priv->r_busy = 1; + priv->phase = 100; + spin_unlock_irqrestore(&priv->rw_lock, flags); + + /* wait for the interrupt routines finish their work */ + + retval = wait_event_interruptible(board->wait, + (priv->end_flag || board->status & TIMO)); + + dbg_printk(3, "awake from wait queue: %d\n", retval); + + if (retval == 0 && board->status & TIMO) { + retval = -ETIMEDOUT; + dbg_printk(1, "timeout\n"); + } else if (retval) { + retval = -ERESTARTSYS; + } + + DISABLE_IRQ(priv->irq_DAV); + spin_lock_irqsave(&priv->rw_lock, flags); + gpiod_set_value(NRFD, 0); // DIR_READ line state + priv->r_busy = 0; + spin_unlock_irqrestore(&priv->rw_lock, flags); + +read_end: + ACT_LED_OFF; + *bytes_read = priv->count; + *end = priv->end; + priv->r_busy = 0; + dbg_printk(2, "return: %d eoi|eos: %d count: %d\n\n", retval, priv->end, priv->count); + return retval; +} + +/*************************************************************************** + * * + * READ interrupt routine (DAV line) * + * * + ***************************************************************************/ + +static irqreturn_t bb_DAV_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct bb_priv *priv = board->private_data; + int val; + unsigned long flags; + + spin_lock_irqsave(&priv->rw_lock, flags); + + priv->all_irqs++; + + if (priv->dav_mode) { + ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_EDGE_BOTH); + priv->dav_mode = 0; + } + + if (priv->r_busy == 0) { + dbg_printk(1, "interrupt while idle after %d at %d\n", + priv->count, priv->phase); + priv->dav_idle++; + priv->phase = 200; + goto dav_exit; /* idle */ + } + + val = gpiod_get_value(DAV); + if (val == priv->dav_rx) { + dbg_printk(1, "out of order DAV interrupt %d/%d after %zu/%zu at %d cmd %d " + LINFMT ".\n", val, priv->dav_rx, priv->w_cnt, priv->length, + priv->phase, priv->cmd, LINVAL); + priv->dav_seq++; + } + priv->dav_rx = val; + + dbg_printk(3, "> irq: %d DAV: %d st: %4lx dir: %d busy: %d:%d\n", + irq, val, board->status, priv->direction, priv->r_busy, priv->w_busy); + + if (val == 0) { + gpiod_set_value(NRFD, 0); // not ready for data + priv->rbuf[priv->count++] = get_data_lines(); + priv->end = !gpiod_get_value(EOI); + gpiod_set_value(NDAC, 1); // data accepted + priv->end |= check_for_eos(priv, priv->rbuf[priv->count - 1]); + priv->end_flag = ((priv->count >= priv->request) || priv->end); + priv->phase = 210; + } else { + gpiod_set_value(NDAC, 0); // data not accepted + if (priv->end_flag) { + priv->r_busy = 0; + wake_up_interruptible(&board->wait); + priv->phase = 220; + } else { + gpiod_set_value(NRFD, 1); // ready for data + priv->phase = 230; + } + } + +dav_exit: + spin_unlock_irqrestore(&priv->rw_lock, flags); + dbg_printk(3, "< irq: %d count %d\n", irq, priv->count); + return IRQ_HANDLED; +} + +/*************************************************************************** + * * + * WRITE * + * * + ***************************************************************************/ + +static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + unsigned long flags; + int retval = 0; + + struct bb_priv *priv = board->private_data; + + ACT_LED_ON; + + priv->w_cnt = 0; + priv->w_buf = buffer; + dbg_printk(2, "board %p lock %d length: %zu\n", + board, mutex_is_locked(&board->user_mutex), length); + + if (debug > 1) + bb_buffer_print(buffer, length, priv->cmd, send_eoi); + priv->count = 0; + priv->phase = 300; + + if (length == 0) + goto write_end; + priv->end = send_eoi; + priv->length = length; + + SET_DIR_WRITE(priv); + + dbg_printk(2, "Enabling interrupts - NRFD: %d NDAC: %d\n", + gpiod_get_value(NRFD), gpiod_get_value(NDAC)); + + if (gpiod_get_value(NRFD) && gpiod_get_value(NDAC)) { /* check for listener */ + retval = -ENODEV; + goto write_end; + } + + spin_lock_irqsave(&priv->rw_lock, flags); + priv->w_busy = 1; /* make the interrupt routines active */ + priv->write_done = 0; + priv->nrfd_mode = 1; + priv->ndac_mode = 1; + priv->dav_tx = 1; + ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_LEVEL_HIGH); + ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_LEVEL_HIGH); + spin_unlock_irqrestore(&priv->rw_lock, flags); + + /* wait for the interrupt routines finish their work */ + + retval = wait_event_interruptible(board->wait, + priv->write_done || (board->status & TIMO)); + + dbg_printk(3, "awake from wait queue: %d\n", retval); + + if (retval == 0) { + if (board->status & TIMO) { + retval = -ETIMEDOUT; + dbg_printk(1, "timeout after %zu/%zu at %d " LINFMT " eoi: %d\n", + priv->w_cnt, length, priv->phase, LINVAL, send_eoi); + } else { + // dbg_printk(1,"written %zu\n", priv->w_cnt); + retval = priv->w_cnt; + } + } else { + retval = -ERESTARTSYS; + } + + DISABLE_IRQ(priv->irq_NRFD); + DISABLE_IRQ(priv->irq_NDAC); + + spin_lock_irqsave(&priv->rw_lock, flags); + priv->w_busy = 0; + gpiod_set_value(DAV, 1); // DIR_WRITE line state + gpiod_set_value(EOI, 1); // De-assert EOI (in case) + spin_unlock_irqrestore(&priv->rw_lock, flags); + +write_end: + *bytes_written = priv->w_cnt; + ACT_LED_OFF; + dbg_printk(2, "sent %zu bytes\r\n\r\n", *bytes_written); + priv->phase = 310; + return retval; +} + +/*************************************************************************** + * * + * WRITE interrupt routine (NRFD line) * + * * + ***************************************************************************/ + +static irqreturn_t bb_NRFD_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct bb_priv *priv = board->private_data; + unsigned long flags; + int nrfd; + + spin_lock_irqsave(&priv->rw_lock, flags); + + nrfd = gpiod_get_value(NRFD); + priv->all_irqs++; + + dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n", + irq, nrfd, gpiod_get_value(NDAC), board->status, priv->direction, + priv->w_busy, priv->r_busy); + + if (priv->nrfd_mode) { + ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_EDGE_RISING); + priv->nrfd_mode = 0; + } + + if (priv->w_busy == 0) { + dbg_printk(1, "interrupt while idle after %zu/%zu at %d\n", + priv->w_cnt, priv->length, priv->phase); + priv->nrfd_idle++; + goto nrfd_exit; /* idle */ + } + if (nrfd == 0) { + dbg_printk(1, "out of order interrupt after %zu/%zu at %d cmd %d " LINFMT ".\n", + priv->w_cnt, priv->length, priv->phase, priv->cmd, LINVAL); + priv->phase = 400; + priv->nrfd_seq++; + goto nrfd_exit; + } + if (!priv->dav_tx) { + dbg_printk(1, "DAV low after %zu/%zu cmd %d " LINFMT ". No action.\n", + priv->w_cnt, priv->length, priv->cmd, LINVAL); + priv->dav_seq++; + goto nrfd_exit; + } + + if (priv->atn_asserted && priv->w_cnt >= priv->length) { // test for end of transfer + priv->write_done = 1; + priv->w_busy = 0; + wake_up_interruptible(&board->wait); + goto nrfd_exit; + } + + dbg_printk(3, "sending %zu\n", priv->w_cnt); + + set_data_lines(priv->w_buf[priv->w_cnt++]); // put the data on the lines + + if (priv->w_cnt == priv->length && priv->end) { + dbg_printk(3, "Asserting EOI\n"); + gpiod_set_value(EOI, 0); // Assert EOI + } + + gpiod_set_value(DAV, 0); // Data available + priv->dav_tx = 0; + priv->phase = 410; + +nrfd_exit: + spin_unlock_irqrestore(&priv->rw_lock, flags); + + return IRQ_HANDLED; +} + +/*************************************************************************** + * * + * WRITE interrupt routine (NDAC line) * + * * + ***************************************************************************/ + +static irqreturn_t bb_NDAC_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct bb_priv *priv = board->private_data; + unsigned long flags; + int ndac; + + spin_lock_irqsave(&priv->rw_lock, flags); + + ndac = gpiod_get_value(NDAC); + priv->all_irqs++; + dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n", + irq, gpiod_get_value(NRFD), ndac, board->status, priv->direction, + priv->w_busy, priv->r_busy); + + if (priv->ndac_mode) { + ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_EDGE_RISING); + priv->ndac_mode = 0; + } + + if (priv->w_busy == 0) { + dbg_printk(1, "interrupt while idle.\n"); + priv->ndac_idle++; + goto ndac_exit; + } + if (ndac == 0) { + dbg_printk(1, "out of order interrupt at %zu:%d.\n", priv->w_cnt, priv->phase); + priv->phase = 500; + priv->ndac_seq++; + goto ndac_exit; + } + if (priv->dav_tx) { + dbg_printk(1, "DAV high after %zu/%zu cmd %d " LINFMT ". No action.\n", + priv->w_cnt, priv->length, priv->cmd, LINVAL); + priv->dav_seq++; + goto ndac_exit; + } + + dbg_printk(3, "accepted %zu\n", priv->w_cnt - 1); + + if (!priv->atn_asserted && priv->w_cnt >= priv->length) { // test for end of transfer + priv->write_done = 1; + priv->w_busy = 0; + wake_up_interruptible(&board->wait); + } else { + gpiod_set_value(DAV, 1); // Data not available + priv->dav_tx = 1; + priv->phase = 510; + } + +ndac_exit: + spin_unlock_irqrestore(&priv->rw_lock, flags); + return IRQ_HANDLED; +} + +/*************************************************************************** + * * + * interrupt routine for SRQ line * + * * + ***************************************************************************/ + +static irqreturn_t bb_SRQ_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + + int val = gpiod_get_value(SRQ); + + dbg_printk(3, "> %d st: %4lx\n", val, board->status); + + if (!val) + set_bit(SRQI_NUM, &board->status); /* set_bit() is atomic */ + + wake_up_interruptible(&board->wait); + + return IRQ_HANDLED; +} + +static int bb_command(gpib_board_t *board, uint8_t *buffer, + size_t length, size_t *bytes_written) +{ + size_t ret; + struct bb_priv *priv = board->private_data; + int i; + + dbg_printk(2, "%p %p\n", buffer, board->buffer); + + /* the _ATN line has already been asserted by bb_take_control() */ + + priv->cmd = 1; + + ret = bb_write(board, buffer, length, 0, bytes_written); // no eoi + + for (i = 0; i < length; i++) { + if (buffer[i] == UNT) { + priv->talker_state = talker_idle; + } else { + if (buffer[i] == UNL) { + priv->listener_state = listener_idle; + } else { + if (buffer[i] == (MTA(board->pad))) { + priv->talker_state = talker_addressed; + priv->listener_state = listener_idle; + } else if (buffer[i] == (MLA(board->pad))) { + priv->listener_state = listener_addressed; + priv->talker_state = talker_idle; + } + } + } + } + + /* the _ATN line will be released by bb_go_to_stby */ + + priv->cmd = 0; + + return ret; +} + +/*************************************************************************** + * * + * Buffer print with decode for debug/trace * + * * + ***************************************************************************/ + +static char *cmd_string[32] = { + "", // 0x00 + "GTL", // 0x01 + "", // 0x02 + "", // 0x03 + "SDC", // 0x04 + "PPC", // 0x05 + "", // 0x06 + "", // 0x07 + "GET", // 0x08 + "TCT", // 0x09 + "", // 0x0a + "", // 0x0b + "", // 0x0c + "", // 0x0d + "", // 0x0e + "", // 0x0f + "", // 0x10 + "LLO", // 0x11 + "", // 0x12 + "", // 0x13 + "DCL", // 0x14 + "PPU", // 0x15 + "", // 0x16 + "", // 0x17 + "SPE", // 0x18 + "SPD", // 0x19 + "", // 0x1a + "", // 0x1b + "", // 0x1c + "", // 0x1d + "", // 0x1e + "CFE" // 0x1f +}; + +static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi) +{ + int i; + + if (cmd) { + dbg_printk(2, "<cmd len %zu>\n", length); + for (i = 0; i < length; i++) { + if (buffer[i] < 0x20) { + dbg_printk(3, "0x%x=%s\n", buffer[i], cmd_string[buffer[i]]); + } else if (buffer[i] == 0x3f) { + dbg_printk(3, "0x%x=%s\n", buffer[i], "UNL"); + } else if (buffer[i] == 0x5f) { + dbg_printk(3, "0x%x=%s\n", buffer[i], "UNT"); + } else if (buffer[i] < 0x60) { + dbg_printk(3, "0x%x=%s%d\n", buffer[i], + (buffer[i] & 0x40) ? "TLK" : "LSN", buffer[i] & 0x1F); + } else { + dbg_printk(3, "0x%x\n", buffer[i]); + } + } + } else { + dbg_printk(2, "<data len %zu %s>\n", length, (eoi) ? "w.EOI" : " "); + for (i = 0; i < length; i++) + dbg_printk(2, "%3d 0x%x->%c\n", i, buffer[i], printable(buffer[i])); + } +} + +/*************************************************************************** + * * + * STATUS Management * + * * + ***************************************************************************/ +static void set_atn(struct bb_priv *priv, int atn_asserted) +{ + if (priv->listener_state != listener_idle && + priv->talker_state != talker_idle) { + dbg_printk(0, "listener/talker state machine conflict\n"); + } + if (atn_asserted) { + if (priv->listener_state == listener_active) + priv->listener_state = listener_addressed; + if (priv->talker_state == talker_active) + priv->talker_state = talker_addressed; + } else { + if (priv->listener_state == listener_addressed) { + priv->listener_state = listener_active; + SET_DIR_READ(priv); // make sure holdoff is active when we unassert ATN + } + if (priv->talker_state == talker_addressed) + priv->talker_state = talker_active; + } + gpiod_direction_output(_ATN, !atn_asserted); + priv->atn_asserted = atn_asserted; +} + +static int bb_take_control(gpib_board_t *board, int synchronous) +{ + dbg_printk(2, "%d\n", synchronous); + set_atn(board->private_data, 1); + set_bit(CIC_NUM, &board->status); + return 0; +} + +static int bb_go_to_standby(gpib_board_t *board) +{ + dbg_printk(2, "\n"); + set_atn(board->private_data, 0); + return 0; +} + +static void bb_request_system_control(gpib_board_t *board, int request_control) +{ + dbg_printk(2, "%d\n", request_control); + if (request_control) { + set_bit(CIC_NUM, &board->status); + // drive DAV & EOI false, enable NRFD & NDAC irqs + SET_DIR_WRITE(board->private_data); + } else { + clear_bit(CIC_NUM, &board->status); + } +} + +static void bb_interface_clear(gpib_board_t *board, int assert) +{ + struct bb_priv *priv = board->private_data; + + dbg_printk(2, "%d\n", assert); + if (assert) { + gpiod_direction_output(IFC, 0); + priv->talker_state = talker_idle; + priv->listener_state = listener_idle; + } else { + gpiod_direction_output(IFC, 1); + } +} + +static void bb_remote_enable(gpib_board_t *board, int enable) +{ + dbg_printk(2, "%d\n", enable); + if (enable) { + set_bit(REM_NUM, &board->status); + gpiod_direction_output(REN, 0); + } else { + clear_bit(REM_NUM, &board->status); + gpiod_direction_output(REN, 1); + } +} + +static int bb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct bb_priv *priv = board->private_data; + + dbg_printk(2, "%s\n", "EOS_en"); + priv->eos = eos_byte; + priv->eos_flags = REOS; + if (compare_8_bits) + priv->eos_flags |= BIN; + + return 0; +} + +static void bb_disable_eos(gpib_board_t *board) +{ + struct bb_priv *priv = board->private_data; + + dbg_printk(2, "\n"); + priv->eos_flags &= ~REOS; +} + +static unsigned int bb_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct bb_priv *priv = board->private_data; + + board->status &= ~clear_mask; + + if (gpiod_get_value(SRQ)) /* SRQ asserted low */ + clear_bit(SRQI_NUM, &board->status); + else + set_bit(SRQI_NUM, &board->status); + if (gpiod_get_value(_ATN)) /* ATN asserted low */ + clear_bit(ATN_NUM, &board->status); + else + set_bit(ATN_NUM, &board->status); + if (priv->talker_state == talker_active || + priv->talker_state == talker_addressed) + set_bit(TACS_NUM, &board->status); + else + clear_bit(TACS_NUM, &board->status); + + if (priv->listener_state == listener_active || + priv->listener_state == listener_addressed) + set_bit(LACS_NUM, &board->status); + else + clear_bit(LACS_NUM, &board->status); + + dbg_printk(2, "0x%lx mask 0x%x\n", board->status, clear_mask); + + return board->status; +} + +static int bb_primary_address(gpib_board_t *board, unsigned int address) +{ + dbg_printk(2, "%d\n", address); + board->pad = address; + return 0; +} + +static int bb_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + dbg_printk(2, "%d %d\n", address, enable); + if (enable) + board->sad = address; + return 0; +} + +static int bb_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + dbg_printk(1, "%s\n", "not implemented"); + return -EPERM; +} + +static void bb_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + dbg_printk(1, "%s\n", "not implemented"); +} + +static void bb_parallel_poll_response(gpib_board_t *board, int ist) +{ +} + +static void bb_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + dbg_printk(1, "%s\n", "not implemented"); +} + +static uint8_t bb_serial_poll_status(gpib_board_t *board) +{ + dbg_printk(1, "%s\n", "not implemented"); + return 0; // -ENOSYS; +} + +static unsigned int bb_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct bb_priv *priv = board->private_data; + + if (nano_sec <= 350) + priv->t1_delay = 350; + else if (nano_sec <= 1100) + priv->t1_delay = 1100; + else + priv->t1_delay = 2000; + + dbg_printk(2, "t1 delay set to %d nanosec\n", priv->t1_delay); + + return priv->t1_delay; +} + +static void bb_return_to_local(gpib_board_t *board) +{ + dbg_printk(1, "%s\n", "not implemented"); +} + +static int bb_line_status(const gpib_board_t *board) +{ + int line_status = ValidALL; + +// dbg_printk(1,"\n"); + + if (gpiod_get_value(REN) == 0) + line_status |= BusREN; + if (gpiod_get_value(IFC) == 0) + line_status |= BusIFC; + if (gpiod_get_value(NDAC) == 0) + line_status |= BusNDAC; + if (gpiod_get_value(NRFD) == 0) + line_status |= BusNRFD; + if (gpiod_get_value(DAV) == 0) + line_status |= BusDAV; + if (gpiod_get_value(EOI) == 0) + line_status |= BusEOI; + if (gpiod_get_value(_ATN) == 0) + line_status |= BusATN; + if (gpiod_get_value(SRQ) == 0) + line_status |= BusSRQ; + + dbg_printk(2, "status lines: %4x\n", line_status); + + return line_status; +} + +/*************************************************************************** + * * + * Module Management * + * * + ***************************************************************************/ + +static int allocate_private(gpib_board_t *board) +{ + board->private_data = kzalloc(sizeof(struct bb_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + return 0; +} + +static void free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static int bb_get_irq(gpib_board_t *board, char *name, + struct gpio_desc *gpio, int *irq, + irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags) +{ + if (!gpio) + return -1; + gpiod_direction_input(gpio); + *irq = gpiod_to_irq(gpio); + dbg_printk(2, "IRQ %s: %d\n", name, *irq); + if (*irq < 0) { + dbg_printk(0, "gpib: can't get IRQ for %s\n", name); + return -1; + } + if (request_threaded_irq(*irq, handler, thread_fn, flags, name, board)) { + dbg_printk(0, "gpib: can't request IRQ for %s %d\n", name, *irq); + *irq = 0; + return -1; + } + DISABLE_IRQ(*irq); + return 0; +} + +static void bb_free_irq(gpib_board_t *board, int *irq, char *name) +{ + if (*irq) { + free_irq(*irq, board); + dbg_printk(2, "IRQ %d(%s) freed\n", *irq, name); + *irq = 0; + } +} + +static void release_gpios(void) +{ + int j; + + for (j = 0 ; j < NUM_PINS ; j++) { + if (all_descriptors[j]) { + gpiod_put(all_descriptors[j]); + all_descriptors[j] = 0; + } + } +} + +static int allocate_gpios(gpib_board_t *board) +{ + int j, retval = 0; + bool error = false; + int table_index = 0; + char name[256]; + struct gpio_desc *desc; + struct gpiod_lookup_table *lookup_table; + + if (!board->gpib_dev) { + pr_err("NULL gpib dev for board\n"); + return -ENOENT; + } + + lookup_table = lookup_tables[0]; + lookup_table->dev_id = dev_name(board->gpib_dev); + gpiod_add_lookup_table(lookup_table); + dbg_printk(1, "Allocating gpios using table index %d\n", table_index); + + for (j = 0 ; j < NUM_PINS ; j++) { + if (gpios_vector[j] < 0) + continue; + /* name not really used in gpiod_get_index() */ + sprintf(name, "GPIO%d", gpios_vector[j]); +try_again: + dbg_printk(1, "Allocating gpio %s pin no %d\n", name, gpios_vector[j]); + desc = gpiod_get_index(board->gpib_dev, name, gpios_vector[j], GPIOD_IN); + + if (IS_ERR(desc)) { + gpiod_remove_lookup_table(lookup_table); + table_index++; + lookup_table = lookup_tables[table_index]; + if (lookup_table) { + dbg_printk(1, "Allocation failed, now using table_index %d\n", + table_index); + lookup_table->dev_id = dev_name(board->gpib_dev); + gpiod_add_lookup_table(lookup_table); + goto try_again; + } + dbg_printk(0, "Unable to obtain gpio descriptor for pin %d error %ld\n", + gpios_vector[j], PTR_ERR(desc)); + error = true; + break; + } + all_descriptors[j] = desc; + } + + if (error) { /* undo what already done */ + release_gpios(); + retval = -1; + } + if (lookup_table) + gpiod_remove_lookup_table(lookup_table); + // Initialize LED trigger + led_trigger_register_simple("gpib", &ledtrig_gpib); + return retval; +} + +static void bb_detach(gpib_board_t *board) +{ + struct bb_priv *priv = board->private_data; + + dbg_printk(2, "Enter with data %p\n", board->private_data); + if (!board->private_data) + return; + + led_trigger_unregister_simple(ledtrig_gpib); + + bb_free_irq(board, &priv->irq_DAV, NAME "_DAV"); + bb_free_irq(board, &priv->irq_NRFD, NAME "_NRFD"); + bb_free_irq(board, &priv->irq_NDAC, NAME "_NDAC"); + bb_free_irq(board, &priv->irq_SRQ, NAME "_SRQ"); + + if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */ + gpiod_set_value(YOGA_ENABLE, 0); + } + + release_gpios(); + + dbg_printk(2, "detached board: %d\n", board->minor); + dbg_printk(0, "NRFD: idle %d, seq %d, NDAC: idle %d, seq %d DAV: idle %d seq: %d all: %ld", + priv->nrfd_idle, priv->nrfd_seq, + priv->ndac_idle, priv->ndac_seq, + priv->dav_idle, priv->dav_seq, priv->all_irqs); + + free_private(board); +} + +static int bb_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct bb_priv *priv; + int retval = 0; + + dbg_printk(2, "%s\n", "Enter ..."); + + board->status = 0; + + if (allocate_private(board)) + return -ENOMEM; + priv = board->private_data; + priv->direction = -1; + priv->t1_delay = 2000; + priv->listener_state = listener_idle; + priv->talker_state = talker_idle; + + sn7516x = sn7516x_used; + if (strcmp(PINMAP_0, pin_map) == 0) { + if (!sn7516x) { + gpios_vector[&(PE) - &all_descriptors[0]] = -1; + gpios_vector[&(DC) - &all_descriptors[0]] = -1; + gpios_vector[&(TE) - &all_descriptors[0]] = -1; + } + } else if (strcmp(PINMAP_1, pin_map) == 0) { + if (!sn7516x) { + gpios_vector[&(PE) - &all_descriptors[0]] = -1; + gpios_vector[&(DC) - &all_descriptors[0]] = -1; + gpios_vector[&(TE) - &all_descriptors[0]] = -1; + } + gpios_vector[&(REN) - &all_descriptors[0]] = 0; /* 27 -> 0 REN on GPIB pin 0 */ + } else if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */ + sn7516x = 0; + gpios_vector[&(D03) - &all_descriptors[0]] = YOGA_D03_pin_nr; + gpios_vector[&(D04) - &all_descriptors[0]] = YOGA_D04_pin_nr; + gpios_vector[&(D05) - &all_descriptors[0]] = YOGA_D05_pin_nr; + gpios_vector[&(D06) - &all_descriptors[0]] = YOGA_D06_pin_nr; + gpios_vector[&(PE) - &all_descriptors[0]] = -1; + gpios_vector[&(DC) - &all_descriptors[0]] = -1; + gpios_vector[&(ACT_LED) - &all_descriptors[0]] = -1; + } else { + dbg_printk(0, "Unrecognized pin mapping.\n"); + goto bb_attach_fail; + } + dbg_printk(0, "Using pin map \"%s\" %s\n", pin_map, (sn7516x) ? + " with SN7516x driver support" : ""); + + if (allocate_gpios(board)) + goto bb_attach_fail; + +/* Configure SN7516X control lines. + * drive ATN, IFC and REN as outputs only when master + * i.e. system controller. In this mode can only be the CIC + * When not master then enable device mode ATN, IFC & REN as inputs + */ + if (sn7516x) { + gpiod_direction_output(DC, 0); + gpiod_direction_output(TE, 1); + gpiod_direction_output(PE, 1); + } + + if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA: enable level shifters */ + gpiod_direction_output(YOGA_ENABLE, 1); + } + + spin_lock_init(&priv->rw_lock); + + /* request DAV interrupt for read */ + if (bb_get_irq(board, NAME "_DAV", DAV, &priv->irq_DAV, bb_DAV_interrupt, NULL, + IRQF_TRIGGER_NONE)) + goto bb_attach_fail_r; + + /* request NRFD interrupt for write */ + if (bb_get_irq(board, NAME "_NRFD", NRFD, &priv->irq_NRFD, bb_NRFD_interrupt, NULL, + IRQF_TRIGGER_NONE)) + goto bb_attach_fail_r; + + /* request NDAC interrupt for write */ + if (bb_get_irq(board, NAME "_NDAC", NDAC, &priv->irq_NDAC, bb_NDAC_interrupt, NULL, + IRQF_TRIGGER_NONE)) + goto bb_attach_fail_r; + + /* request SRQ interrupt for Service Request */ + if (bb_get_irq(board, NAME "_SRQ", SRQ, &priv->irq_SRQ, bb_SRQ_interrupt, NULL, + IRQF_TRIGGER_NONE)) + goto bb_attach_fail_r; + + ENABLE_IRQ(priv->irq_SRQ, IRQ_TYPE_EDGE_FALLING); + + dbg_printk(0, "attached board %d\n", board->minor); + goto bb_attach_out; + +bb_attach_fail_r: + release_gpios(); +bb_attach_fail: + retval = -1; +bb_attach_out: + return retval; +} + +gpib_interface_t bb_interface = { +name: NAME, +attach : bb_attach, +detach : bb_detach, +read : bb_read, +write : bb_write, +command : bb_command, +take_control : bb_take_control, +go_to_standby : bb_go_to_standby, +request_system_control : bb_request_system_control, +interface_clear : bb_interface_clear, +remote_enable : bb_remote_enable, +enable_eos : bb_enable_eos, +disable_eos : bb_disable_eos, +parallel_poll : bb_parallel_poll, +parallel_poll_configure : bb_parallel_poll_configure, +parallel_poll_response : bb_parallel_poll_response, +line_status : bb_line_status, +update_status : bb_update_status, +primary_address : bb_primary_address, +secondary_address : bb_secondary_address, +serial_poll_response : bb_serial_poll_response, +serial_poll_status : bb_serial_poll_status, +t1_delay : bb_t1_delay, +return_to_local : bb_return_to_local, +}; + +static int __init bb_init_module(void) +{ + gpib_register_driver(&bb_interface, THIS_MODULE); + + dbg_printk(0, "module loaded with pin map \"%s\"%s\n", + pin_map, (sn7516x_used) ? " and SN7516x driver support" : ""); + return 0; +} + +static void __exit bb_exit_module(void) +{ + dbg_printk(0, "module unloaded!"); + + gpib_unregister_driver(&bb_interface); +} + +module_init(bb_init_module); +module_exit(bb_exit_module); + +/*************************************************************************** + * * + * UTILITY Functions * + * * + ***************************************************************************/ +inline long usec_diff(struct timespec64 *a, struct timespec64 *b) +{ + return ((a->tv_sec - b->tv_sec) * 1000000 + + (a->tv_nsec - b->tv_nsec) / 1000); +} + +static inline int check_for_eos(struct bb_priv *priv, uint8_t byte) +{ + if (priv->eos_check) + return 0; + + if (priv->eos_check_8) { + if (priv->eos == byte) + return 1; + } else { + if (priv->eos_mask_7 == (byte & 0x7f)) + return 1; + } + return 0; +} + +static void set_data_lines_output(void) +{ + gpiod_direction_output(D01, 1); + gpiod_direction_output(D02, 1); + gpiod_direction_output(D03, 1); + gpiod_direction_output(D04, 1); + gpiod_direction_output(D05, 1); + gpiod_direction_output(D06, 1); + gpiod_direction_output(D07, 1); + gpiod_direction_output(D08, 1); +} + +static void set_data_lines(u8 byte) +{ + gpiod_set_value(D01, !(byte & 0x01)); + gpiod_set_value(D02, !(byte & 0x02)); + gpiod_set_value(D03, !(byte & 0x04)); + gpiod_set_value(D04, !(byte & 0x08)); + gpiod_set_value(D05, !(byte & 0x10)); + gpiod_set_value(D06, !(byte & 0x20)); + gpiod_set_value(D07, !(byte & 0x40)); + gpiod_set_value(D08, !(byte & 0x80)); +} + +static u8 get_data_lines(void) +{ + u8 ret; + + ret = gpiod_get_value(D01); + ret |= gpiod_get_value(D02) << 1; + ret |= gpiod_get_value(D03) << 2; + ret |= gpiod_get_value(D04) << 3; + ret |= gpiod_get_value(D05) << 4; + ret |= gpiod_get_value(D06) << 5; + ret |= gpiod_get_value(D07) << 6; + ret |= gpiod_get_value(D08) << 7; + return ~ret; +} + +static void set_data_lines_input(void) +{ + gpiod_direction_input(D01); + gpiod_direction_input(D02); + gpiod_direction_input(D03); + gpiod_direction_input(D04); + gpiod_direction_input(D05); + gpiod_direction_input(D06); + gpiod_direction_input(D07); + gpiod_direction_input(D08); +} + +static inline void SET_DIR_WRITE(struct bb_priv *priv) +{ + if (priv->direction == DIR_WRITE) + return; + + gpiod_direction_input(NRFD); + gpiod_direction_input(NDAC); + set_data_lines_output(); + gpiod_direction_output(DAV, 1); + gpiod_direction_output(EOI, 1); + + if (sn7516x) { + gpiod_set_value(PE, 1); /* set data lines to transmit on sn75160b */ + gpiod_set_value(TE, 1); /* set NDAC and NRFD to receive and DAV to transmit */ + } + + priv->direction = DIR_WRITE; +} + +static inline void SET_DIR_READ(struct bb_priv *priv) +{ + if (priv->direction == DIR_READ) + return; + + gpiod_direction_input(DAV); + gpiod_direction_input(EOI); + + set_data_lines_input(); + + if (sn7516x) { + gpiod_set_value(PE, 0); /* set data lines to receive on sn75160b */ + gpiod_set_value(TE, 0); /* set NDAC and NRFD to transmit and DAV to receive */ + } + + gpiod_direction_output(NRFD, 0); // hold off the talker + gpiod_direction_output(NDAC, 0); // data not accepted + + priv->direction = DIR_READ; +} diff --git a/drivers/staging/gpib/hp_82335/Makefile b/drivers/staging/gpib/hp_82335/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8b7a552e935566bfe7085bf76f49e47244a339d6 --- /dev/null +++ b/drivers/staging/gpib/hp_82335/Makefile @@ -0,0 +1,4 @@ + +obj-m += hp82335.o + + diff --git a/drivers/staging/gpib/hp_82335/hp82335.c b/drivers/staging/gpib/hp_82335/hp82335.c new file mode 100644 index 0000000000000000000000000000000000000000..40afe42aea4788ad9683e71cc9205a42b7f0abb9 --- /dev/null +++ b/drivers/staging/gpib/hp_82335/hp82335.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess * + ***************************************************************************/ + +/*should enable ATN interrupts (and update board->status on occurrence), + * implement recovery from bus errors (if necessary) + */ + +#include "hp82335.h" +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/init.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for HP 82335 interface cards"); + +static int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void hp82335_detach(gpib_board_t *board); + +// wrappers for interface functions +int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); +} + +int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); +} + +int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); +} + +int hp82335_take_control(gpib_board_t *board, int synchronous) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_take_control(board, &priv->tms9914_priv, synchronous); +} + +int hp82335_go_to_standby(gpib_board_t *board) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_go_to_standby(board, &priv->tms9914_priv); +} + +void hp82335_request_system_control(gpib_board_t *board, int request_control) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_request_system_control(board, &priv->tms9914_priv, request_control); +} + +void hp82335_interface_clear(gpib_board_t *board, int assert) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_interface_clear(board, &priv->tms9914_priv, assert); +} + +void hp82335_remote_enable(gpib_board_t *board, int enable) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_remote_enable(board, &priv->tms9914_priv, enable); +} + +int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); +} + +void hp82335_disable_eos(gpib_board_t *board) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_disable_eos(board, &priv->tms9914_priv); +} + +unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); +} + +int hp82335_primary_address(gpib_board_t *board, unsigned int address) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_primary_address(board, &priv->tms9914_priv, address); +} + +int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); +} + +int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_parallel_poll(board, &priv->tms9914_priv, result); +} + +void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); +} + +void hp82335_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); +} + +void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_serial_poll_response(board, &priv->tms9914_priv, status); +} + +static uint8_t hp82335_serial_poll_status(gpib_board_t *board) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_serial_poll_status(board, &priv->tms9914_priv); +} + +static int hp82335_line_status(const gpib_board_t *board) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_line_status(board, &priv->tms9914_priv); +} + +static unsigned int hp82335_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct hp82335_priv *priv = board->private_data; + + return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec); +} + +void hp82335_return_to_local(gpib_board_t *board) +{ + struct hp82335_priv *priv = board->private_data; + + tms9914_return_to_local(board, &priv->tms9914_priv); +} + +gpib_interface_t hp82335_interface = { +name: "hp82335", +attach : hp82335_attach, +detach : hp82335_detach, +read : hp82335_read, +write : hp82335_write, +command : hp82335_command, +request_system_control : hp82335_request_system_control, +take_control : hp82335_take_control, +go_to_standby : hp82335_go_to_standby, +interface_clear : hp82335_interface_clear, +remote_enable : hp82335_remote_enable, +enable_eos : hp82335_enable_eos, +disable_eos : hp82335_disable_eos, +parallel_poll : hp82335_parallel_poll, +parallel_poll_configure : hp82335_parallel_poll_configure, +parallel_poll_response : hp82335_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : hp82335_line_status, +update_status : hp82335_update_status, +primary_address : hp82335_primary_address, +secondary_address : hp82335_secondary_address, +serial_poll_response : hp82335_serial_poll_response, +serial_poll_status : hp82335_serial_poll_status, +t1_delay : hp82335_t1_delay, +return_to_local : hp82335_return_to_local, +}; + +int hp82335_allocate_private(gpib_board_t *board) +{ + board->private_data = kzalloc(sizeof(struct hp82335_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + return 0; +} + +void hp82335_free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static inline unsigned int tms9914_to_hp82335_offset(unsigned int register_num) +{ + return 0x1ff8 + register_num; +} + +static uint8_t hp82335_read_byte(struct tms9914_priv *priv, unsigned int register_num) +{ + return tms9914_iomem_read_byte(priv, tms9914_to_hp82335_offset(register_num)); +} + +static void hp82335_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num) +{ + tms9914_iomem_write_byte(priv, data, tms9914_to_hp82335_offset(register_num)); +} + +static void hp82335_clear_interrupt(struct hp82335_priv *hp_priv) +{ + struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; + + writeb(0, tms_priv->iobase + HPREG_INTR_CLEAR); +} + +int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct hp82335_priv *hp_priv; + struct tms9914_priv *tms_priv; + int retval; + const unsigned long upper_iomem_base = (unsigned long)config->ibbase + hp82335_rom_size; + + board->status = 0; + + if (hp82335_allocate_private(board)) + return -ENOMEM; + hp_priv = board->private_data; + tms_priv = &hp_priv->tms9914_priv; + tms_priv->read_byte = hp82335_read_byte; + tms_priv->write_byte = hp82335_write_byte; + tms_priv->offset = 1; + + switch ((unsigned long)(config->ibbase)) { + case 0xc4000: + case 0xc8000: + case 0xcc000: + case 0xd0000: + case 0xd4000: + case 0xd8000: + case 0xdc000: + case 0xe0000: + case 0xe4000: + case 0xe8000: + case 0xec000: + case 0xf0000: + case 0xf4000: + case 0xf8000: + case 0xfc000: + break; + default: + pr_err("hp82335: invalid base io address 0x%p\n", config->ibbase); + return -EINVAL; + } + if (!request_mem_region(upper_iomem_base, hp82335_upper_iomem_size, "hp82335")) { + pr_err("hp82335: failed to allocate io memory region 0x%lx-0x%lx\n", + upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1); + return -EBUSY; + } + hp_priv->raw_iobase = upper_iomem_base; + tms_priv->iobase = ioremap(upper_iomem_base, hp82335_upper_iomem_size); + pr_info("hp82335: upper half of 82335 iomem region 0x%lx remapped to 0x%p\n", + hp_priv->raw_iobase, tms_priv->iobase); + + retval = request_irq(config->ibirq, hp82335_interrupt, 0, "hp82335", board); + if (retval) { + pr_err("hp82335: can't request IRQ %d\n", config->ibirq); + return retval; + } + hp_priv->irq = config->ibirq; + pr_info("hp82335: IRQ %d\n", config->ibirq); + + tms9914_board_reset(tms_priv); + + hp82335_clear_interrupt(hp_priv); + + writeb(INTR_ENABLE, tms_priv->iobase + HPREG_CCR); + + tms9914_online(board, tms_priv); + + return 0; +} + +void hp82335_detach(gpib_board_t *board) +{ + struct hp82335_priv *hp_priv = board->private_data; + struct tms9914_priv *tms_priv; + + if (hp_priv) { + tms_priv = &hp_priv->tms9914_priv; + if (hp_priv->irq) + free_irq(hp_priv->irq, board); + if (tms_priv->iobase) { + writeb(0, tms_priv->iobase + HPREG_CCR); + tms9914_board_reset(tms_priv); + iounmap((void *)tms_priv->iobase); + } + if (hp_priv->raw_iobase) + release_mem_region(hp_priv->raw_iobase, hp82335_upper_iomem_size); + } + hp82335_free_private(board); +} + +static int __init hp82335_init_module(void) +{ + gpib_register_driver(&hp82335_interface, THIS_MODULE); + return 0; +} + +static void __exit hp82335_exit_module(void) +{ + gpib_unregister_driver(&hp82335_interface); +} + +module_init(hp82335_init_module); +module_exit(hp82335_exit_module); + +/* + * GPIB interrupt service routines + */ + +irqreturn_t hp82335_interrupt(int irq, void *arg) +{ + int status1, status2; + gpib_board_t *board = arg; + struct hp82335_priv *priv = board->private_data; + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + status1 = read_byte(&priv->tms9914_priv, ISR0); + status2 = read_byte(&priv->tms9914_priv, ISR1); + hp82335_clear_interrupt(priv); + retval = tms9914_interrupt_have_status(board, &priv->tms9914_priv, status1, status2); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + diff --git a/drivers/staging/gpib/hp_82335/hp82335.h b/drivers/staging/gpib/hp_82335/hp82335.h new file mode 100644 index 0000000000000000000000000000000000000000..5e5297af731ae24a69942047ffba032c5ad88474 --- /dev/null +++ b/drivers/staging/gpib/hp_82335/hp82335.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess * + ***************************************************************************/ + +#ifndef _HP82335_H +#define _HP82335_H + +#include "tms9914.h" +#include "gpibP.h" + +// struct which defines private_data for board +struct hp82335_priv { + struct tms9914_priv tms9914_priv; + unsigned int irq; + unsigned long raw_iobase; +}; + +// interfaces +extern gpib_interface_t hp82335_interface; + +// interface functions +int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); +int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); +int hp82335_take_control(gpib_board_t *board, int synchronous); +int hp82335_go_to_standby(gpib_board_t *board); +void hp82335_request_system_control(gpib_board_t *board, int request_control); +void hp82335_interface_clear(gpib_board_t *board, int assert); +void hp82335_remote_enable(gpib_board_t *board, int enable); +int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int + compare_8_bits); +void hp82335_disable_eos(gpib_board_t *board); +unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask); +int hp82335_primary_address(gpib_board_t *board, unsigned int address); +int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int + enable); +int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result); +void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config); +void hp82335_parallel_poll_response(gpib_board_t *board, int ist); +void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status); +void hp82335_return_to_local(gpib_board_t *board); + +// interrupt service routines +irqreturn_t hp82335_interrupt(int irq, void *arg); + +// utility functions +int hp82335_allocate_private(gpib_board_t *board); +void hp82335_free_private(gpib_board_t *board); + +// size of io memory region used +static const int hp82335_rom_size = 0x2000; +static const int hp82335_upper_iomem_size = 0x2000; + +// hp82335 register offsets +enum hp_read_regs { + HPREG_CSR = 0x17f8, + HPREG_STATUS = 0x1ffc, +}; + +enum hp_write_regs { + HPREG_INTR_CLEAR = 0x17f7, + HPREG_CCR = HPREG_CSR, +}; + +enum ccr_bits { + DMA_ENABLE = (1 << 0), /* DMA enable */ + DMA_CHAN_SELECT = (1 << 1), /* DMA channel select O=3,1=2 */ + INTR_ENABLE = (1 << 2), /* interrupt enable */ + SYS_DISABLE = (1 << 3), /* system controller disable */ +}; + +enum csr_bits { + SWITCH6 = (1 << 0), /* switch 6 position */ + SWITCH5 = (1 << 1), /* switch 5 position */ + SYS_CONTROLLER = (1 << 2), /* system controller bit */ + DMA_ENABLE_STATUS = (1 << 4), /* DMA enabled */ + DMA_CHAN_STATUS = (1 << 5), /* DMA channel 0=3,1=2 */ + INTR_ENABLE_STATUS = (1 << 6), /* Interrupt enable */ + INTR_PENDING = (1 << 7), /* Interrupt Pending */ +}; + +#endif // _HP82335_H diff --git a/drivers/staging/gpib/hp_82341/Makefile b/drivers/staging/gpib/hp_82341/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1fe7db4f8ca4733c85b10c841644fbcb0fdae5a9 --- /dev/null +++ b/drivers/staging/gpib/hp_82341/Makefile @@ -0,0 +1,2 @@ + +obj-m += hp_82341.o diff --git a/drivers/staging/gpib/hp_82341/hp_82341.c b/drivers/staging/gpib/hp_82341/hp_82341.c new file mode 100644 index 0000000000000000000000000000000000000000..8ad1c885a9fb60aae9035e555830706275a26900 --- /dev/null +++ b/drivers/staging/gpib/hp_82341/hp_82341.c @@ -0,0 +1,895 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * Driver for hp 82341a/b/c/d boards. * + * Might be worth merging with Agilent 82350b driver. * + * copyright : (C) 2002, 2005 by Frank Mori Hess * + ***************************************************************************/ + +#include "hp_82341.h" +#include <linux/delay.h> +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/isapnp.h> + +MODULE_LICENSE("GPL"); + +int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) +{ + struct hp_82341_priv *hp_priv = board->private_data; + struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; + int retval = 0; + unsigned short event_status; + int i; + int num_fifo_bytes; + //hardware doesn't support checking for end-of-string character when using fifo + if (tms_priv->eos_flags & REOS) + return tms9914_read(board, tms_priv, buffer, length, end, bytes_read); + + clear_bit(DEV_CLEAR_BN, &tms_priv->state); + + read_and_clear_event_status(board); + *end = 0; + *bytes_read = 0; + if (length == 0) + return 0; + //disable fifo for the moment + outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); + // Handle corner case of board not in holdoff and one byte has slipped in already. + // Also, board sometimes has problems (spurious 1 byte reads) when read fifo is + // started up with board in + // TACS under certain data holdoff conditions. Doing a 1 byte tms9914-style + // read avoids these problems. + if (/*tms_priv->holdoff_active == 0 && */length > 1) { + size_t num_bytes; + + retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + pr_err("tms9914_read failed retval=%i\n", retval); + if (retval < 0 || *end) + return retval; + ++buffer; + --length; + } + tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI); + tms9914_release_holdoff(tms_priv); + outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG); + i = 0; + num_fifo_bytes = length - 1; + while (i < num_fifo_bytes && *end == 0) { + int block_size; + int j; + int count; + + if (num_fifo_bytes - i < hp_82341_fifo_size) + block_size = num_fifo_bytes - i; + else + block_size = hp_82341_fifo_size; + set_transfer_counter(hp_priv, block_size); + outb(ENABLE_TI_BUFFER_BIT | DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + + BUFFER_CONTROL_REG); + if (inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT) + outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG); + + clear_bit(READ_READY_BN, &tms_priv->state); + + retval = wait_event_interruptible(board->wait, + ((event_status = + read_and_clear_event_status(board)) & + (TERMINAL_COUNT_EVENT_BIT | + BUFFER_END_EVENT_BIT)) || + test_bit(DEV_CLEAR_BN, &tms_priv->state) || + test_bit(TIMO_NUM, &board->status)); + if (retval) { + pr_warn("%s: read wait interrupted\n", __func__); + retval = -ERESTARTSYS; + break; + } + // have to disable buffer before we can read from buffer port + outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); + count = block_size - read_transfer_counter(hp_priv); + j = 0; + while (j < count && i < num_fifo_bytes) { + unsigned short data_word = inw(hp_priv->iobase[3] + BUFFER_PORT_LOW_REG); + + buffer[i++] = data_word & 0xff; + ++j; + if (j < count && i < num_fifo_bytes) { + buffer[i++] = (data_word >> 8) & 0xff; + ++j; + } + } + if (event_status & BUFFER_END_EVENT_BIT) { + clear_bit(RECEIVED_END_BN, &tms_priv->state); + + *end = 1; + tms_priv->holdoff_active = 1; + } + if (test_bit(TIMO_NUM, &board->status)) { + pr_debug("%s: minor %i: read timed out\n", __FILE__, board->minor); + retval = -ETIMEDOUT; + break; + } + if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { + pr_warn("%s: device clear interrupted read\n", __FILE__); + retval = -EINTR; + break; + } + } + *bytes_read += i; + buffer += i; + length -= i; + if (retval < 0) + return retval; + // read last byte if we havn't received an END yet + if (*end == 0) { + size_t num_bytes; + // try to make sure we holdoff after last byte read + retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + return retval; + } + return 0; +} + +static int restart_write_fifo(gpib_board_t *board, struct hp_82341_priv *hp_priv) +{ + struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; + + if ((inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT) == 0) + return 0; + while (1) { + int status; + + //restart doesn't work if data holdoff is in effect + status = tms9914_line_status(board, tms_priv); + if ((status & BusNRFD) == 0) { + outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG); + return 0; + } + if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) + return -EINTR; + if (test_bit(TIMO_NUM, &board->status)) + return -ETIMEDOUT; + if (msleep_interruptible(1)) + return -EINTR; + } + return 0; +} + +int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + struct hp_82341_priv *hp_priv = board->private_data; + struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; + int i, j; + unsigned short event_status; + int retval = 0; + int fifo_xfer_len = length; + + *bytes_written = 0; + if (send_eoi) + --fifo_xfer_len; + + clear_bit(DEV_CLEAR_BN, &tms_priv->state); + + read_and_clear_event_status(board); + outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG); + outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG); + for (i = 0; i < fifo_xfer_len;) { + int block_size; + + if (fifo_xfer_len - i < hp_82341_fifo_size) + block_size = fifo_xfer_len - i; + else + block_size = hp_82341_fifo_size; + set_transfer_counter(hp_priv, block_size); + // load data into board's fifo + for (j = 0; j < block_size;) { + unsigned short data_word = buffer[i++]; + ++j; + if (j < block_size) { + data_word |= buffer[i++] << 8; + ++j; + } + outw(data_word, hp_priv->iobase[3] + BUFFER_PORT_LOW_REG); + } + clear_bit(WRITE_READY_BN, &tms_priv->state); + outb(ENABLE_TI_BUFFER_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); + retval = restart_write_fifo(board, hp_priv); + if (retval < 0) { + pr_err("hp82341: failed to restart write stream\n"); + break; + } + retval = wait_event_interruptible(board->wait, + ((event_status = + read_and_clear_event_status(board)) & + TERMINAL_COUNT_EVENT_BIT) || + test_bit(DEV_CLEAR_BN, &tms_priv->state) || + test_bit(TIMO_NUM, &board->status)); + outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG); + *bytes_written += block_size - read_transfer_counter(hp_priv); + if (retval) { + pr_warn("%s: write wait interrupted\n", __FILE__); + retval = -ERESTARTSYS; + break; + } + if (test_bit(TIMO_NUM, &board->status)) { + pr_debug("%s: minor %i: write timed out\n", __FILE__, board->minor); + retval = -ETIMEDOUT; + break; + } + if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { + pr_warn("%s: device clear interrupted write\n", __FILE__); + retval = -EINTR; + break; + } + } + if (retval) + return retval; + if (send_eoi) { + size_t num_bytes; + + retval = hp_82341_write(board, buffer + fifo_xfer_len, 1, 1, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + } + return 0; +} + +static int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void hp_82341_detach(gpib_board_t *board); + +// wrappers for interface functions +int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); +} + +int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); +} + +int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); +} + +int hp_82341_take_control(gpib_board_t *board, int synchronous) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_take_control(board, &priv->tms9914_priv, synchronous); +} + +int hp_82341_go_to_standby(gpib_board_t *board) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_go_to_standby(board, &priv->tms9914_priv); +} + +void hp_82341_request_system_control(gpib_board_t *board, int request_control) +{ + struct hp_82341_priv *priv = board->private_data; + + if (request_control) + priv->mode_control_bits |= SYSTEM_CONTROLLER_BIT; + else + priv->mode_control_bits &= ~SYSTEM_CONTROLLER_BIT; + outb(priv->mode_control_bits, priv->iobase[0] + MODE_CONTROL_STATUS_REG); + tms9914_request_system_control(board, &priv->tms9914_priv, request_control); +} + +void hp_82341_interface_clear(gpib_board_t *board, int assert) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_interface_clear(board, &priv->tms9914_priv, assert); +} + +void hp_82341_remote_enable(gpib_board_t *board, int enable) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_remote_enable(board, &priv->tms9914_priv, enable); +} + +int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); +} + +void hp_82341_disable_eos(gpib_board_t *board) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_disable_eos(board, &priv->tms9914_priv); +} + +unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); +} + +int hp_82341_primary_address(gpib_board_t *board, unsigned int address) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_primary_address(board, &priv->tms9914_priv, address); +} + +int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); +} + +int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_parallel_poll(board, &priv->tms9914_priv, result); +} + +void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); +} + +void hp_82341_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); +} + +void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_serial_poll_response(board, &priv->tms9914_priv, status); +} + +static uint8_t hp_82341_serial_poll_status(gpib_board_t *board) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_serial_poll_status(board, &priv->tms9914_priv); +} + +static int hp_82341_line_status(const gpib_board_t *board) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_line_status(board, &priv->tms9914_priv); +} + +static unsigned int hp_82341_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct hp_82341_priv *priv = board->private_data; + + return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec); +} + +void hp_82341_return_to_local(gpib_board_t *board) +{ + struct hp_82341_priv *priv = board->private_data; + + tms9914_return_to_local(board, &priv->tms9914_priv); +} + +gpib_interface_t hp_82341_unaccel_interface = { +name: "hp_82341_unaccel", +attach : hp_82341_attach, +detach : hp_82341_detach, +read : hp_82341_read, +write : hp_82341_write, +command : hp_82341_command, +request_system_control : hp_82341_request_system_control, +take_control : hp_82341_take_control, +go_to_standby : hp_82341_go_to_standby, +interface_clear : hp_82341_interface_clear, +remote_enable : hp_82341_remote_enable, +enable_eos : hp_82341_enable_eos, +disable_eos : hp_82341_disable_eos, +parallel_poll : hp_82341_parallel_poll, +parallel_poll_configure : hp_82341_parallel_poll_configure, +parallel_poll_response : hp_82341_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : hp_82341_line_status, +update_status : hp_82341_update_status, +primary_address : hp_82341_primary_address, +secondary_address : hp_82341_secondary_address, +serial_poll_response : hp_82341_serial_poll_response, +serial_poll_status : hp_82341_serial_poll_status, +t1_delay : hp_82341_t1_delay, +return_to_local : hp_82341_return_to_local, +}; + +gpib_interface_t hp_82341_interface = { +name: "hp_82341", +attach : hp_82341_attach, +detach : hp_82341_detach, +read : hp_82341_accel_read, +write : hp_82341_accel_write, +command : hp_82341_command, +request_system_control : hp_82341_request_system_control, +take_control : hp_82341_take_control, +go_to_standby : hp_82341_go_to_standby, +interface_clear : hp_82341_interface_clear, +remote_enable : hp_82341_remote_enable, +enable_eos : hp_82341_enable_eos, +disable_eos : hp_82341_disable_eos, +parallel_poll : hp_82341_parallel_poll, +parallel_poll_configure : hp_82341_parallel_poll_configure, +parallel_poll_response : hp_82341_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : hp_82341_line_status, +update_status : hp_82341_update_status, +primary_address : hp_82341_primary_address, +secondary_address : hp_82341_secondary_address, +serial_poll_response : hp_82341_serial_poll_response, +t1_delay : hp_82341_t1_delay, +return_to_local : hp_82341_return_to_local, +}; + +int hp_82341_allocate_private(gpib_board_t *board) +{ + board->private_data = kzalloc(sizeof(struct hp_82341_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + return 0; +} + +void hp_82341_free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static uint8_t hp_82341_read_byte(struct tms9914_priv *priv, unsigned int register_num) +{ + return inb((unsigned long)(priv->iobase) + register_num); +} + +static void hp_82341_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num) +{ + outb(data, (unsigned long)(priv->iobase) + register_num); +} + +static int hp_82341_find_isapnp_board(struct pnp_dev **dev) +{ + *dev = pnp_find_dev(NULL, ISAPNP_VENDOR('H', 'W', 'P'), + ISAPNP_FUNCTION(0x1411), NULL); + if (!*dev || !(*dev)->card) { + pr_err("hp_82341: failed to find isapnp board\n"); + return -ENODEV; + } + if (pnp_device_attach(*dev) < 0) { + pr_err("hp_82341: board already active, skipping\n"); + return -EBUSY; + } + if (pnp_activate_dev(*dev) < 0) { + pnp_device_detach(*dev); + pr_err("hp_82341: failed to activate() atgpib/tnt, aborting\n"); + return -EAGAIN; + } + if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { + pnp_device_detach(*dev); + pr_err("hp_82341: invalid port or irq for atgpib/tnt, aborting\n"); + return -ENOMEM; + } + return 0; +} + +static int xilinx_ready(struct hp_82341_priv *hp_priv) +{ + switch (hp_priv->hw_version) { + case HW_VERSION_82341C: + if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & XILINX_READY_BIT) + return 1; + else + return 0; + break; + case HW_VERSION_82341D: + if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_READY_BIT) + return 1; + else + return 0; + default: + pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + break; + } + return 0; +} + +static int xilinx_done(struct hp_82341_priv *hp_priv) +{ + switch (hp_priv->hw_version) { + case HW_VERSION_82341C: + if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & DONE_PGL_BIT) + return 1; + else + return 0; + case HW_VERSION_82341D: + if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_DONE_BIT) + return 1; + else + return 0; + default: + pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + break; + } + return 0; +} + +static int irq_valid(struct hp_82341_priv *hp_priv, int irq) +{ + switch (hp_priv->hw_version) { + case HW_VERSION_82341C: + switch (irq) { + case 3: + case 5: + case 7: + case 9: + case 10: + case 11: + case 12: + case 15: + return 1; + default: + pr_err("hp_82341: invalid irq=%i for 82341C, irq must be 3, 5, 7, 9, 10, 11, 12, or 15.\n", + irq); + return 0; + } + break; + case HW_VERSION_82341D: + return 1; + default: + pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + break; + } + return 0; +} + +static int hp_82341_load_firmware_array(struct hp_82341_priv *hp_priv, + const unsigned char *firmware_data, + unsigned int firmware_length) +{ + int i, j; + static const int timeout = 100; + + for (i = 0; i < firmware_length; ++i) { + for (j = 0; j < timeout; ++j) { + if (need_resched()) + schedule(); + if (xilinx_ready(hp_priv)) + break; + usleep_range(10, 15); + } + if (j == timeout) { + pr_err("hp_82341: timed out waiting for Xilinx ready.\n"); + return -ETIMEDOUT; + } + outb(firmware_data[i], hp_priv->iobase[0] + XILINX_DATA_REG); + } + for (j = 0; j < timeout; ++j) { + if (xilinx_done(hp_priv)) + break; + if (need_resched()) + schedule(); + usleep_range(10, 15); + } + if (j == timeout) { + pr_err("hp_82341: timed out waiting for Xilinx done.\n"); + return -ETIMEDOUT; + } + return 0; +} + +static int hp_82341_load_firmware(struct hp_82341_priv *hp_priv, const gpib_board_config_t *config) +{ + if (config->init_data_length == 0) { + if (xilinx_done(hp_priv)) + return 0; + pr_err("hp_82341: board needs be initialized with firmware upload.\n" + "\tUse the --init-data option of gpib_config.\n"); + return -EINVAL; + } + switch (hp_priv->hw_version) { + case HW_VERSION_82341C: + if (config->init_data_length != hp_82341c_firmware_length) { + pr_err("hp_82341: bad firmware length=%i for 82341c (expected %i).\n", + config->init_data_length, hp_82341c_firmware_length); + return -EINVAL; + } + break; + case HW_VERSION_82341D: + if (config->init_data_length != hp_82341d_firmware_length) { + pr_err("hp_82341: bad firmware length=%i for 82341d (expected %i).\n", + config->init_data_length, hp_82341d_firmware_length); + return -EINVAL; + } + break; + default: + pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__); + break; + } + return hp_82341_load_firmware_array(hp_priv, config->init_data, config->init_data_length); +} + +static void set_xilinx_not_prog(struct hp_82341_priv *hp_priv, int assert) +{ + switch (hp_priv->hw_version) { + case HW_VERSION_82341C: + if (assert) + hp_priv->config_control_bits |= DONE_PGL_BIT; + else + hp_priv->config_control_bits &= ~DONE_PGL_BIT; + outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG); + break; + case HW_VERSION_82341D: + if (assert) + isapnp_write_byte(PIO_DATA_REG, HP_82341D_NOT_PROG_BIT); + else + isapnp_write_byte(PIO_DATA_REG, 0x0); + break; + default: + break; + } +} + +// clear xilinx firmware +static int clear_xilinx(struct hp_82341_priv *hp_priv) +{ + set_xilinx_not_prog(hp_priv, 1); + if (msleep_interruptible(1)) + return -EINTR; + set_xilinx_not_prog(hp_priv, 0); + if (msleep_interruptible(1)) + return -EINTR; + set_xilinx_not_prog(hp_priv, 1); + if (msleep_interruptible(1)) + return -EINTR; + return 0; +} + +int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct hp_82341_priv *hp_priv; + struct tms9914_priv *tms_priv; + unsigned long start_addr; + void *iobase; + int irq; + int i; + int retval; + + board->status = 0; + if (hp_82341_allocate_private(board)) + return -ENOMEM; + hp_priv = board->private_data; + tms_priv = &hp_priv->tms9914_priv; + tms_priv->read_byte = hp_82341_read_byte; + tms_priv->write_byte = hp_82341_write_byte; + tms_priv->offset = 1; + + if (config->ibbase == 0) { + struct pnp_dev *dev; + int retval = hp_82341_find_isapnp_board(&dev); + + if (retval < 0) + return retval; + hp_priv->pnp_dev = dev; + iobase = (void *)(pnp_port_start(dev, 0)); + irq = pnp_irq(dev, 0); + hp_priv->hw_version = HW_VERSION_82341D; + hp_priv->io_region_offset = 0x8; + } else { + iobase = config->ibbase; + irq = config->ibirq; + hp_priv->hw_version = HW_VERSION_82341C; + hp_priv->io_region_offset = 0x400; + } + pr_info("hp_82341: base io 0x%p\n", iobase); + for (i = 0; i < hp_82341_num_io_regions; ++i) { + start_addr = (unsigned long)(iobase) + i * hp_priv->io_region_offset; + if (!request_region(start_addr, hp_82341_region_iosize, "hp_82341")) { + pr_err("hp_82341: failed to allocate io ports 0x%lx-0x%lx\n", + start_addr, + start_addr + hp_82341_region_iosize - 1); + return -EIO; + } + hp_priv->iobase[i] = start_addr; + } + tms_priv->iobase = (void *)(hp_priv->iobase[2]); + if (hp_priv->hw_version == HW_VERSION_82341D) { + retval = isapnp_cfg_begin(hp_priv->pnp_dev->card->number, + hp_priv->pnp_dev->number); + if (retval < 0) { + pr_err("hp_82341: isapnp_cfg_begin returned error\n"); + return retval; + } + isapnp_write_byte(PIO_DIRECTION_REG, HP_82341D_XILINX_READY_BIT | + HP_82341D_XILINX_DONE_BIT); + } + retval = clear_xilinx(hp_priv); + if (retval < 0) + return retval; + retval = hp_82341_load_firmware(hp_priv, config); + if (hp_priv->hw_version == HW_VERSION_82341D) + isapnp_cfg_end(); + if (retval < 0) + return retval; + if (irq_valid(hp_priv, irq) == 0) + return -EINVAL; + if (request_irq(irq, hp_82341_interrupt, 0, "hp_82341", board)) { + pr_err("hp_82341: failed to allocate IRQ %d\n", irq); + return -EIO; + } + hp_priv->irq = irq; + pr_info("hp_82341: IRQ %d\n", irq); + hp_priv->config_control_bits &= ~IRQ_SELECT_MASK; + hp_priv->config_control_bits |= IRQ_SELECT_BITS(irq); + outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG); + hp_priv->mode_control_bits |= ENABLE_IRQ_CONFIG_BIT; + outb(hp_priv->mode_control_bits, hp_priv->iobase[0] + MODE_CONTROL_STATUS_REG); + tms9914_board_reset(tms_priv); + outb(ENABLE_BUFFER_END_EVENT_BIT | ENABLE_TERMINAL_COUNT_EVENT_BIT | + ENABLE_TI_INTERRUPT_EVENT_BIT, hp_priv->iobase[0] + EVENT_ENABLE_REG); + outb(ENABLE_BUFFER_END_INTERRUPT_BIT | ENABLE_TERMINAL_COUNT_INTERRUPT_BIT | + ENABLE_TI_INTERRUPT_BIT, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG); + //write clear event register + outb((TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT | + BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT), + hp_priv->iobase[0] + EVENT_STATUS_REG); + + tms9914_online(board, tms_priv); + pr_info("hp_82341: board id %x %x %x %x\n", inb(hp_priv->iobase[1] + ID0_REG), + inb(hp_priv->iobase[1] + ID1_REG), inb(hp_priv->iobase[2] + ID2_REG), + inb(hp_priv->iobase[2] + ID3_REG)); + return 0; +} + +void hp_82341_detach(gpib_board_t *board) +{ + struct hp_82341_priv *hp_priv = board->private_data; + struct tms9914_priv *tms_priv; + int i; + + if (hp_priv) { + tms_priv = &hp_priv->tms9914_priv; + if (hp_priv->iobase[0]) { + outb(0, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG); + if (tms_priv->iobase) + tms9914_board_reset(tms_priv); + if (hp_priv->irq) + free_irq(hp_priv->irq, board); + } + for (i = 0; i < hp_82341_num_io_regions; ++i) { + if (hp_priv->iobase[i]) + release_region(hp_priv->iobase[i], hp_82341_region_iosize); + } + if (hp_priv->pnp_dev) + pnp_device_detach(hp_priv->pnp_dev); + } + hp_82341_free_private(board); +} + +static const struct pnp_device_id hp_82341_pnp_table[] = { + {.id = "HWP1411"}, + {.id = ""} +}; +MODULE_DEVICE_TABLE(pnp, hp_82341_pnp_table); + +static int __init hp_82341_init_module(void) +{ + gpib_register_driver(&hp_82341_unaccel_interface, THIS_MODULE); + gpib_register_driver(&hp_82341_interface, THIS_MODULE); + return 0; +} + +static void __exit hp_82341_exit_module(void) +{ + gpib_unregister_driver(&hp_82341_interface); + gpib_unregister_driver(&hp_82341_unaccel_interface); +} + +module_init(hp_82341_init_module); +module_exit(hp_82341_exit_module); + +/* + * GPIB interrupt service routines + */ +unsigned short read_and_clear_event_status(gpib_board_t *board) +{ + struct hp_82341_priv *hp_priv = board->private_data; + unsigned long flags; + unsigned short status; + + spin_lock_irqsave(&board->spinlock, flags); + status = hp_priv->event_status_bits; + hp_priv->event_status_bits = 0; + spin_unlock_irqrestore(&board->spinlock, flags); + return status; +} + +irqreturn_t hp_82341_interrupt(int irq, void *arg) +{ + int status1, status2; + gpib_board_t *board = arg; + struct hp_82341_priv *hp_priv = board->private_data; + struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; + unsigned long flags; + irqreturn_t retval = IRQ_NONE; + int event_status; + + spin_lock_irqsave(&board->spinlock, flags); + event_status = inb(hp_priv->iobase[0] + EVENT_STATUS_REG); +// printk("hp_82341: interrupt event_status=0x%x\n", event_status); + if (event_status & INTERRUPT_PENDING_EVENT_BIT) + retval = IRQ_HANDLED; + //write-clear status bits + if (event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT | + BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT)) { + outb(event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT | + BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT), + hp_priv->iobase[0] + EVENT_STATUS_REG); + hp_priv->event_status_bits |= event_status; + } + if (event_status & TI_INTERRUPT_EVENT_BIT) { + status1 = read_byte(tms_priv, ISR0); + status2 = read_byte(tms_priv, ISR1); + tms9914_interrupt_have_status(board, tms_priv, status1, status2); +/* printk("hp_82341: interrupt status1=0x%x status2=0x%x\n", + * status1, status2); + */ + } + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +int read_transfer_counter(struct hp_82341_priv *hp_priv) +{ + int lo, mid, value; + + lo = inb(hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG); + mid = inb(hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG); + value = (lo & 0xff) | ((mid << 8) & 0x7f00); + value = ~(value - 1) & 0x7fff; + return value; +} + +void set_transfer_counter(struct hp_82341_priv *hp_priv, int count) +{ + int complement = -count; + + outb(complement & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG); + outb((complement >> 8) & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG); + //I don't think the hi count reg is even used, but oh well + outb((complement >> 16) & 0xf, hp_priv->iobase[1] + TRANSFER_COUNT_HIGH_REG); +} + diff --git a/drivers/staging/gpib/hp_82341/hp_82341.h b/drivers/staging/gpib/hp_82341/hp_82341.h new file mode 100644 index 0000000000000000000000000000000000000000..7c391860b3994e4df571588c7e105ac6b07f5bc3 --- /dev/null +++ b/drivers/staging/gpib/hp_82341/hp_82341.h @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002, 2005 by Frank Mori Hess * + ***************************************************************************/ + +#include "tms9914.h" +#include "gpibP.h" + +enum hp_82341_hardware_version { + HW_VERSION_UNKNOWN, + HW_VERSION_82341C, + HW_VERSION_82341D, +}; + +// struct which defines private_data for board +struct hp_82341_priv { + struct tms9914_priv tms9914_priv; + unsigned int irq; + unsigned short config_control_bits; + unsigned short mode_control_bits; + unsigned short event_status_bits; + struct pnp_dev *pnp_dev; + unsigned long iobase[4]; + unsigned long io_region_offset; + enum hp_82341_hardware_version hw_version; +}; + +// interfaces +extern gpib_interface_t hp_82341_interface; + +// interface functions +int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read); +int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); +int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read); +int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); +int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); +int hp_82341_take_control(gpib_board_t *board, int synchronous); +int hp_82341_go_to_standby(gpib_board_t *board); +void hp_82341_request_system_control(gpib_board_t *board, int request_control); +void hp_82341_interface_clear(gpib_board_t *board, int assert); +void hp_82341_remote_enable(gpib_board_t *board, int enable); +int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int + compare_8_bits); +void hp_82341_disable_eos(gpib_board_t *board); +unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask); +int hp_82341_primary_address(gpib_board_t *board, unsigned int address); +int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int + enable); +int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result); +void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config); +void hp_82341_parallel_poll_response(gpib_board_t *board, int ist); +void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status); +void hp_82341_return_to_local(gpib_board_t *board); + +// interrupt service routines +irqreturn_t hp_82341_interrupt(int irq, void *arg); + +// utility functions +int hp_82341_allocate_private(gpib_board_t *board); +void hp_82341_free_private(gpib_board_t *board); + +static const int hp_82341_region_iosize = 0x8; +static const int hp_82341_num_io_regions = 4; +static const int hp_82341_fifo_size = 0xffe; +static const int hp_82341c_firmware_length = 5764; +static const int hp_82341d_firmware_length = 5302; + +// hp 82341 register offsets +enum hp_82341_region_0_registers { + CONFIG_CONTROL_STATUS_REG = 0x0, + MODE_CONTROL_STATUS_REG = 0x1, + MONITOR_REG = 0x2, // after initialization + XILINX_DATA_REG = 0x2, // before initialization, write only + INTERRUPT_ENABLE_REG = 0x3, + EVENT_STATUS_REG = 0x4, + EVENT_ENABLE_REG = 0x5, + STREAM_STATUS_REG = 0x7, +}; + +enum hp_82341_region_1_registers { + ID0_REG = 0x2, + ID1_REG = 0x3, + TRANSFER_COUNT_LOW_REG = 0x4, + TRANSFER_COUNT_MID_REG = 0x5, + TRANSFER_COUNT_HIGH_REG = 0x6, +}; + +enum hp_82341_region_3_registers { + BUFFER_PORT_LOW_REG = 0x0, + BUFFER_PORT_HIGH_REG = 0x1, + ID2_REG = 0x2, + ID3_REG = 0x3, + BUFFER_FLUSH_REG = 0x4, + BUFFER_CONTROL_REG = 0x7 +}; + +enum config_control_status_bits { + IRQ_SELECT_MASK = 0x7, + DMA_CONFIG_MASK = 0x18, + ENABLE_DMA_CONFIG_BIT = 0x20, + XILINX_READY_BIT = 0x40, //read only + DONE_PGL_BIT = 0x80 +}; + +static inline unsigned int IRQ_SELECT_BITS(int irq) +{ + switch (irq) { + case 3: + return 0x3; + case 5: + return 0x2; + case 7: + return 0x1; + case 9: + return 0x0; + case 10: + return 0x7; + case 11: + return 0x6; + case 12: + return 0x5; + case 15: + return 0x4; + default: + return 0x0; + } +}; + +enum mode_control_status_bits { + SLOT8_BIT = 0x1, // read only + ACTIVE_CONTROLLER_BIT = 0x2, // read only + ENABLE_DMA_BIT = 0x4, + SYSTEM_CONTROLLER_BIT = 0x8, + MONITOR_BIT = 0x10, + ENABLE_IRQ_CONFIG_BIT = 0x20, + ENABLE_TI_STREAM_BIT = 0x40 +}; + +enum monitor_bits { + MONITOR_INTERRUPT_PENDING_BIT = 0x1, // read only + MONITOR_CLEAR_HOLDOFF_BIT = 0x2, // write only + MONITOR_PPOLL_BIT = 0x4, // write clear + MONITOR_SRQ_BIT = 0x8, // write clear + MONITOR_IFC_BIT = 0x10, // write clear + MONITOR_REN_BIT = 0x20, // write clear + MONITOR_END_BIT = 0x40, // write clear + MONITOR_DAV_BIT = 0x80 // write clear +}; + +enum interrupt_enable_bits { + ENABLE_TI_INTERRUPT_BIT = 0x1, + ENABLE_POINTERS_EQUAL_INTERRUPT_BIT = 0x4, + ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10, + ENABLE_TERMINAL_COUNT_INTERRUPT_BIT = 0x20, + ENABLE_DMA_TERMINAL_COUNT_INTERRUPT_BIT = 0x80, +}; + +enum event_status_bits { + TI_INTERRUPT_EVENT_BIT = 0x1, //write clear + INTERRUPT_PENDING_EVENT_BIT = 0x2, // read only + POINTERS_EQUAL_EVENT_BIT = 0x4, //write clear + BUFFER_END_EVENT_BIT = 0x10, //write clear + TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear + DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear +}; + +enum event_enable_bits { + ENABLE_TI_INTERRUPT_EVENT_BIT = 0x1, //write clear + ENABLE_POINTERS_EQUAL_EVENT_BIT = 0x4, //write clear + ENABLE_BUFFER_END_EVENT_BIT = 0x10, //write clear + ENABLE_TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear + ENABLE_DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear +}; + +enum stream_status_bits { + HALTED_STATUS_BIT = 0x1, //read + RESTART_STREAM_BIT = 0x1 //write +}; + +enum buffer_control_bits { + DIRECTION_GPIB_TO_HOST_BIT = 0x20, // transfer direction (set for gpib to host) + ENABLE_TI_BUFFER_BIT = 0x40, //enable fifo + FAST_WR_EN_BIT = 0x80, // 350 ns t1 delay? +}; + +// registers accessible through isapnp chip on 82341d +enum hp_82341d_pnp_registers { + PIO_DATA_REG = 0x20, //read/write pio data lines + PIO_DIRECTION_REG = 0x21, // set pio data line directions (set for input) +}; + +enum hp_82341d_pnp_pio_bits { + HP_82341D_XILINX_READY_BIT = 0x1, + HP_82341D_XILINX_DONE_BIT = 0x2, + // use register layout compatible with C and older versions instead of 32 contiguous ioports + HP_82341D_LEGACY_MODE_BIT = 0x4, + HP_82341D_NOT_PROG_BIT = 0x8, // clear to reinitialize xilinx +}; + +unsigned short read_and_clear_event_status(gpib_board_t *board); +int read_transfer_counter(struct hp_82341_priv *hp_priv); +void set_transfer_counter(struct hp_82341_priv *hp_priv, int count); diff --git a/drivers/staging/gpib/include/amcc5920.h b/drivers/staging/gpib/include/amcc5920.h new file mode 100644 index 0000000000000000000000000000000000000000..766b3799223f14c12325ee86f0f555ed0bbd43be --- /dev/null +++ b/drivers/staging/gpib/include/amcc5920.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Header for amcc5920 pci chip + * + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +// plx pci chip registers and bits +enum amcc_registers { + AMCC_INTCS_REG = 0x38, + AMCC_PASS_THRU_REG = 0x60, +}; + +enum amcc_incsr_bits { + AMCC_ADDON_INTR_ENABLE_BIT = 0x2000, + AMCC_ADDON_INTR_ACTIVE_BIT = 0x400000, + AMCC_INTR_ACTIVE_BIT = 0x800000, +}; + +static const int bits_per_region = 8; + +static inline uint32_t amcc_wait_state_bits(unsigned int region, unsigned int num_wait_states) +{ + return (num_wait_states & 0x7) << (-region * bits_per_region); +}; + +enum amcc_prefetch_bits { + PREFETCH_DISABLED = 0x0, + PREFETCH_SMALL = 0x8, + PREFETCH_MEDIUM = 0x10, + PREFETCH_LARGE = 0x18, +}; + +static inline uint32_t amcc_prefetch_bits(unsigned int region, enum amcc_prefetch_bits prefetch) +{ + return prefetch << (--region * bits_per_region); +}; + +static inline uint32_t amcc_PTADR_mode_bit(unsigned int region) +{ + return 0x80 << (--region * bits_per_region); +}; + +static inline uint32_t amcc_disable_write_fifo_bit(unsigned int region) +{ + return 0x20 << (--region * bits_per_region); +}; + diff --git a/drivers/staging/gpib/include/amccs5933.h b/drivers/staging/gpib/include/amccs5933.h new file mode 100644 index 0000000000000000000000000000000000000000..4de0f6797458477cfd5ed7235f743348305ed2f7 --- /dev/null +++ b/drivers/staging/gpib/include/amccs5933.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Registers and bits for amccs5933 pci chip + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +// register offsets +enum { + MBEF_REG = 0x34, // mailbux empty/full + INTCSR_REG = 0x38, // interrupt control and status + BMCSR_REG = 0x3c, // bus master control and status +}; + +// incoming mailbox 0-3 register offsets +extern inline int INCOMING_MAILBOX_REG(unsigned int mailbox) +{ + return (0x10 + 4 * mailbox); +}; + +// bit definitions + +// INTCSR bits +enum { + OUTBOX_EMPTY_INTR_BIT = 0x10, // enable outbox empty interrupt + INBOX_FULL_INTR_BIT = 0x1000, // enable inbox full interrupt + INBOX_INTR_CS_BIT = 0x20000, // read, or write clear inbox full interrupt + INTR_ASSERTED_BIT = 0x800000, // read only, interrupt asserted +}; + +// select byte 0 to 3 of incoming mailbox +extern inline int INBOX_BYTE_BITS(unsigned int byte) +{ + return (byte & 0x3) << 8; +}; + +// select incoming mailbox 0 to 3 +extern inline int INBOX_SELECT_BITS(unsigned int mailbox) +{ + return (mailbox & 0x3) << 10; +}; + +// select byte 0 to 3 of outgoing mailbox +extern inline int OUTBOX_BYTE_BITS(unsigned int byte) +{ + return (byte & 0x3); +}; + +// select outgoing mailbox 0 to 3 +extern inline int OUTBOX_SELECT_BITS(unsigned int mailbox) +{ + return (mailbox & 0x3) << 2; +}; + +//BMCSR bits +enum { + MBOX_FLAGS_RESET_BIT = 0x08000000, // resets mailbox empty/full flags +}; + diff --git a/drivers/staging/gpib/include/gpibP.h b/drivers/staging/gpib/include/gpibP.h new file mode 100644 index 0000000000000000000000000000000000000000..5fc42b645ab70c29ad0400188ed1a4b384a2b380 --- /dev/null +++ b/drivers/staging/gpib/include/gpibP.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002,2003 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _GPIB_P_H +#define _GPIB_P_H + +#include <linux/types.h> + +#include "gpib_types.h" +#include "gpib_proto.h" +#include "gpib_user.h" +#include "gpib_ioctl.h" + +#include <linux/fs.h> +#include <linux/interrupt.h> + +void gpib_register_driver(gpib_interface_t *interface, struct module *mod); +void gpib_unregister_driver(gpib_interface_t *interface); +struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id, + unsigned int device_id, struct pci_dev *from); +struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id, + unsigned int device_id, unsigned int ss_vendor, + unsigned int ss_device, struct pci_dev *from); +unsigned int num_gpib_events(const gpib_event_queue_t *queue); +int push_gpib_event(gpib_board_t *board, short event_type); +int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type); +int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *)); +void gpib_free_pseudo_irq(gpib_board_t *board); +int gpib_match_device_path(struct device *dev, const char *device_path_in); + +extern gpib_board_t board_array[GPIB_MAX_NUM_BOARDS]; + +extern struct list_head registered_drivers; + +#include <linux/io.h> + +void writeb_wrapper(unsigned int value, void *address); +unsigned int readb_wrapper(void *address); +void outb_wrapper(unsigned int value, void *address); +unsigned int inb_wrapper(void *address); +void writew_wrapper(unsigned int value, void *address); +unsigned int readw_wrapper(void *address); +void outw_wrapper(unsigned int value, void *address); +unsigned int inw_wrapper(void *address); + +#endif // _GPIB_P_H + diff --git a/drivers/staging/gpib/include/gpib_pci_ids.h b/drivers/staging/gpib/include/gpib_pci_ids.h new file mode 100644 index 0000000000000000000000000000000000000000..52dcab07a7d188925a4d696d6b658f397f3b0153 --- /dev/null +++ b/drivers/staging/gpib/include/gpib_pci_ids.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __GPIB_PCI_IDS_H +#define __GPIB_PCI_IDS_H + +#ifndef PCI_VENDOR_ID_AMCC +#define PCI_VENDOR_ID_AMCC 0x10e8 +#endif + +#ifndef PCI_VENDOR_ID_CBOARDS +#define PCI_VENDOR_ID_CBOARDS 0x1307 +#endif + +#ifndef PCI_VENDOR_ID_QUANCOM +#define PCI_VENDOR_ID_QUANCOM 0x8008 +#endif + +#ifndef PCI_DEVICE_ID_QUANCOM_GPIB +#define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302 +#endif + +#endif // __GPIB_PCI_IDS_H + diff --git a/drivers/staging/gpib/include/gpib_proto.h b/drivers/staging/gpib/include/gpib_proto.h new file mode 100644 index 0000000000000000000000000000000000000000..1499f954210b8ce7949f9f10ff71fd116f0f1969 --- /dev/null +++ b/drivers/staging/gpib/include/gpib_proto.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef GPIB_PROTO_INCLUDED +#define GPIB_PROTO_INCLUDED + +#include <linux/fs.h> + +int ibopen(struct inode *inode, struct file *filep); +int ibclose(struct inode *inode, struct file *file); +long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg); +int osInit(void); +void osReset(void); +void os_start_timer(gpib_board_t *board, unsigned int usec_timeout); +void os_remove_timer(gpib_board_t *board); +void osSendEOI(void); +void osSendEOI(void); +void init_gpib_board(gpib_board_t *board); +static inline unsigned long usec_to_jiffies(unsigned int usec) +{ + unsigned long usec_per_jiffy = 1000000 / HZ; + + return 1 + (usec + usec_per_jiffy - 1) / usec_per_jiffy; +}; + +int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout); +void init_gpib_descriptor(gpib_descriptor_t *desc); +int dvrsp(gpib_board_t *board, unsigned int pad, int sad, + unsigned int usec_timeout, uint8_t *result); +int ibAPWait(gpib_board_t *board, int pad); +int ibAPrsp(gpib_board_t *board, int padsad, char *spb); +void ibAPE(gpib_board_t *board, int pad, int v); +int ibcac(gpib_board_t *board, int sync, int fallback_to_async); +int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written); +int ibgts(gpib_board_t *board); +int ibonline(gpib_board_t *board); +int iboffline(gpib_board_t *board); +int iblines(const gpib_board_t *board, short *lines); +int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *bytes_read); +int ibrpp(gpib_board_t *board, uint8_t *buf); +int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service); +void ibrsc(gpib_board_t *board, int request_control); +int ibsic(gpib_board_t *board, unsigned int usec_duration); +int ibsre(gpib_board_t *board, int enable); +int ibpad(gpib_board_t *board, unsigned int addr); +int ibsad(gpib_board_t *board, int addr); +int ibeos(gpib_board_t *board, int eos, int eosflags); +int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask, + int *status, unsigned long usec_timeout, gpib_descriptor_t *desc); +int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written); +int ibstatus(gpib_board_t *board); +int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device, + int clear_mask, int set_mask, gpib_descriptor_t *desc); +int io_timed_out(gpib_board_t *board); +int ibppc(gpib_board_t *board, uint8_t configuration); + +#endif /* GPIB_PROTO_INCLUDED */ diff --git a/drivers/staging/gpib/include/gpib_state_machines.h b/drivers/staging/gpib/include/gpib_state_machines.h new file mode 100644 index 0000000000000000000000000000000000000000..7488c00f191e80ab8e257dce0e909c8b8d9b11d4 --- /dev/null +++ b/drivers/staging/gpib/include/gpib_state_machines.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2006 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _GPIB_STATE_MACHINES_H +#define _GPIB_STATE_MACHINES_H + +enum talker_function_state { + talker_idle, + talker_addressed, + talker_active, + serial_poll_active +}; + +enum listener_function_state { + listener_idle, + listener_addressed, + listener_active +}; + +#endif // _GPIB_STATE_MACHINES_H diff --git a/drivers/staging/gpib/include/gpib_types.h b/drivers/staging/gpib/include/gpib_types.h new file mode 100644 index 0000000000000000000000000000000000000000..ee2643da6d71066c1aaea4d6a656d1545b8ad67c --- /dev/null +++ b/drivers/staging/gpib/include/gpib_types.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _GPIB_TYPES_H +#define _GPIB_TYPES_H + +#ifdef __KERNEL__ +/* gpib_interface_t defines the interface + * between the board-specific details dealt with in the drivers + * and generic interface provided by gpib-common. + * This really should be in a different header file. + */ +#include "gpib_user.h" +#include <linux/atomic.h> +#include <linux/device.h> +#include <linux/mutex.h> +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/timer.h> +#include <linux/interrupt.h> + +typedef struct gpib_interface_struct gpib_interface_t; +typedef struct gpib_board_struct gpib_board_t; + +/* config parameters that are only used by driver attach functions */ +typedef struct { + /* firmware blob */ + void *init_data; + int init_data_length; + /* IO base address to use for non-pnp cards (set by core, driver should make local copy) */ + void *ibbase; + /* IRQ to use for non-pnp cards (set by core, driver should make local copy) */ + unsigned int ibirq; + /* dma channel to use for non-pnp cards (set by core, driver should make local copy) */ + unsigned int ibdma; + /* pci bus of card, useful for distinguishing multiple identical pci cards + * (negative means don't care) + */ + int pci_bus; + /* pci slot of card, useful for distinguishing multiple identical pci cards + * (negative means don't care) + */ + int pci_slot; + /* sysfs device path of hardware to attach */ + char *device_path; + /* serial number of hardware to attach */ + char *serial_number; +} gpib_board_config_t; + +struct gpib_interface_struct { + /* name of board */ + char *name; + /* attach() initializes board and allocates resources */ + int (*attach)(gpib_board_t *board, const gpib_board_config_t *config); + /* detach() shuts down board and frees resources */ + void (*detach)(gpib_board_t *board); + /* read() should read at most 'length' bytes from the bus into + * 'buffer'. It should return when it fills the buffer or + * encounters an END (EOI and or EOS if appropriate). It should set 'end' + * to be nonzero if the read was terminated by an END, otherwise 'end' + * should be zero. + * Ultimately, this will be changed into or replaced by an asynchronous + * read. Zero return value for success, negative + * return indicates error. + * nbytes returns number of bytes read + */ + int (*read)(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read); + /* write() should write 'length' bytes from buffer to the bus. + * If the boolean value send_eoi is nonzero, then EOI should + * be sent along with the last byte. Returns number of bytes + * written or negative value on error. + */ + int (*write)(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written); + /* command() writes the command bytes in 'buffer' to the bus + * Returns zero on success or negative value on error. + */ + int (*command)(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written); + /* Take control (assert ATN). If 'asyncronous' is nonzero, take + * control asyncronously (assert ATN immediately without waiting + * for other processes to complete first). Should not return + * until board becomes controller in charge. Returns zero no success, + * nonzero on error. + */ + int (*take_control)(gpib_board_t *board, int asyncronous); + /* De-assert ATN. Returns zero on success, nonzer on error. + */ + int (*go_to_standby)(gpib_board_t *board); + /* request/release control of the IFC and REN lines (system controller) */ + void (*request_system_control)(gpib_board_t *board, int request_control); + /* Asserts or de-asserts 'interface clear' (IFC) depending on + * boolean value of 'assert' + */ + void (*interface_clear)(gpib_board_t *board, int assert); + /* Sends remote enable command if 'enable' is nonzero, disables remote mode + * if 'enable' is zero + */ + void (*remote_enable)(gpib_board_t *board, int enable); + /* enable END for reads, when byte 'eos' is received. If + * 'compare_8_bits' is nonzero, then all 8 bits are compared + * with the eos bytes. Otherwise only the 7 least significant + * bits are compared. + */ + int (*enable_eos)(gpib_board_t *board, uint8_t eos, int compare_8_bits); + /* disable END on eos byte (END on EOI only)*/ + void (*disable_eos)(gpib_board_t *board); + /* configure parallel poll */ + void (*parallel_poll_configure)(gpib_board_t *board, uint8_t configuration); + /* conduct parallel poll */ + int (*parallel_poll)(gpib_board_t *board, uint8_t *result); + /* set/clear ist (individual status bit) */ + void (*parallel_poll_response)(gpib_board_t *board, int ist); + /* select local parallel poll configuration mode PP2 versus remote PP1 */ + void (*local_parallel_poll_mode)(gpib_board_t *board, int local); + /* Returns current status of the bus lines. Should be set to + * NULL if your board does not have the ability to query the + * state of the bus lines. + */ + int (*line_status)(const gpib_board_t *board); + /* updates and returns the board's current status. + * The meaning of the bits are specified in gpib_user.h + * in the IBSTA section. The driver does not need to + * worry about setting the CMPL, END, TIMO, or ERR bits. + */ + unsigned int (*update_status)(gpib_board_t *board, unsigned int clear_mask); + /* Sets primary address 0-30 for gpib interface card. + */ + int (*primary_address)(gpib_board_t *board, unsigned int address); + /* Sets and enables, or disables secondary address 0-30 + * for gpib interface card. + */ + int (*secondary_address)(gpib_board_t *board, unsigned int address, + int enable); + /* Sets the byte the board should send in response to a serial poll. + * This function should also start or stop requests for service via + * IEEE 488.2 reqt/reqf, based on MSS (bit 6 of the status_byte). + * If the more flexible serial_poll_response2 is implemented by the + * driver, then this method should be left NULL since it will not + * be used. This method can generate spurious service requests + * which are allowed by IEEE 488.2, but not ideal. + * + * This method should implement the serial poll response method described + * by IEEE 488.2 section 11.3.3.4.3 "Allowed Coupled Control of + * STB, reqt, and reqf". + */ + void (*serial_poll_response)(gpib_board_t *board, uint8_t status_byte); + /* Sets the byte the board should send in response to a serial poll. + * This function should also request service via IEEE 488.2 reqt/reqf + * based on MSS (bit 6 of the status_byte) and new_reason_for_service. + * reqt should be set true if new_reason_for_service is true, + * and reqf should be set true if MSS is false. This function + * will never be called with MSS false and new_reason_for_service + * true simultaneously, so don't worry about that case. + * + * This method implements the serial poll response method described + * by IEEE 488.2 section 11.3.3.4.1 "Preferred Implementation". + * + * If this method is left NULL by the driver, then the user library + * function ibrsv2 will not work. + */ + void (*serial_poll_response2)(gpib_board_t *board, uint8_t status_byte, + int new_reason_for_service); + /* returns the byte the board will send in response to a serial poll. + */ + uint8_t (*serial_poll_status)(gpib_board_t *board); + /* adjust T1 delay */ + unsigned int (*t1_delay)(gpib_board_t *board, unsigned int nano_sec); + /* go to local mode */ + void (*return_to_local)(gpib_board_t *board); + /* board does not support 7 bit eos comparisons */ + unsigned no_7_bit_eos : 1; + /* skip check for listeners before trying to send command bytes */ + unsigned skip_check_for_command_acceptors : 1; +}; + +typedef struct { + struct list_head event_head; + spinlock_t lock; // for access to event list + unsigned int num_events; + unsigned dropped_event : 1; +} gpib_event_queue_t; + +static inline void init_event_queue(gpib_event_queue_t *queue) +{ + INIT_LIST_HEAD(&queue->event_head); + queue->num_events = 0; + queue->dropped_event = 0; + spin_lock_init(&queue->lock); +} + +/* struct for supporting polling operation when irq is not available */ +struct gpib_pseudo_irq { + struct timer_list timer; + irqreturn_t (*handler)(int irq, void *arg); + gpib_board_t *board; + atomic_t active; +}; + +static inline void init_gpib_pseudo_irq(struct gpib_pseudo_irq *pseudo_irq) +{ + pseudo_irq->handler = NULL; + timer_setup(&pseudo_irq->timer, NULL, 0); + atomic_set(&pseudo_irq->active, 0); +} + +/* list so we can make a linked list of drivers */ +typedef struct gpib_interface_list_struct { + struct list_head list; + gpib_interface_t *interface; + struct module *module; +} gpib_interface_list_t; + +/* One gpib_board_t is allocated for each physical board in the computer. + * It provides storage for variables local to each board, and interface + * functions for performing operations on the board + */ +struct gpib_board_struct { + /* functions used by this board */ + gpib_interface_t *interface; + /* Pointer to module whose use count we should increment when + * interface is in use + */ + struct module *provider_module; + /* buffer used to store read/write data for this board */ + u8 *buffer; + /* length of buffer */ + unsigned int buffer_length; + /* Used to hold the board's current status (see update_status() above) + */ + unsigned long status; + /* Driver should only sleep on this wait queue. It is special in that the + * core will wake this queue and set the TIMO bit in 'status' when the + * watchdog timer times out. + */ + wait_queue_head_t wait; + /* Lock that only allows one process to access this board at a time. + * Has to be first in any locking order, since it can be locked over + * multiple ioctls. + */ + struct mutex user_mutex; + /* Mutex which compensates for removal of "big kernel lock" from kernel. + * Should not be held for extended waits. + */ + struct mutex big_gpib_mutex; + /* pid of last process to lock the board mutex */ + pid_t locking_pid; + spinlock_t locking_pid_spinlock; // lock for setting locking pid + /* Spin lock for dealing with races with the interrupt handler */ + spinlock_t spinlock; + /* Watchdog timer to enable timeouts */ + struct timer_list timer; + /* device of attached driver if any */ + struct device *dev; + /* gpib_common device gpibN */ + struct device *gpib_dev; + /* 'private_data' can be used as seen fit by the driver to + * store additional variables for this board + */ + void *private_data; + /* Number of open file descriptors using this board */ + unsigned int use_count; + /* list of open devices connected to this board */ + struct list_head device_list; + /* primary address */ + unsigned int pad; + /* secondary address */ + int sad; + /* timeout for io operations, in microseconds */ + unsigned int usec_timeout; + /* board's parallel poll configuration byte */ + u8 parallel_poll_configuration; + /* t1 delay we are using */ + unsigned int t1_nano_sec; + /* Count that keeps track of whether board is up and running or not */ + unsigned int online; + /* number of processes trying to autopoll */ + int autospollers; + /* autospoll kernel thread */ + struct task_struct *autospoll_task; + /* queue for recording received trigger/clear/ifc events */ + gpib_event_queue_t event_queue; + /* minor number for this board's device file */ + int minor; + /* struct to deal with polling mode*/ + struct gpib_pseudo_irq pseudo_irq; + /* error dong autopoll */ + atomic_t stuck_srq; + gpib_board_config_t config; + /* Flag that indicates whether board is system controller of the bus */ + unsigned master : 1; + /* individual status bit */ + unsigned ist : 1; + /* one means local parallel poll mode ieee 488.1 PP2 (or no parallel poll PP0), + * zero means remote parallel poll configuration mode ieee 488.1 PP1 + */ + unsigned local_ppoll_mode : 1; +}; + +/* element of event queue */ +typedef struct { + struct list_head list; + short event_type; +} gpib_event_t; + +/* Each board has a list of gpib_status_queue_t to keep track of all open devices + * on the bus, so we know what address to poll when we get a service request + */ +typedef struct { + /* list_head so we can make a linked list of devices */ + struct list_head list; + unsigned int pad; /* primary gpib address */ + int sad; /* secondary gpib address (negative means disabled) */ + /* stores serial poll bytes for this device */ + struct list_head status_bytes; + unsigned int num_status_bytes; + /* number of times this address is opened */ + unsigned int reference_count; + /* flags loss of status byte error due to limit on size of queue */ + unsigned dropped_byte : 1; +} gpib_status_queue_t; + +typedef struct { + struct list_head list; + u8 poll_byte; +} status_byte_t; + +void init_gpib_status_queue(gpib_status_queue_t *device); + +/* Used to store device-descriptor-specific information */ +typedef struct { + unsigned int pad; /* primary gpib address */ + int sad; /* secondary gpib address (negative means disabled) */ + atomic_t io_in_progress; + unsigned is_board : 1; + unsigned autopoll_enabled : 1; +} gpib_descriptor_t; + +typedef struct { + atomic_t holding_mutex; + gpib_descriptor_t *descriptors[GPIB_MAX_NUM_DESCRIPTORS]; + /* locked while descriptors are being allocated/deallocated */ + struct mutex descriptors_mutex; + unsigned got_module : 1; +} gpib_file_private_t; + +#endif /* __KERNEL__ */ + +#endif /* _GPIB_TYPES_H */ diff --git a/drivers/staging/gpib/include/nec7210.h b/drivers/staging/gpib/include/nec7210.h new file mode 100644 index 0000000000000000000000000000000000000000..c00aba4ce846dc885c7e2d7ed5dc780317f88501 --- /dev/null +++ b/drivers/staging/gpib/include/nec7210.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _NEC7210_H +#define _NEC7210_H + +#include "gpib_state_machines.h" +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/string.h> +#include <linux/interrupt.h> + +#include "gpib_types.h" +#include "nec7210_registers.h" + +/* struct used to provide variables local to a nec7210 chip */ +struct nec7210_priv { + void *iobase; + unsigned int offset; // offset between successive nec7210 io addresses + unsigned int dma_channel; + u8 *dma_buffer; + unsigned int dma_buffer_length; // length of dma buffer + dma_addr_t dma_buffer_addr; // bus address of board->buffer for use with dma + // software copy of bits written to registers + u8 reg_bits[8]; + u8 auxa_bits; // bits written to auxiliary register A + u8 auxb_bits; // bits written to auxiliary register B + // used to keep track of board's state, bit definitions given below + unsigned long state; + /* lock for chips that extend the nec7210 registers by paging in alternate regs */ + spinlock_t register_page_lock; + // wrappers for outb, inb, readb, or writeb + u8 (*read_byte)(struct nec7210_priv *priv, unsigned int register_number); + void (*write_byte)(struct nec7210_priv *priv, u8 byte, unsigned int register_number); + enum nec7210_chipset type; + enum talker_function_state talker_state; + enum listener_function_state listener_state; + void *private; + unsigned srq_pending : 1; +}; + +static inline void init_nec7210_private(struct nec7210_priv *priv) +{ + memset(priv, 0, sizeof(struct nec7210_priv)); + spin_lock_init(&priv->register_page_lock); +} + +// slightly shorter way to access read_byte and write_byte +static inline u8 read_byte(struct nec7210_priv *priv, unsigned int register_number) +{ + return priv->read_byte(priv, register_number); +} + +static inline void write_byte(struct nec7210_priv *priv, u8 byte, unsigned int register_number) +{ + priv->write_byte(priv, byte, register_number); +} + +// struct nec7210_priv.state bit numbers +enum { + PIO_IN_PROGRESS_BN, // pio transfer in progress + DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress + DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress + READ_READY_BN, // board has data byte available to read + WRITE_READY_BN, // board is ready to send a data byte + COMMAND_READY_BN, // board is ready to send a command byte + RECEIVED_END_BN, // received END + BUS_ERROR_BN, // output error has occurred + RFD_HOLDOFF_BN, // rfd holdoff in effect + DEV_CLEAR_BN, // device clear received + ADR_CHANGE_BN, // address state change occurred +}; + +// interface functions +int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read); +int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written); +int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length, size_t *bytes_written); +int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous); +int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv); +void nec7210_request_system_control(gpib_board_t *board, + struct nec7210_priv *priv, int request_control); +void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert); +void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable); +int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_bytes, + int compare_8_bits); +void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv); +unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv, + unsigned int clear_mask); +unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv); +int nec7210_primary_address(const gpib_board_t *board, + struct nec7210_priv *priv, unsigned int address); +int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv, + unsigned int address, int enable); +int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result); +void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status); +void nec7210_parallel_poll_configure(gpib_board_t *board, + struct nec7210_priv *priv, unsigned int configuration); +void nec7210_parallel_poll_response(gpib_board_t *board, + struct nec7210_priv *priv, int ist); +uint8_t nec7210_serial_poll_status(gpib_board_t *board, + struct nec7210_priv *priv); +unsigned int nec7210_t1_delay(gpib_board_t *board, + struct nec7210_priv *priv, unsigned int nano_sec); +void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv); + +// utility functions +void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board); +void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board); +unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg, + unsigned int mask, unsigned int bits); +void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode); +void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv); +uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end); + +// wrappers for io functions +uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num); +uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num); +uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, + unsigned int register_num); +uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num); +void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, + unsigned int register_num); + +// interrupt service routine +irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv); +irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board, + struct nec7210_priv *priv, int status1, int status2); + +#endif //_NEC7210_H diff --git a/drivers/staging/gpib/include/nec7210_registers.h b/drivers/staging/gpib/include/nec7210_registers.h new file mode 100644 index 0000000000000000000000000000000000000000..888803dd97f9e7ac2229bff5318e7b245cdff0e8 --- /dev/null +++ b/drivers/staging/gpib/include/nec7210_registers.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _NEC7210_REGISTERS_H +#define _NEC7210_REGISTERS_H + +enum nec7210_chipset { + NEC7210, // The original + TNT4882, // NI + NAT4882, // NI + CB7210, // measurement computing + IOT7210, // iotech + IGPIB7210, // Ines + TNT5004, // NI (minor differences to TNT4882) +}; + +/* nec7210 register numbers (might need to be multiplied by + * a board-dependent offset to get actually io address offset) + */ +// write registers +enum nec7210_write_regs { + CDOR, // command/data out + IMR1, // interrupt mask 1 + IMR2, // interrupt mask 2 + SPMR, // serial poll mode + ADMR, // address mode + AUXMR, // auxiliary mode + ADR, // address + EOSR, // end-of-string + + // nec7210 has 8 registers + nec7210_num_registers = 8, +}; + +// read registers +enum nec7210_read_regs { + DIR, // data in + ISR1, // interrupt status 1 + ISR2, // interrupt status 2 + SPSR, // serial poll status + ADSR, // address status + CPTR, // command pass though + ADR0, // address 1 + ADR1, // address 2 +}; + +//bit definitions common to nec-7210 compatible registers + +// ISR1: interrupt status register 1 +enum isr1_bits { + HR_DI = (1 << 0), + HR_DO = (1 << 1), + HR_ERR = (1 << 2), + HR_DEC = (1 << 3), + HR_END = (1 << 4), + HR_DET = (1 << 5), + HR_APT = (1 << 6), + HR_CPT = (1 << 7), +}; + +// IMR1: interrupt mask register 1 +enum imr1_bits { + HR_DIIE = (1 << 0), + HR_DOIE = (1 << 1), + HR_ERRIE = (1 << 2), + HR_DECIE = (1 << 3), + HR_ENDIE = (1 << 4), + HR_DETIE = (1 << 5), + HR_APTIE = (1 << 6), + HR_CPTIE = (1 << 7), +}; + +// ISR2, interrupt status register 2 +enum isr2_bits { + HR_ADSC = (1 << 0), + HR_REMC = (1 << 1), + HR_LOKC = (1 << 2), + HR_CO = (1 << 3), + HR_REM = (1 << 4), + HR_LOK = (1 << 5), + HR_SRQI = (1 << 6), + HR_INT = (1 << 7), +}; + +// IMR2, interrupt mask register 2 +enum imr2_bits { + // all the bits in this register that enable interrupts + IMR2_ENABLE_INTR_MASK = 0x4f, + HR_ACIE = (1 << 0), + HR_REMIE = (1 << 1), + HR_LOKIE = (1 << 2), + HR_COIE = (1 << 3), + HR_DMAI = (1 << 4), + HR_DMAO = (1 << 5), + HR_SRQIE = (1 << 6), +}; + +// SPSR, serial poll status register +enum spsr_bits { + HR_PEND = (1 << 6), +}; + +// SPMR, serial poll mode register +enum spmr_bits { + HR_RSV = (1 << 6), +}; + +// ADSR, address status register +enum adsr_bits { + HR_MJMN = (1 << 0), + HR_TA = (1 << 1), + HR_LA = (1 << 2), + HR_TPAS = (1 << 3), + HR_LPAS = (1 << 4), + HR_SPMS = (1 << 5), + HR_NATN = (1 << 6), + HR_CIC = (1 << 7), +}; + +// ADMR, address mode register +enum admr_bits { + HR_ADM0 = (1 << 0), + HR_ADM1 = (1 << 1), + HR_TRM0 = (1 << 4), + HR_TRM1 = (1 << 5), + HR_TRM_EOIOE_TRIG = 0, + HR_TRM_CIC_TRIG = HR_TRM0, + HR_TRM_CIC_EOIOE = HR_TRM1, + HR_TRM_CIC_PE = HR_TRM0 | HR_TRM1, + HR_LON = (1 << 6), + HR_TON = (1 << 7), +}; + +// ADR, bits used in address0, address1 and address0/1 registers +enum adr_bits { + ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits */ + HR_DL = (1 << 5), + HR_DT = (1 << 6), + HR_ARS = (1 << 7), +}; + +// ADR1, address1 register +enum adr1_bits { + HR_EOI = (1 << 7), +}; + +// AUXMR, auxiliary mode register +enum auxmr_bits { + ICR = 0x20, + PPR = 0x60, + AUXRA = 0x80, + AUXRB = 0xa0, + AUXRE = 0xc0, +}; + +// auxra, auxiliary register A +enum auxra_bits { + HR_HANDSHAKE_MASK = 0x3, + HR_HLDA = 0x1, + HR_HLDE = 0x2, + HR_LCM = 0x3, /* auxra listen continuous */ + HR_REOS = 0x4, + HR_XEOS = 0x8, + HR_BIN = 0x10, +}; + +// auxrb, auxiliary register B +enum auxrb_bits { + HR_CPTE = (1 << 0), + HR_SPEOI = (1 << 1), + HR_TRI = (1 << 2), + HR_INV = (1 << 3), + HR_ISS = (1 << 4), +}; + +enum auxre_bits { + HR_DAC_HLD_DCAS = 0x1, /* perform DAC holdoff on receiving clear */ + HR_DAC_HLD_DTAS = 0x2, /* perform DAC holdoff on receiving trigger */ +}; + +// parallel poll register +enum ppr_bits { + HR_PPS = (1 << 3), + HR_PPU = (1 << 4), +}; + +/* 7210 Auxiliary Commands */ +enum aux_cmds { + AUX_PON = 0x0, /* Immediate Execute pon */ + AUX_CPPF = 0x1, /* Clear Parallel Poll Flag */ + AUX_CR = 0x2, /* Chip Reset */ + AUX_FH = 0x3, /* Finish Handshake */ + AUX_TRIG = 0x4, /* Trigger */ + AUX_RTL = 0x5, /* Return to local */ + AUX_SEOI = 0x6, /* Send EOI */ + AUX_NVAL = 0x7, /* Non-Valid Secondary Command or Address */ + AUX_SPPF = 0x9, /* Set Parallel Poll Flag */ + AUX_VAL = 0xf, /* Valid Secondary Command or Address */ + AUX_GTS = 0x10, /* Go To Standby */ + AUX_TCA = 0x11, /* Take Control Asynchronously */ + AUX_TCS = 0x12, /* Take Control Synchronously */ + AUX_LTN = 0x13, /* Listen */ + AUX_DSC = 0x14, /* Disable System Control */ + AUX_CIFC = 0x16, /* Clear IFC */ + AUX_CREN = 0x17, /* Clear REN */ + AUX_TCSE = 0x1a, /* Take Control Synchronously on End */ + AUX_LTNC = 0x1b, /* Listen in Continuous Mode */ + AUX_LUN = 0x1c, /* Local Unlisten */ + AUX_EPP = 0x1d, /* Execute Parallel Poll */ + AUX_SIFC = 0x1e, /* Set IFC */ + AUX_SREN = 0x1f, /* Set REN */ +}; + +#endif //_NEC7210_REGISTERS_H diff --git a/drivers/staging/gpib/include/plx9050.h b/drivers/staging/gpib/include/plx9050.h new file mode 100644 index 0000000000000000000000000000000000000000..66c56335f5c0b4aeeef29bed285b2a627dfc7792 --- /dev/null +++ b/drivers/staging/gpib/include/plx9050.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Header for plx9050 pci chip + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _PLX9050_GPIB_H +#define _PLX9050_GPIB_H + +// plx pci chip registers and bits +enum { + PLX9050_INTCSR_REG = 0x4c, + PLX9050_CNTRL_REG = 0x50 +}; + +enum plx9050_intcsr_bits { + PLX9050_LINTR1_EN_BIT = 0x1, + PLX9050_LINTR1_POLARITY_BIT = 0x2, + PLX9050_LINTR1_STATUS_BIT = 0x4, + PLX9050_LINTR2_EN_BIT = 0x8, + PLX9050_LINTR2_POLARITY_BIT = 0x10, + PLX9050_LINTR2_STATUS_BIT = 0x20, + PLX9050_PCI_INTR_EN_BIT = 0x40, + PLX9050_SOFT_INTR_BIT = 0x80, + PLX9050_LINTR1_SELECT_ENABLE_BIT = 0x100, //9052 extension + PLX9050_LINTR2_SELECT_ENABLE_BIT = 0x200, //9052 extension + PLX9050_LINTR1_EDGE_CLEAR_BIT = 0x400, //9052 extension + PLX9050_LINTR2_EDGE_CLEAR_BIT = 0x800, //9052 extension +}; + +enum plx9050_cntrl_bits { + PLX9050_WAITO_NOT_USER0_SELECT_BIT = 0x1, + PLX9050_USER0_OUTPUT_BIT = 0x2, + PLX9050_USER0_DATA_BIT = 0x4, + PLX9050_LLOCK_NOT_USER1_SELECT_BIT = 0x8, + PLX9050_USER1_OUTPUT_BIT = 0x10, + PLX9050_USER1_DATA_BIT = 0x20, + PLX9050_CS2_NOT_USER2_SELECT_BIT = 0x40, + PLX9050_USER2_OUTPUT_BIT = 0x80, + PLX9050_USER2_DATA_BIT = 0x100, + PLX9050_CS3_NOT_USER3_SELECT_BIT = 0x200, + PLX9050_USER3_OUTPUT_BIT = 0x400, + PLX9050_USER3_DATA_BIT = 0x800, + PLX9050_PCIBAR_ENABLE_MASK = 0x3000, + PLX9050_PCIBAR_MEMORY_AND_IO_ENABLE_BITS = 0x0, + PLX9050_PCIBAR_MEMORY_NO_IO_ENABLE_BITS = 0x1000, + PLX9050_PCIBAR_IO_NO_MEMORY_ENABLE_BITS = 0x2000, + PLX9050_PCIBAR_MEMORY_AND_IO_TOO_ENABLE_BITS = 0x3000, + PLX9050_PCI_READ_MODE_BIT = 0x4000, + PLX9050_PCI_READ_WITH_WRITE_FLUSH_MODE_BIT = 0x8000, + PLX9050_PCI_READ_NO_FLUSH_MODE_BIT = 0x10000, + PLX9050_PCI_READ_NO_WRITE_MODE_BIT = 0x20000, + PLX9050_PCI_WRITE_MODE_BIT = 0x40000, + PLX9050_PCI_RETRY_DELAY_MASK = 0x780000, + PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT = 0x800000, + PLX9050_EEPROM_CLOCK_BIT = 0x1000000, + PLX9050_EEPROM_CHIP_SELECT_BIT = 0x2000000, + PLX9050_WRITE_TO_EEPROM_BIT = 0x4000000, + PLX9050_READ_EEPROM_DATA_BIT = 0x8000000, + PLX9050_EEPROM_VALID_BIT = 0x10000000, + PLX9050_RELOAD_CONFIG_REGISTERS_BIT = 0x20000000, + PLX9050_PCI_SOFTWARE_RESET_BIT = 0x40000000, + PLX9050_MASK_REVISION_BIT = 0x80000000 +}; + +static inline unsigned int PLX9050_PCI_RETRY_DELAY_BITS(unsigned int clocks) +{ + return ((clocks / 8) << 19) & PLX9050_PCI_RETRY_DELAY_MASK; +} + +#endif // _PLX9050_GPIB_H diff --git a/drivers/staging/gpib/include/quancom_pci.h b/drivers/staging/gpib/include/quancom_pci.h new file mode 100644 index 0000000000000000000000000000000000000000..cdaf0d056be9e7823a7896eb7719221220230121 --- /dev/null +++ b/drivers/staging/gpib/include/quancom_pci.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Quancom pci stuff + * copyright (C) 2005 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _QUANCOM_PCI_H +#define _QUANCOM_PCI_H + +/* quancom registers */ +enum quancom_regs { + QUANCOM_IRQ_CONTROL_STATUS_REG = 0xfc, +}; + +enum quancom_irq_control_status_bits { + QUANCOM_IRQ_ASSERTED_BIT = 0x1, /* readable */ + /* (any write to the register clears the interrupt)*/ + QUANCOM_IRQ_ENABLE_BIT = 0x4, /* writeable */ +}; + +#endif // _QUANCOM_PCI_H diff --git a/drivers/staging/gpib/include/tms9914.h b/drivers/staging/gpib/include/tms9914.h new file mode 100644 index 0000000000000000000000000000000000000000..456b488212d2b7d23981618581d8fb5f5400b69b --- /dev/null +++ b/drivers/staging/gpib/include/tms9914.h @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _TMS9914_H +#define _TMS9914_H + +#include <linux/types.h> +#include <linux/interrupt.h> +#include "gpib_state_machines.h" +#include "gpib_types.h" + +enum tms9914_holdoff_mode { + TMS9914_HOLDOFF_NONE, + TMS9914_HOLDOFF_EOI, + TMS9914_HOLDOFF_ALL, +}; + +/* struct used to provide variables local to a tms9914 chip */ +struct tms9914_priv { + void *iobase; + unsigned int offset; // offset between successive tms9914 io addresses + unsigned int dma_channel; + // software copy of bits written to interrupt mask registers + u8 imr0_bits, imr1_bits; + // bits written to address mode register + u8 admr_bits; + u8 auxa_bits; // bits written to auxiliary register A + // used to keep track of board's state, bit definitions given below + unsigned long state; + u8 eos; // eos character + short eos_flags; + u8 spoll_status; + enum tms9914_holdoff_mode holdoff_mode; + unsigned int ppoll_line; + enum talker_function_state talker_state; + enum listener_function_state listener_state; + unsigned ppoll_sense : 1; + unsigned ppoll_enable : 1; + unsigned ppoll_configure_state : 1; + unsigned primary_listen_addressed : 1; + unsigned primary_talk_addressed : 1; + unsigned holdoff_on_end : 1; + unsigned holdoff_on_all : 1; + unsigned holdoff_active : 1; + // wrappers for outb, inb, readb, or writeb + u8 (*read_byte)(struct tms9914_priv *priv, unsigned int register_number); + void (*write_byte)(struct tms9914_priv *priv, u8 byte, unsigned int + register_number); +}; + +// slightly shorter way to access read_byte and write_byte +static inline u8 read_byte(struct tms9914_priv *priv, unsigned int register_number) +{ + return priv->read_byte(priv, register_number); +} + +static inline void write_byte(struct tms9914_priv *priv, u8 byte, unsigned int register_number) +{ + priv->write_byte(priv, byte, register_number); +} + +// struct tms9914_priv.state bit numbers +enum { + PIO_IN_PROGRESS_BN, // pio transfer in progress + DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress + DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress + READ_READY_BN, // board has data byte available to read + WRITE_READY_BN, // board is ready to send a data byte + COMMAND_READY_BN, // board is ready to send a command byte + RECEIVED_END_BN, // received END + BUS_ERROR_BN, // bus error + DEV_CLEAR_BN, // device clear received +}; + +// interface functions +int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read); +int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, int send_eoi, size_t *bytes_written); +int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, size_t *bytes_written); +int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int syncronous); +/* alternate version of tms9914_take_control which works around buggy tcs + * implementation. + */ +int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv, + int syncronous); +int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv); +void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv, + int request_control); +void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert); +void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable); +int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_bytes, + int compare_8_bits); +void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv); +unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv, + unsigned int clear_mask); +int tms9914_primary_address(gpib_board_t *board, + struct tms9914_priv *priv, unsigned int address); +int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv, + unsigned int address, int enable); +int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result); +void tms9914_parallel_poll_configure(gpib_board_t *board, + struct tms9914_priv *priv, uint8_t config); +void tms9914_parallel_poll_response(gpib_board_t *board, + struct tms9914_priv *priv, int ist); +void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status); +uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv); +int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv); +unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv, + unsigned int nano_sec); +void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv); + +// utility functions +void tms9914_board_reset(struct tms9914_priv *priv); +void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv); +void tms9914_release_holdoff(struct tms9914_priv *priv); +void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode); + +// wrappers for io functions +uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num); +void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num); +uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num); +void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num); + +// interrupt service routine +irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv); +irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv, + int status1, int status2); + +// tms9914 has 8 registers +enum { + ms9914_num_registers = 8, +}; + +/* tms9914 register numbers (might need to be multiplied by + * a board-dependent offset to get actually io address offset) + */ +// write registers +enum { + IMR0 = 0, /* interrupt mask 0 */ + IMR1 = 1, /* interrupt mask 1 */ + AUXCR = 3, /* auxiliary command */ + ADR = 4, // address register + SPMR = 5, // serial poll mode register + PPR = 6, /* parallel poll */ + CDOR = 7, /* data out register */ +}; + +// read registers +enum { + ISR0 = 0, /* interrupt status 0 */ + ISR1 = 1, /* interrupt status 1 */ + ADSR = 2, /* address status */ + BSR = 3, /* bus status */ + CPTR = 6, /* command pass thru */ + DIR = 7, /* data in register */ +}; + +//bit definitions common to tms9914 compatible registers + +/* ISR0 - Register bits */ +enum isr0_bits { + HR_MAC = (1 << 0), /* My Address Change */ + HR_RLC = (1 << 1), /* Remote/Local change */ + HR_SPAS = (1 << 2), /* Serial Poll active State */ + HR_END = (1 << 3), /* END (EOI or EOS) */ + HR_BO = (1 << 4), /* Byte Out */ + HR_BI = (1 << 5), /* Byte In */ +}; + +/* IMR0 - Register bits */ +enum imr0_bits { + HR_MACIE = (1 << 0), /* */ + HR_RLCIE = (1 << 1), /* */ + HR_SPASIE = (1 << 2), /* */ + HR_ENDIE = (1 << 3), /* */ + HR_BOIE = (1 << 4), /* */ + HR_BIIE = (1 << 5), /* */ +}; + +/* ISR1 - Register bits */ +enum isr1_bits { + HR_IFC = (1 << 0), /* IFC asserted */ + HR_SRQ = (1 << 1), /* SRQ asserted */ + HR_MA = (1 << 2), /* My Address */ + HR_DCAS = (1 << 3), /* Device Clear active State */ + HR_APT = (1 << 4), /* Address pass Through */ + HR_UNC = (1 << 5), /* Unrecognized Command */ + HR_ERR = (1 << 6), /* Data Transmission Error */ + HR_GET = (1 << 7), /* Group execute Trigger */ +}; + +/* IMR1 - Register bits */ +enum imr1_bits { + HR_IFCIE = (1 << 0), /* */ + HR_SRQIE = (1 << 1), /* */ + HR_MAIE = (1 << 2), /* */ + HR_DCASIE = (1 << 3), /* */ + HR_APTIE = (1 << 4), /* */ + HR_UNCIE = (1 << 5), /* */ + HR_ERRIE = (1 << 6), /* */ + HR_GETIE = (1 << 7), /* */ +}; + +/* ADSR - Register bits */ +enum adsr_bits { + HR_ULPA = (1 << 0), /* Store last address LSB */ + HR_TA = (1 << 1), /* Talker Adressed */ + HR_LA = (1 << 2), /* Listener adressed */ + HR_TPAS = (1 << 3), /* talker primary address state */ + HR_LPAS = (1 << 4), /* listener " */ + HR_ATN = (1 << 5), /* ATN active */ + HR_LLO = (1 << 6), /* LLO active */ + HR_REM = (1 << 7), /* REM active */ +}; + +/* ADR - Register bits */ +enum adr_bits { + ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits for ADR */ + HR_DAT = (1 << 5), /* disable talker */ + HR_DAL = (1 << 6), /* disable listener */ + HR_EDPA = (1 << 7), /* enable dual primary addressing */ +}; + +enum bus_status_bits { + BSR_REN_BIT = 0x1, + BSR_IFC_BIT = 0x2, + BSR_SRQ_BIT = 0x4, + BSR_EOI_BIT = 0x8, + BSR_NRFD_BIT = 0x10, + BSR_NDAC_BIT = 0x20, + BSR_DAV_BIT = 0x40, + BSR_ATN_BIT = 0x80, +}; + +/*---------------------------------------------------------*/ +/* TMS 9914 Auxiliary Commands */ +/*---------------------------------------------------------*/ + +enum aux_cmd_bits { + AUX_CS = 0x80, /* set bit instead of clearing it, used with commands marked 'd' below */ + AUX_CHIP_RESET = 0x0, /* d Chip reset */ + AUX_INVAL = 0x1, // release dac holdoff, invalid command byte + AUX_VAL = (AUX_INVAL | AUX_CS), // release dac holdoff, valid command byte + AUX_RHDF = 0x2, /* X Release RFD holdoff */ + AUX_HLDA = 0x3, /* d holdoff on all data */ + AUX_HLDE = 0x4, /* d holdoff on EOI only */ + AUX_NBAF = 0x5, /* X Set new byte available false */ + AUX_FGET = 0x6, /* d force GET */ + AUX_RTL = 0x7, /* d return to local */ + AUX_SEOI = 0x8, /* X send EOI with next byte */ + AUX_LON = 0x9, /* d Listen only */ + AUX_TON = 0xa, /* d Talk only */ + AUX_GTS = 0xb, /* X goto standby */ + AUX_TCA = 0xc, /* X take control asynchronously */ + AUX_TCS = 0xd, /* X take " synchronously */ + AUX_RPP = 0xe, /* d Request parallel poll */ + AUX_SIC = 0xf, /* d send interface clear */ + AUX_SRE = 0x10, /* d send remote enable */ + AUX_RQC = 0x11, /* X request control */ + AUX_RLC = 0x12, /* X release control */ + AUX_DAI = 0x13, /* d disable all interrupts */ + AUX_PTS = 0x14, /* X pass through next secondary */ + AUX_STDL = 0x15, /* d short T1 delay */ + AUX_SHDW = 0x16, /* d shadow handshake */ + AUX_VSTDL = 0x17, /* d very short T1 delay (smj9914 extension) */ + AUX_RSV2 = 0x18, /* d request service bit 2 (smj9914 extension) */ +}; + +#endif //_TMS9914_H diff --git a/drivers/staging/gpib/include/tnt4882_registers.h b/drivers/staging/gpib/include/tnt4882_registers.h new file mode 100644 index 0000000000000000000000000000000000000000..1b1441cd03d50ec23dca803be5853601b0d8addc --- /dev/null +++ b/drivers/staging/gpib/include/tnt4882_registers.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002, 2004 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _TNT4882_REGISTERS_H +#define _TNT4882_REGISTERS_H + +// tnt4882 register offsets +enum { + ACCWR = 0x5, + // offset of auxiliary command register in 9914 mode + AUXCR = 0x6, + INTRT = 0x7, + // register number for auxiliary command register when swap bit is set (9914 mode) + SWAPPED_AUXCR = 0xa, + HSSEL = 0xd, // handshake select register + CNT2 = 0x9, + CNT3 = 0xb, + CFG = 0x10, + SASR = 0x1b, + IMR0 = 0x1d, + IMR3 = 0x12, + CNT0 = 0x14, + CNT1 = 0x16, + KEYREG = 0x17, // key control register (7210 mode only) + CSR = KEYREG, + FIFOB = 0x18, + FIFOA = 0x19, + CCR = 0x1a, // carry cycle register + CMDR = 0x1c, // command register + TIMER = 0x1e, // timer register + + STS1 = 0x10, /* T488 Status Register 1 */ + STS2 = 0x1c, /* T488 Status Register 2 */ + ISR0 = IMR0, + ISR3 = 0x1a, /* T488 Interrupt Status Register 3 */ + BCR = 0x1f, /* bus control/status register */ + BSR = BCR, +}; + +enum { + tnt_pagein_offset = 0x11, +}; + +/*============================================================*/ + +/* TURBO-488 registers bit definitions */ + +enum bus_control_status_bits { + BCSR_REN_BIT = 0x1, + BCSR_IFC_BIT = 0x2, + BCSR_SRQ_BIT = 0x4, + BCSR_EOI_BIT = 0x8, + BCSR_NRFD_BIT = 0x10, + BCSR_NDAC_BIT = 0x20, + BCSR_DAV_BIT = 0x40, + BCSR_ATN_BIT = 0x80, +}; + +/* CFG -- Configuration Register (write only) */ +enum cfg_bits { + TNT_COMMAND = 0x80, /* bytes are command bytes instead of data bytes + * (tnt4882 one-chip and newer only?) + */ + TNT_TLCHE = (1 << 6), /* halt transfer on imr0, imr1, or imr2 interrupt */ + TNT_IN = (1 << 5), /* transfer is GPIB read */ + TNT_A_B = (1 << 4), /* order to use fifos 1=fifo A first(big endian), + * 0=fifo b first(little endian) + */ + TNT_CCEN = (1 << 3), /* enable carry cycle */ + TNT_TMOE = (1 << 2), /* enable CPU bus time limit */ + TNT_TIM_BYTN = (1 << 1), /* tmot reg is: 1=125ns clocks, 0=num bytes */ + TNT_B_16BIT = (1 << 0), /* 1=FIFO is 16-bit register, 0=8-bit */ +}; + +/* CMDR -- Command Register */ +enum cmdr_bits { + CLRSC = 0x2, /* clear the system controller bit */ + SETSC = 0x3, /* set the system controller bit */ + GO = 0x4, /* start fifos */ + STOP = 0x8, /* stop fifos */ + RESET_FIFO = 0x10, /* reset the FIFOs */ + SOFT_RESET = 0x22, /* issue a software reset */ + HARD_RESET = 0x40 /* 500x only? */ +}; + +/* HSSEL -- handshake select register (write only) */ +enum hssel_bits { + TNT_ONE_CHIP_BIT = 0x1, + NODMA = 0x10, + TNT_GO2SIDS_BIT = 0x20, +}; + +/* IMR0 -- Interrupt Mode Register 0 */ +enum imr0_bits { + TNT_SYNCIE_BIT = 0x1, /* handshake sync */ + TNT_TOIE_BIT = 0x2, /* timeout */ + TNT_ATNIE_BIT = 0x4, /* ATN interrupt */ + TNT_IFCIE_BIT = 0x8, /* interface clear interrupt */ + TNT_BTO_BIT = 0x10, /* byte timeout */ + TNT_NLEN_BIT = 0x20, /* treat new line as EOS char */ + TNT_STBOIE_BIT = 0x40, /* status byte out */ + TNT_IMR0_ALWAYS_BITS = 0x80, /* always set this bit on write */ +}; + +/* ISR0 -- Interrupt Status Register 0 */ +enum isr0_bits { + TNT_SYNC_BIT = 0x1, /* handshake sync */ + TNT_TO_BIT = 0x2, /* timeout */ + TNT_ATNI_BIT = 0x4, /* ATN interrupt */ + TNT_IFCI_BIT = 0x8, /* interface clear interrupt */ + TNT_EOS_BIT = 0x10, /* end of string */ + TNT_NL_BIT = 0x20, /* new line receive */ + TNT_STBO_BIT = 0x40, /* status byte out */ + TNT_NBA_BIT = 0x80, /* new byte available */ +}; + +/* ISR3 -- Interrupt Status Register 3 (read only) */ +enum isr3_bits { + HR_DONE = (1 << 0), /* transfer done */ + HR_TLCI = (1 << 1), /* isr0, isr1, or isr2 interrupt asserted */ + HR_NEF = (1 << 2), /* NOT empty fifo */ + HR_NFF = (1 << 3), /* NOT full fifo */ + HR_STOP = (1 << 4), /* fifo empty or STOP command issued */ + HR_SRQI_CIC = (1 << 5), /* SRQ asserted and we are CIC (500x only?)*/ + HR_INTR = (1 << 7), /* isr3 interrupt active */ +}; + +enum keyreg_bits { + MSTD = 0x20, // enable 350ns T1 delay +}; + +/* STS1 -- Status Register 1 (read only) */ +enum sts1_bits { + S_DONE = 0x80, /* DMA done */ + S_SC = 0x40, /* is system controller */ + S_IN = 0x20, /* DMA in (to memory) */ + S_DRQ = 0x10, /* DRQ line (for diagnostics) */ + S_STOP = 0x08, /* DMA stopped */ + S_NDAV = 0x04, /* inverse of DAV */ + S_HALT = 0x02, /* status of transfer machine */ + S_GSYNC = 0x01, /* indicates if GPIB is in sync w I/O */ +}; + +/* STS2 -- Status Register 2 */ +enum sts2_bits { + AFFN = (1 << 3), /* "A full FIFO NOT" (0=FIFO full) */ + AEFN = (1 << 2), /* "A empty FIFO NOT" (0=FIFO empty) */ + BFFN = (1 << 1), /* "B full FIFO NOT" (0=FIFO full) */ + BEFN = (1 << 0), /* "B empty FIFO NOT" (0=FIFO empty) */ +}; + +// Auxiliary commands +enum tnt4882_aux_cmds { + AUX_9914 = 0x15, // switch to 9914 mode + AUX_REQT = 0x18, + AUX_REQF = 0x19, + AUX_PAGEIN = 0x50, /* page in alternate registers */ + AUX_HLDI = 0x51, // rfd holdoff immediately + AUX_CLEAR_END = 0x55, + AUX_7210 = 0x99, // switch to 7210 mode +}; + +enum tnt4882_aux_regs { + AUXRG = 0x40, + AUXRI = 0xe0, +}; + +enum auxg_bits { + /* no talking when no listeners bit (prevents bus errors when data written at wrong time) */ + NTNL_BIT = 0x8, + RPP2_BIT = 0x4, /* set/clear local rpp message */ + CHES_BIT = 0x1, /*clear holdoff on end select bit*/ +}; + +enum auxi_bits { + SISB = 0x1, // static interrupt bits (don't clear isr1, isr2 on read) + PP2 = 0x4, // ignore remote parallel poll configuration + USTD = 0x8, // ultra short (1100 nanosec) T1 delay +}; + +enum sasr_bits { + ACRDY_BIT = 0x4, /* acceptor ready state */ + ADHS_BIT = 0x8, /* acceptor data holdoff state */ + ANHS2_BIT = 0x10, /* acceptor not ready holdoff immediately state */ + ANHS1_BIT = 0x20, /* acceptor not ready holdoff state */ + AEHS_BIT = 0x40, /* acceptor end holdoff state */ +}; + +#endif // _TNT4882_REGISTERS_H diff --git a/drivers/staging/gpib/ines/Makefile b/drivers/staging/gpib/ines/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cdcaa59a4e39c5f3c0a4bfd5f16122d6a872ef38 --- /dev/null +++ b/drivers/staging/gpib/ines/Makefile @@ -0,0 +1,4 @@ +ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA +obj-m += ines_gpib.o + + diff --git a/drivers/staging/gpib/ines/ines.h b/drivers/staging/gpib/ines/ines.h new file mode 100644 index 0000000000000000000000000000000000000000..7e8302619998fe05611221a7a6af4d126d105e87 --- /dev/null +++ b/drivers/staging/gpib/ines/ines.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * Header for ines GPIB boards + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _INES_GPIB_H +#define _INES_GPIB_H + +#include "nec7210.h" +#include "gpibP.h" +#include "plx9050.h" +#include "amcc5920.h" +#include "quancom_pci.h" +#include <linux/interrupt.h> + +enum ines_pci_chip { + PCI_CHIP_NONE, + PCI_CHIP_PLX9050, + PCI_CHIP_AMCC5920, + PCI_CHIP_QUANCOM, + PCI_CHIP_QUICKLOGIC5030, +}; + +struct ines_priv { + struct nec7210_priv nec7210_priv; + struct pci_dev *pci_device; + // base address for plx9052 pci chip + unsigned long plx_iobase; + // base address for amcc5920 pci chip + unsigned long amcc_iobase; + unsigned int irq; + enum ines_pci_chip pci_chip_type; + u8 extend_mode_bits; +}; + +// interfaces +extern gpib_interface_t ines_pci_interface; +extern gpib_interface_t ines_pci_accel_interface; +extern gpib_interface_t ines_pcmcia_interface; +extern gpib_interface_t ines_pcmcia_accel_interface; +extern gpib_interface_t ines_pcmcia_unaccel_interface; + +// interface functions +int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read); +int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +int ines_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read); +int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written); +int ines_take_control(gpib_board_t *board, int synchronous); +int ines_go_to_standby(gpib_board_t *board); +void ines_request_system_control(gpib_board_t *board, int request_control); +void ines_interface_clear(gpib_board_t *board, int assert); +void ines_remote_enable(gpib_board_t *board, int enable); +int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits); +void ines_disable_eos(gpib_board_t *board); +unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask); +int ines_primary_address(gpib_board_t *board, unsigned int address); +int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable); +int ines_parallel_poll(gpib_board_t *board, uint8_t *result); +void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config); +void ines_parallel_poll_response(gpib_board_t *board, int ist); +void ines_serial_poll_response(gpib_board_t *board, uint8_t status); +uint8_t ines_serial_poll_status(gpib_board_t *board); +int ines_line_status(const gpib_board_t *board); +unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec); +void ines_return_to_local(gpib_board_t *board); + +// interrupt service routines +irqreturn_t ines_pci_interrupt(int irq, void *arg); +irqreturn_t ines_interrupt(gpib_board_t *board); + +// utility functions +void ines_free_private(gpib_board_t *board); +int ines_generic_attach(gpib_board_t *board); +void ines_online(struct ines_priv *priv, const gpib_board_t *board, int use_accel); +void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count); + +/* inb/outb wrappers */ +static inline unsigned int ines_inb(struct ines_priv *priv, unsigned int register_number) +{ + return inb((unsigned long)(priv->nec7210_priv.iobase) + + register_number * priv->nec7210_priv.offset); +} + +static inline void ines_outb(struct ines_priv *priv, unsigned int value, + unsigned int register_number) +{ + outb(value, (unsigned long)(priv->nec7210_priv.iobase) + + register_number * priv->nec7210_priv.offset); +} + +// pcmcia init/cleanup + +int ines_pcmcia_init_module(void); +void ines_pcmcia_cleanup_module(void); + +enum ines_regs { + // read + FIFO_STATUS = 0x8, + ISR3 = 0x9, + ISR4 = 0xa, + IN_FIFO_COUNT = 0x10, + OUT_FIFO_COUNT = 0x11, + EXTEND_STATUS = 0xf, + + // write + XDMA_CONTROL = 0x8, + IMR3 = ISR3, + IMR4 = ISR4, + IN_FIFO_WATERMARK = IN_FIFO_COUNT, + OUT_FIFO_WATERMARK = OUT_FIFO_COUNT, + EXTEND_MODE = 0xf, + + // read-write + XFER_COUNT_LOWER = 0xb, + XFER_COUNT_UPPER = 0xc, + BUS_CONTROL_MONITOR = 0x13, +}; + +enum isr3_imr3_bits { + HW_TIMEOUT_BIT = 0x1, + XFER_COUNT_BIT = 0x2, + CMD_RECEIVED_BIT = 0x4, + TCT_RECEIVED_BIT = 0x8, + IFC_ACTIVE_BIT = 0x10, + ATN_ACTIVE_BIT = 0x20, + FIFO_ERROR_BIT = 0x40, +}; + +enum isr4_imr4_bits { + IN_FIFO_WATERMARK_BIT = 0x1, + OUT_FIFO_WATERMARK_BIT = 0x2, + IN_FIFO_FULL_BIT = 0x4, + OUT_FIFO_EMPTY_BIT = 0x8, + IN_FIFO_READY_BIT = 0x10, + OUT_FIFO_READY_BIT = 0x20, + IN_FIFO_EXIT_WATERMARK_BIT = 0x40, + OUT_FIFO_EXIT_WATERMARK_BIT = 0x80, +}; + +enum extend_mode_bits { + TR3_TRIG_ENABLE_BIT = 0x1, // enable generation of trigger pulse T/R3 pin + // clear message available status bit when chip writes byte with EOI true + MAV_ENABLE_BIT = 0x2, + EOS1_ENABLE_BIT = 0x4, // enable eos register 1 + EOS2_ENABLE_BIT = 0x8, // enable eos register 2 + EOIDIS_BIT = 0x10, // disable EOI interrupt when doing rfd holdoff on end? + XFER_COUNTER_ENABLE_BIT = 0x20, + XFER_COUNTER_OUTPUT_BIT = 0x40, // use counter for output, clear for input + // when xfer counter hits 0, assert EOI on write or RFD holdoff on read + LAST_BYTE_HANDLING_BIT = 0x80, +}; + +enum extend_status_bits { + OUTPUT_MESSAGE_IN_PROGRESS_BIT = 0x1, + SCSEL_BIT = 0x2, // statue of SCSEL pin + LISTEN_DISABLED = 0x4, + IN_FIFO_EMPTY_BIT = 0x8, + OUT_FIFO_FULL_BIT = 0x10, +}; + +// ines adds fifo enable bits to address mode register +enum ines_admr_bits { + IN_FIFO_ENABLE_BIT = 0x8, + OUT_FIFO_ENABLE_BIT = 0x4, +}; + +enum xdma_control_bits { + DMA_OUTPUT_BIT = 0x1, // use dma for output, clear for input + ENABLE_SYNC_DMA_BIT = 0x2, + DMA_ACCESS_EVERY_CYCLE = 0x4,// dma accesses fifo every cycle, clear for every other cycle + DMA_16BIT = 0x8, // clear for 8 bit transfers +}; + +enum bus_control_monitor_bits { + BCM_DAV_BIT = 0x1, + BCM_NRFD_BIT = 0x2, + BCM_NDAC_BIT = 0x4, + BCM_IFC_BIT = 0x8, + BCM_ATN_BIT = 0x10, + BCM_SRQ_BIT = 0x20, + BCM_REN_BIT = 0x40, + BCM_EOI_BIT = 0x80, +}; + +enum ines_aux_reg_bits { + INES_AUXD = 0x40, +}; + +enum ines_aux_cmds { + INES_RFD_HLD_IMMEDIATE = 0x4, + INES_AUX_CLR_OUT_FIFO = 0x5, + INES_AUX_CLR_IN_FIFO = 0x6, + INES_AUX_XMODE = 0xa, +}; + +enum ines_auxd_bits { + INES_FOLLOWING_T1_MASK = 0x3, + INES_FOLLOWING_T1_500ns = 0x0, + INES_FOLLOWING_T1_350ns = 0x1, + INES_FOLLOWING_T1_250ns = 0x2, + INES_INITIAL_TI_MASK = 0xc, + INES_INITIAL_T1_2000ns = 0x0, + INES_INITIAL_T1_1100ns = 0x4, + INES_INITIAL_T1_700ns = 0x8, + INES_T6_2us = 0x0, + INES_T6_50us = 0x10, +}; + +#endif // _INES_GPIB_H diff --git a/drivers/staging/gpib/ines/ines_gpib.c b/drivers/staging/gpib/ines/ines_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..9d8387c3bf019bd36a68da540a3ea5d27f40f7cf --- /dev/null +++ b/drivers/staging/gpib/ines/ines_gpib.c @@ -0,0 +1,1464 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 1999 Axel Dziemba (axel.dziemba@ines.de) + * (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "ines.h" + +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/bitops.h> +#include <asm/dma.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include "gpib_pci_ids.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for Ines iGPIB 72010"); + +int ines_line_status(const gpib_board_t *board) +{ + int status = ValidALL; + int bcm_bits; + struct ines_priv *ines_priv; + struct nec7210_priv *nec_priv; + + ines_priv = board->private_data; + nec_priv = &ines_priv->nec7210_priv; + + bcm_bits = ines_inb(ines_priv, BUS_CONTROL_MONITOR); + + if (bcm_bits & BCM_REN_BIT) + status |= BusREN; + if (bcm_bits & BCM_IFC_BIT) + status |= BusIFC; + if (bcm_bits & BCM_SRQ_BIT) + status |= BusSRQ; + if (bcm_bits & BCM_EOI_BIT) + status |= BusEOI; + if (bcm_bits & BCM_NRFD_BIT) + status |= BusNRFD; + if (bcm_bits & BCM_NDAC_BIT) + status |= BusNDAC; + if (bcm_bits & BCM_DAV_BIT) + status |= BusDAV; + if (bcm_bits & BCM_ATN_BIT) + status |= BusATN; + + return status; +} + +void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count) +{ + if (count > 0xffff) { + pr_err("ines: bug! tried to set xfer counter > 0xffff\n"); + return; + } + ines_outb(priv, (count >> 8) & 0xff, XFER_COUNT_UPPER); + ines_outb(priv, count & 0xff, XFER_COUNT_LOWER); +} + +unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct ines_priv *ines_priv = board->private_data; + struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; + unsigned int retval; + + retval = nec7210_t1_delay(board, nec_priv, nano_sec); + + if (nano_sec <= 250) { + write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_250ns | + INES_INITIAL_T1_2000ns, AUXMR); + retval = 250; + } else if (nano_sec <= 350) { + write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_350ns | + INES_INITIAL_T1_2000ns, AUXMR); + retval = 350; + } else { + write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_500ns | + INES_INITIAL_T1_2000ns, AUXMR); + retval = 500; + } + + return retval; +} + +static inline unsigned short num_in_fifo_bytes(struct ines_priv *ines_priv) +{ + return ines_inb(ines_priv, IN_FIFO_COUNT); +} + +static ssize_t pio_read(gpib_board_t *board, struct ines_priv *ines_priv, uint8_t *buffer, + size_t length, size_t *nbytes) +{ + ssize_t retval = 0; + unsigned int num_fifo_bytes, i; + struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; + + *nbytes = 0; + while (*nbytes < length) { + if (wait_event_interruptible(board->wait, + num_in_fifo_bytes(ines_priv) || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_warn("gpib: pio read wait interrupted\n"); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + return -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + return -EINTR; + + num_fifo_bytes = num_in_fifo_bytes(ines_priv); + if (num_fifo_bytes + *nbytes > length) { + pr_warn("ines: counter allowed %li extra byte(s)\n", + (long)(num_fifo_bytes - (length - *nbytes))); + num_fifo_bytes = length - *nbytes; + } + for (i = 0; i < num_fifo_bytes; i++) + buffer[(*nbytes)++] = read_byte(nec_priv, DIR); + if (test_bit(RECEIVED_END_BN, &nec_priv->state) && + num_in_fifo_bytes(ines_priv) == 0) + break; + if (need_resched()) + schedule(); + } + /* make sure RECEIVED_END is in sync */ + ines_interrupt(board); + return retval; +} + +int ines_accel_read(gpib_board_t *board, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval = 0; + struct ines_priv *ines_priv = board->private_data; + struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; + int counter_setting; + + *end = 0; + *bytes_read = 0; + if (length == 0) + return 0; + + clear_bit(DEV_CLEAR_BN, &nec_priv->state); + + write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); + + //clear in fifo + nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, 0); + nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, IN_FIFO_ENABLE_BIT); + + ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT; + ines_priv->extend_mode_bits &= ~XFER_COUNTER_OUTPUT_BIT & ~XFER_COUNTER_ENABLE_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + + counter_setting = length - num_in_fifo_bytes(ines_priv); + if (counter_setting > 0) { + ines_set_xfer_counter(ines_priv, length); + ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + + // holdoff on END + nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); + /* release rfd holdoff */ + write_byte(nec_priv, AUX_FH, AUXMR); + } + + retval = pio_read(board, ines_priv, buffer, length, bytes_read); + ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + if (retval < 0) { + write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); + return retval; + } + if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) + *end = 1; + + return retval; +} + +static const int out_fifo_size = 0xff; + +static inline unsigned short num_out_fifo_bytes(struct ines_priv *ines_priv) +{ + return ines_inb(ines_priv, OUT_FIFO_COUNT); +} + +static int ines_write_wait(gpib_board_t *board, struct ines_priv *ines_priv, + unsigned int fifo_threshold) +{ + struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; + + // wait until byte is ready to be sent + if (wait_event_interruptible(board->wait, + num_out_fifo_bytes(ines_priv) < fifo_threshold || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted\n"); + return -ERESTARTSYS; + } + if (test_bit(BUS_ERROR_BN, &nec_priv->state)) + return -EIO; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) + return -EINTR; + if (test_bit(TIMO_NUM, &board->status)) + return -ETIMEDOUT; + + return 0; +} + +int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + size_t count = 0; + ssize_t retval = 0; + struct ines_priv *ines_priv = board->private_data; + struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; + unsigned int num_bytes, i; + + *bytes_written = 0; + //clear out fifo + nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, 0); + nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, OUT_FIFO_ENABLE_BIT); + + ines_priv->extend_mode_bits |= XFER_COUNTER_OUTPUT_BIT; + ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; + ines_priv->extend_mode_bits &= ~LAST_BYTE_HANDLING_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + + ines_set_xfer_counter(ines_priv, length); + if (send_eoi) + ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT; + ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + + while (count < length) { + retval = ines_write_wait(board, ines_priv, out_fifo_size); + if (retval < 0) + break; + + num_bytes = out_fifo_size - num_out_fifo_bytes(ines_priv); + if (num_bytes + count > length) + num_bytes = length - count; + for (i = 0; i < num_bytes; i++) + write_byte(nec_priv, buffer[count++], CDOR); + } + if (retval < 0) { + ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + *bytes_written = length - num_out_fifo_bytes(ines_priv); + return retval; + } + // wait last byte has been sent + retval = ines_write_wait(board, ines_priv, 1); + ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + *bytes_written = length - num_out_fifo_bytes(ines_priv); + + return retval; +} + +irqreturn_t ines_pci_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct ines_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + + if (priv->pci_chip_type == PCI_CHIP_QUANCOM) { + if ((inb((unsigned long)nec_priv->iobase + + QUANCOM_IRQ_CONTROL_STATUS_REG) & + QUANCOM_IRQ_ASSERTED_BIT)) + outb(QUANCOM_IRQ_ENABLE_BIT, (unsigned long)(nec_priv->iobase) + + QUANCOM_IRQ_CONTROL_STATUS_REG); + } + + return ines_interrupt(board); +} + +irqreturn_t ines_interrupt(gpib_board_t *board) +{ + struct ines_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + unsigned int isr3_bits, isr4_bits; + unsigned long flags; + int wake = 0; + + spin_lock_irqsave(&board->spinlock, flags); + + nec7210_interrupt(board, nec_priv); + isr3_bits = ines_inb(priv, ISR3); + isr4_bits = ines_inb(priv, ISR4); + if (isr3_bits & IFC_ACTIVE_BIT) { + push_gpib_event(board, EventIFC); + wake++; + } + if (isr3_bits & FIFO_ERROR_BIT) + pr_err("ines gpib: fifo error\n"); + if (isr3_bits & XFER_COUNT_BIT) + wake++; + + if (isr4_bits & (IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT | OUT_FIFO_WATERMARK_BIT | + OUT_FIFO_EMPTY_BIT)) + wake++; + + if (wake) + wake_up_interruptible(&board->wait); + spin_unlock_irqrestore(&board->spinlock, flags); + return IRQ_HANDLED; +} + +static int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void ines_pci_detach(gpib_board_t *board); +static void ines_isa_detach(gpib_board_t *board); + +enum ines_pci_vendor_ids { + PCI_VENDOR_ID_INES_QUICKLOGIC = 0x16da +}; + +enum ines_pci_device_ids { + PCI_DEVICE_ID_INES_GPIB_AMCC = 0x8507, + PCI_DEVICE_ID_INES_GPIB_QL5030 = 0x11, +}; + +enum ines_pci_subdevice_ids { + PCI_SUBDEVICE_ID_INES_GPIB = 0x1072 +}; + +static struct pci_device_id ines_pci_table[] = { + {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, + PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0}, + {PCI_VENDOR_ID_AMCC, PCI_DEVICE_ID_INES_GPIB_AMCC, PCI_VENDOR_ID_AMCC, + PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0}, + {PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030, + PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030, 0, 0, 0}, + {PCI_DEVICE(PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB)}, + {0} +}; +MODULE_DEVICE_TABLE(pci, ines_pci_table); + +struct ines_pci_id { + unsigned int vendor_id; + unsigned int device_id; + int subsystem_vendor_id; + int subsystem_device_id; + unsigned int gpib_region; + unsigned int io_offset; + enum ines_pci_chip pci_chip_type; +}; + +struct ines_pci_id pci_ids[] = { + {vendor_id: PCI_VENDOR_ID_PLX, + device_id : PCI_DEVICE_ID_PLX_9050, + subsystem_vendor_id : PCI_VENDOR_ID_PLX, + subsystem_device_id : PCI_SUBDEVICE_ID_INES_GPIB, + gpib_region : 2, + io_offset : 1, + pci_chip_type : PCI_CHIP_PLX9050, + }, + {vendor_id: PCI_VENDOR_ID_AMCC, + device_id : PCI_DEVICE_ID_INES_GPIB_AMCC, + subsystem_vendor_id : PCI_VENDOR_ID_AMCC, + subsystem_device_id : PCI_SUBDEVICE_ID_INES_GPIB, + gpib_region : 1, + io_offset : 1, + pci_chip_type : PCI_CHIP_AMCC5920, + }, + {vendor_id: PCI_VENDOR_ID_INES_QUICKLOGIC, + device_id : PCI_DEVICE_ID_INES_GPIB_QL5030, + subsystem_vendor_id : PCI_VENDOR_ID_INES_QUICKLOGIC, + subsystem_device_id : PCI_DEVICE_ID_INES_GPIB_QL5030, + gpib_region : 1, + io_offset : 1, + pci_chip_type : PCI_CHIP_QUICKLOGIC5030, + }, + {vendor_id: PCI_VENDOR_ID_QUANCOM, + device_id : PCI_DEVICE_ID_QUANCOM_GPIB, + subsystem_vendor_id : -1, + subsystem_device_id : -1, + gpib_region : 0, + io_offset : 4, + pci_chip_type : PCI_CHIP_QUANCOM, + }, +}; + +static const int num_pci_chips = ARRAY_SIZE(pci_ids); + +// wrappers for interface functions +int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +{ + struct ines_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + ssize_t retval; + int dummy; + + retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); + if (retval < 0) { + write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); + + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + + nec7210_read_data_in(board, nec_priv, &dummy); + } + return retval; +} + +int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +int ines_take_control(gpib_board_t *board, int synchronous) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +int ines_go_to_standby(gpib_board_t *board) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +void ines_request_system_control(gpib_board_t *board, int request_control) +{ + struct ines_priv *priv = board->private_data; + + nec7210_request_system_control(board, &priv->nec7210_priv, request_control); +} + +void ines_interface_clear(gpib_board_t *board, int assert) +{ + struct ines_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +void ines_remote_enable(gpib_board_t *board, int enable) +{ + struct ines_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +void ines_disable_eos(gpib_board_t *board) +{ + struct ines_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); +} + +int ines_primary_address(gpib_board_t *board, unsigned int address) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +int ines_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_parallel_poll(board, &priv->nec7210_priv, result); +} + +void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + struct ines_priv *priv = board->private_data; + + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); +} + +void ines_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct ines_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +void ines_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct ines_priv *priv = board->private_data; + + nec7210_serial_poll_response(board, &priv->nec7210_priv, status); +} + +uint8_t ines_serial_poll_status(gpib_board_t *board) +{ + struct ines_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +void ines_return_to_local(gpib_board_t *board) +{ + struct ines_priv *priv = board->private_data; + + nec7210_return_to_local(board, &priv->nec7210_priv); +} + +gpib_interface_t ines_pci_unaccel_interface = { +name: "ines_pci_unaccel", +attach : ines_pci_attach, +detach : ines_pci_detach, +read : ines_read, +write : ines_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +gpib_interface_t ines_pci_interface = { +name: "ines_pci", +attach : ines_pci_accel_attach, +detach : ines_pci_detach, +read : ines_accel_read, +write : ines_accel_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +gpib_interface_t ines_pci_accel_interface = { +name: "ines_pci_accel", +attach : ines_pci_accel_attach, +detach : ines_pci_detach, +read : ines_accel_read, +write : ines_accel_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +gpib_interface_t ines_isa_interface = { +name: "ines_isa", +attach : ines_isa_attach, +detach : ines_isa_detach, +read : ines_accel_read, +write : ines_accel_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +static int ines_allocate_private(gpib_board_t *board) +{ + struct ines_priv *priv; + + board->private_data = kmalloc(sizeof(struct ines_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + priv = board->private_data; + memset(priv, 0, sizeof(struct ines_priv)); + init_nec7210_private(&priv->nec7210_priv); + return 0; +} + +void ines_free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +int ines_generic_attach(gpib_board_t *board) +{ + struct ines_priv *ines_priv; + struct nec7210_priv *nec_priv; + + board->status = 0; + + if (ines_allocate_private(board)) + return -ENOMEM; + ines_priv = board->private_data; + nec_priv = &ines_priv->nec7210_priv; + nec_priv->read_byte = nec7210_ioport_read_byte; + nec_priv->write_byte = nec7210_ioport_write_byte; + nec_priv->offset = 1; + nec_priv->type = IGPIB7210; + ines_priv->pci_chip_type = PCI_CHIP_NONE; + + return 0; +} + +void ines_online(struct ines_priv *ines_priv, const gpib_board_t *board, int use_accel) +{ + struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; + + /* ines doesn't seem to use internal count register */ + write_byte(nec_priv, ICR | 0, AUXMR); + + write_byte(nec_priv, INES_AUX_XMODE, AUXMR); + write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); + + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + + write_byte(nec_priv, INES_AUXD | 0, AUXMR); + ines_outb(ines_priv, 0, XDMA_CONTROL); + ines_priv->extend_mode_bits = 0; + ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); + if (use_accel) { + ines_outb(ines_priv, 0x80, OUT_FIFO_WATERMARK); + ines_outb(ines_priv, 0x80, IN_FIFO_WATERMARK); + ines_outb(ines_priv, IFC_ACTIVE_BIT | ATN_ACTIVE_BIT | + FIFO_ERROR_BIT | XFER_COUNT_BIT, IMR3); + ines_outb(ines_priv, IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT | + OUT_FIFO_WATERMARK_BIT | OUT_FIFO_EMPTY_BIT, IMR4); + } else { + nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT | OUT_FIFO_ENABLE_BIT, 0); + ines_outb(ines_priv, IFC_ACTIVE_BIT | FIFO_ERROR_BIT, IMR3); + ines_outb(ines_priv, 0, IMR4); + } + + nec7210_board_online(nec_priv, board); + if (use_accel) + nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, 0); +} + +static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct ines_priv *ines_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + int retval; + struct ines_pci_id found_id; + unsigned int i; + struct pci_dev *pdev; + + memset(&found_id, 0, sizeof(found_id)); + + retval = ines_generic_attach(board); + if (retval) + return retval; + + ines_priv = board->private_data; + nec_priv = &ines_priv->nec7210_priv; + + // find board + ines_priv->pci_device = NULL; + for (i = 0; i < num_pci_chips && !ines_priv->pci_device; i++) { + pdev = NULL; + do { + if (pci_ids[i].subsystem_vendor_id >= 0 && + pci_ids[i].subsystem_device_id >= 0) + pdev = pci_get_subsys(pci_ids[i].vendor_id, pci_ids[i].device_id, + pci_ids[i].subsystem_vendor_id, + pci_ids[i].subsystem_device_id, pdev); + else + pdev = pci_get_device(pci_ids[i].vendor_id, pci_ids[i].device_id, + pdev); + if (!pdev) + break; + if (config->pci_bus >= 0 && config->pci_bus != pdev->bus->number) + continue; + if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(pdev->devfn)) + continue; + found_id = pci_ids[i]; + ines_priv->pci_device = pdev; + break; + } while (1); + } + if (!ines_priv->pci_device) { + pr_err("gpib: could not find ines PCI board\n"); + return -1; + } + + if (pci_enable_device(ines_priv->pci_device)) { + pr_err("error enabling pci device\n"); + return -1; + } + + if (pci_request_regions(ines_priv->pci_device, "ines-gpib")) + return -1; + nec_priv->iobase = (void *)(pci_resource_start(ines_priv->pci_device, + found_id.gpib_region)); + + ines_priv->pci_chip_type = found_id.pci_chip_type; + nec_priv->offset = found_id.io_offset; + switch (ines_priv->pci_chip_type) { + case PCI_CHIP_PLX9050: + ines_priv->plx_iobase = pci_resource_start(ines_priv->pci_device, 1); + break; + case PCI_CHIP_AMCC5920: + ines_priv->amcc_iobase = pci_resource_start(ines_priv->pci_device, 0); + break; + case PCI_CHIP_QUANCOM: + break; + case PCI_CHIP_QUICKLOGIC5030: + break; + default: + pr_err("gpib: unspecified chip type? (bug)\n"); + nec_priv->iobase = 0; + pci_release_regions(ines_priv->pci_device); + return -1; + } + + nec7210_board_reset(nec_priv, board); +#ifdef QUANCOM_PCI + if (ines_priv->pci_chip_type == PCI_CHIP_QUANCOM) { + /* change interrupt polarity */ + nec_priv->auxb_bits |= HR_INV; + ines_outb(ines_priv, nec_priv->auxb_bits, AUXMR); + } +#endif + isr_flags |= IRQF_SHARED; + if (request_irq(ines_priv->pci_device->irq, ines_pci_interrupt, isr_flags, + "pci-gpib", board)) { + pr_err("gpib: can't request IRQ %d\n", ines_priv->pci_device->irq); + return -1; + } + ines_priv->irq = ines_priv->pci_device->irq; + + // enable interrupts on pci chip + switch (ines_priv->pci_chip_type) { + case PCI_CHIP_PLX9050: + outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT, + ines_priv->plx_iobase + PLX9050_INTCSR_REG); + break; + case PCI_CHIP_AMCC5920: + { + static const int region = 1; + static const int num_wait_states = 7; + u32 bits; + + bits = amcc_prefetch_bits(region, PREFETCH_DISABLED); + bits |= amcc_PTADR_mode_bit(region); + bits |= amcc_disable_write_fifo_bit(region); + bits |= amcc_wait_state_bits(region, num_wait_states); + outl(bits, ines_priv->amcc_iobase + AMCC_PASS_THRU_REG); + outl(AMCC_ADDON_INTR_ENABLE_BIT, ines_priv->amcc_iobase + AMCC_INTCS_REG); + } + break; + case PCI_CHIP_QUANCOM: + outb(QUANCOM_IRQ_ENABLE_BIT, (unsigned long)(nec_priv->iobase) + + QUANCOM_IRQ_CONTROL_STATUS_REG); + break; + case PCI_CHIP_QUICKLOGIC5030: + break; + default: + pr_err("gpib: unspecified chip type? (bug)\n"); + return -1; + } + + return 0; +} + +int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct ines_priv *ines_priv; + int retval; + + retval = ines_common_pci_attach(board, config); + if (retval < 0) + return retval; + + ines_priv = board->private_data; + ines_online(ines_priv, board, 0); + + return 0; +} + +int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct ines_priv *ines_priv; + int retval; + + retval = ines_common_pci_attach(board, config); + if (retval < 0) + return retval; + + ines_priv = board->private_data; + ines_online(ines_priv, board, 1); + + return 0; +} + +static const int ines_isa_iosize = 0x20; + +int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct ines_priv *ines_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + int retval; + + retval = ines_generic_attach(board); + if (retval) + return retval; + + ines_priv = board->private_data; + nec_priv = &ines_priv->nec7210_priv; + + if (!request_region((unsigned long)config->ibbase, ines_isa_iosize, "ines_gpib")) { + pr_err("ines_gpib: ioports at 0x%p already in use\n", config->ibbase); + return -1; + } + nec_priv->iobase = config->ibbase; + nec_priv->offset = 1; + nec7210_board_reset(nec_priv, board); + if (request_irq(config->ibirq, ines_pci_interrupt, isr_flags, "ines_gpib", board)) { + pr_err("ines_gpib: failed to allocate IRQ %d\n", config->ibirq); + return -1; + } + ines_priv->irq = config->ibirq; + ines_online(ines_priv, board, 1); + return 0; +} + +void ines_pci_detach(gpib_board_t *board) +{ + struct ines_priv *ines_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (ines_priv) { + nec_priv = &ines_priv->nec7210_priv; + if (ines_priv->irq) { + // disable interrupts + switch (ines_priv->pci_chip_type) { + case PCI_CHIP_AMCC5920: + if (ines_priv->plx_iobase) + outl(0, ines_priv->plx_iobase + PLX9050_INTCSR_REG); + break; + case PCI_CHIP_QUANCOM: + if (nec_priv->iobase) + outb(0, (unsigned long)(nec_priv->iobase) + + QUANCOM_IRQ_CONTROL_STATUS_REG); + break; + default: + break; + } + free_irq(ines_priv->irq, board); + } + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + pci_release_regions(ines_priv->pci_device); + } + if (ines_priv->pci_device) + pci_dev_put(ines_priv->pci_device); + } + ines_free_private(board); +} + +void ines_isa_detach(gpib_board_t *board) +{ + struct ines_priv *ines_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (ines_priv) { + nec_priv = &ines_priv->nec7210_priv; + if (ines_priv->irq) + free_irq(ines_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + release_region((unsigned long)(nec_priv->iobase), ines_isa_iosize); + } + } + ines_free_private(board); +} + +static int ines_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return 0; +} + +static struct pci_driver ines_pci_driver = { + .name = "ines_gpib", + .id_table = ines_pci_table, + .probe = &ines_pci_probe +}; + +#ifdef GPIB_PCMCIA + +#include <linux/kernel.h> +#include <linux/ptrace.h> +#include <linux/string.h> +#include <linux/timer.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> +#include <pcmcia/cisreg.h> + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args)} while (0) +#else +#define DEBUG(args...) +#endif + +static const int ines_pcmcia_iosize = 0x20; + +/* The event() function is this driver's Card Services event handler. + * It will be called by Card Services when an appropriate card status + * event is received. The config() and release() entry points are + * used to configure or release a socket, in response to card insertion + * and ejection events. They are invoked from the gpib event + * handler. + */ + +static int ines_gpib_config(struct pcmcia_device *link); +static void ines_gpib_release(struct pcmcia_device *link); +static int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config); +static void ines_pcmcia_detach(gpib_board_t *board); +static irqreturn_t ines_pcmcia_interrupt(int irq, void *arg); +static int ines_common_pcmcia_attach(gpib_board_t *board); +/* + * A linked list of "instances" of the gpib device. Each actual + * PCMCIA card corresponds to one device instance, and is described + * by one dev_link_t structure (defined in ds.h). + * + * You may not want to use a linked list for this -- for example, the + * memory card driver uses an array of dev_link_t pointers, where minor + * device numbers are used to derive the corresponding array index. + */ + +static struct pcmcia_device *curr_dev; + +/* + * A dev_link_t structure has fields for most things that are needed + * to keep track of a socket, but there will usually be some device + * specific information that also needs to be kept track of. The + * 'priv' pointer in a dev_link_t structure can be used to point to + * a device-specific private data structure, like this. + * + * A driver needs to provide a dev_node_t structure for each device + * on a card. In some cases, there is only one device per card (for + * example, ethernet cards, modems). In other cases, there may be + * many actual or logical devices (SCSI adapters, memory cards with + * multiple partitions). The dev_node_t structures need to be kept + * in a linked list starting at the 'dev' field of a dev_link_t + * structure. We allocate them in the card's private data structure, + * because they generally can't be allocated dynamically. + */ + +struct local_info { + struct pcmcia_device *p_dev; + gpib_board_t *dev; + u_short manfid; + u_short cardid; +}; + +/* + * gpib_attach() creates an "instance" of the driver, allocating + * local data structures for one device. The device is registered + * with Card Services. + * + * The dev_link structure is initialized, but we don't actually + * configure the card at this point -- we wait until we receive a + * card insertion event. + */ +static int ines_gpib_probe(struct pcmcia_device *link) +{ + struct local_info *info; + +// int ret, i; + + DEBUG(0, "%s(0x%p)\n", __func__ link); + + /* Allocate space for private device-specific data */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->p_dev = link; + link->priv = info; + + /* The io structure describes IO port mapping */ + link->resource[0]->end = 32; + link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->io_lines = 5; + + /* General socket configuration */ + link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + + /* Register with Card Services */ + curr_dev = link; + return ines_gpib_config(link); +} + +/* + * This deletes a driver "instance". The device is de-registered + * with Card Services. If it has been released, all local data + * structures are freed. Otherwise, the structures will be freed + * when the device is released. + */ +static void ines_gpib_remove(struct pcmcia_device *link) +{ + struct local_info *info = link->priv; + //struct gpib_board_t *dev = info->dev; + + DEBUG(0, "%s(0x%p)\n", __func__, link); + + if (info->dev) + ines_pcmcia_detach(info->dev); + ines_gpib_release(link); + + //free_netdev(dev); + kfree(info); +} + +static int ines_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) +{ + return pcmcia_request_io(link); +} + +/* + * gpib_config() is scheduled to run after a CARD_INSERTION event + * is received, to configure the PCMCIA socket, and to make the + * device available to the system. + */ +static int ines_gpib_config(struct pcmcia_device *link) +{ + struct local_info *dev; + int retval; + void *virt; + + dev = link->priv; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + retval = pcmcia_loop_config(link, &ines_gpib_config_iteration, NULL); + if (retval) { + dev_warn(&link->dev, "no configuration found\n"); + ines_gpib_release(link); + return -ENODEV; + } + + pr_debug("ines_cs: manufacturer: 0x%x card: 0x%x\n", + link->manf_id, link->card_id); + + /* for the ines card we have to setup the configuration registers in + * attribute memory here + */ + link->resource[2]->flags |= WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8 | WIN_ENABLE; + link->resource[2]->end = 0x1000; + retval = pcmcia_request_window(link, link->resource[2], 250); + if (retval) { + dev_warn(&link->dev, "pcmcia_request_window failed\n"); + ines_gpib_release(link); + return -ENODEV; + } + retval = pcmcia_map_mem_page(link, link->resource[2], 0); + if (retval) { + dev_warn(&link->dev, "pcmcia_map_mem_page failed\n"); + ines_gpib_release(link); + return -ENODEV; + } + virt = ioremap(link->resource[2]->start, resource_size(link->resource[2])); + writeb((link->resource[2]->start >> 2) & 0xff, virt + 0xf0); // IOWindow base + iounmap((void *)virt); + + /* + * This actually configures the PCMCIA socket -- setting up + * the I/O windows and the interrupt mapping. + */ + retval = pcmcia_enable_device(link); + if (retval) { + ines_gpib_release(link); + return -ENODEV; + } + pr_info("ines gpib device loaded\n"); + return 0; +} /* gpib_config */ + +/* + * After a card is removed, gpib_release() will unregister the net + * device, and release the PCMCIA configuration. If the device is + * still open, this will be postponed until it is closed. + */ + +static void ines_gpib_release(struct pcmcia_device *link) +{ + DEBUG(0, "%s(0x%p)\n", __func__, link); + pcmcia_disable_device(link); +} /* gpib_release */ + +static int ines_gpib_suspend(struct pcmcia_device *link) +{ + //struct local_info *info = link->priv; + //struct gpib_board_t *dev = info->dev; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + if (link->open) + pr_err("Device still open ???\n"); + //netif_device_detach(dev); + + return 0; +} + +static int ines_gpib_resume(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //struct gpib_board_t *dev = info->dev; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + /*if (link->open) { + * ni_gpib_probe(dev); / really? + * printk("Gpib resumed ???\n"); + * //netif_device_attach(dev); + *} + */ + return ines_gpib_config(link); +} + +static struct pcmcia_device_id ines_pcmcia_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x01b4, 0x4730), + PCMCIA_DEVICE_NULL +}; +MODULE_DEVICE_TABLE(pcmcia, ines_pcmcia_ids); + +static struct pcmcia_driver ines_gpib_cs_driver = { + .owner = THIS_MODULE, + .name = "ines_gpib_cs", + .id_table = ines_pcmcia_ids, + .probe = ines_gpib_probe, + .remove = ines_gpib_remove, + .suspend = ines_gpib_suspend, + .resume = ines_gpib_resume, +}; + +int ines_pcmcia_init_module(void) +{ + pcmcia_register_driver(&ines_gpib_cs_driver); + return 0; +} + +void ines_pcmcia_cleanup_module(void) +{ + DEBUG(0, "ines_cs: unloading\n"); + pcmcia_unregister_driver(&ines_gpib_cs_driver); +} + +gpib_interface_t ines_pcmcia_unaccel_interface = { +name: "ines_pcmcia_unaccel", +attach : ines_pcmcia_attach, +detach : ines_pcmcia_detach, +read : ines_read, +write : ines_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +gpib_interface_t ines_pcmcia_accel_interface = { +name: "ines_pcmcia_accel", +attach : ines_pcmcia_accel_attach, +detach : ines_pcmcia_detach, +read : ines_accel_read, +write : ines_accel_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +gpib_interface_t ines_pcmcia_interface = { +name: "ines_pcmcia", +attach : ines_pcmcia_accel_attach, +detach : ines_pcmcia_detach, +read : ines_accel_read, +write : ines_accel_write, +command : ines_command, +take_control : ines_take_control, +go_to_standby : ines_go_to_standby, +request_system_control : ines_request_system_control, +interface_clear : ines_interface_clear, +remote_enable : ines_remote_enable, +enable_eos : ines_enable_eos, +disable_eos : ines_disable_eos, +parallel_poll : ines_parallel_poll, +parallel_poll_configure : ines_parallel_poll_configure, +parallel_poll_response : ines_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ines_line_status, +update_status : ines_update_status, +primary_address : ines_primary_address, +secondary_address : ines_secondary_address, +serial_poll_response : ines_serial_poll_response, +serial_poll_status : ines_serial_poll_status, +t1_delay : ines_t1_delay, +return_to_local : ines_return_to_local, +}; + +irqreturn_t ines_pcmcia_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + + return ines_interrupt(board); +} + +int ines_common_pcmcia_attach(gpib_board_t *board) +{ + struct ines_priv *ines_priv; + struct nec7210_priv *nec_priv; + int retval; + + if (!curr_dev) { + pr_err("no ines pcmcia cards found\n"); + return -1; + } + + retval = ines_generic_attach(board); + if (retval) + return retval; + + ines_priv = board->private_data; + nec_priv = &ines_priv->nec7210_priv; + + if (request_region(curr_dev->resource[0]->start, + resource_size(curr_dev->resource[0]), "ines_gpib") == 0) { + pr_err("ines_gpib: ioports at 0x%lx already in use\n", + (unsigned long)(curr_dev->resource[0]->start)); + return -1; + } + + nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start; + + nec7210_board_reset(nec_priv, board); + + if (request_irq(curr_dev->irq, ines_pcmcia_interrupt, IRQF_SHARED, + "pcmcia-gpib", board)) { + pr_err("gpib: can't request IRQ %d\n", curr_dev->irq); + return -1; + } + ines_priv->irq = curr_dev->irq; + + return 0; +} + +int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct ines_priv *ines_priv; + int retval; + + retval = ines_common_pcmcia_attach(board); + if (retval < 0) + return retval; + + ines_priv = board->private_data; + ines_online(ines_priv, board, 0); + + return 0; +} + +int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct ines_priv *ines_priv; + int retval; + + retval = ines_common_pcmcia_attach(board); + if (retval < 0) + return retval; + + ines_priv = board->private_data; + ines_online(ines_priv, board, 1); + + return 0; +} + +void ines_pcmcia_detach(gpib_board_t *board) +{ + struct ines_priv *ines_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (ines_priv) { + nec_priv = &ines_priv->nec7210_priv; + if (ines_priv->irq) + free_irq(ines_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + release_region((unsigned long)(nec_priv->iobase), ines_pcmcia_iosize); + } + } + ines_free_private(board); +} + +#endif /* GPIB_PCMCIA */ + +static int __init ines_init_module(void) +{ + int err = 0; + + err = pci_register_driver(&ines_pci_driver); + if (err) { + pr_err("ines_gpib: pci_driver_register failed!\n"); + return err; + } + + gpib_register_driver(&ines_pci_interface, THIS_MODULE); + gpib_register_driver(&ines_pci_unaccel_interface, THIS_MODULE); + gpib_register_driver(&ines_pci_accel_interface, THIS_MODULE); + gpib_register_driver(&ines_isa_interface, THIS_MODULE); +#ifdef GPIB_PCMCIA + gpib_register_driver(&ines_pcmcia_interface, THIS_MODULE); + gpib_register_driver(&ines_pcmcia_unaccel_interface, THIS_MODULE); + gpib_register_driver(&ines_pcmcia_accel_interface, THIS_MODULE); + err += ines_pcmcia_init_module(); +#endif + if (err) + return -1; + + return 0; +} + +static void __exit ines_exit_module(void) +{ + gpib_unregister_driver(&ines_pci_interface); + gpib_unregister_driver(&ines_pci_unaccel_interface); + gpib_unregister_driver(&ines_pci_accel_interface); + gpib_unregister_driver(&ines_isa_interface); +#ifdef GPIB__PCMCIA + gpib_unregister_driver(&ines_pcmcia_interface); + gpib_unregister_driver(&ines_pcmcia_unaccel_interface); + gpib_unregister_driver(&ines_pcmcia_accel_interface); + ines_pcmcia_cleanup_module(); +#endif + + pci_unregister_driver(&ines_pci_driver); +} + +module_init(ines_init_module); +module_exit(ines_exit_module); diff --git a/drivers/staging/gpib/lpvo_usb_gpib/Makefile b/drivers/staging/gpib/lpvo_usb_gpib/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..137511acce63521d570d1f4a6ce798003187e5cd --- /dev/null +++ b/drivers/staging/gpib/lpvo_usb_gpib/Makefile @@ -0,0 +1,3 @@ + +obj-m += lpvo_usb_gpib.o + diff --git a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..796c3a5be54513ab0f40694bb7229760a0b3e606 --- /dev/null +++ b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c @@ -0,0 +1,2136 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * This code has been developed at the Department of Physics (University * + * of Florence, Italy) to support in linux-gpib the open usb-gpib adapter * + * implemented at the University of Ljubljana (lpvo.fe.uni-lj.si/gpib) * + * * + * copyright : (C) 2011 Marcello Carla' * + ***************************************************************************/ + +/* base module includes */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/tty.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/vmalloc.h> +#include <linux/spinlock.h> +#include <linux/file.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/sched/signal.h> +#include <linux/uaccess.h> +#include <linux/usb.h> + +#include "gpibP.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for LPVO usb devices"); + +#define NAME "lpvo_usb_gpib" + +/* + * Table of devices that work with this driver. + * + * Currently, only one device is known to be used in the + * lpvo_usb_gpib adapter (FTDI 0403:6001). + * If your adapter uses a different chip, insert a line + * in the following table with proper <Vendor-id>, <Product-id>. + * + * To have your chip automatically handled by the driver, + * update files "/usr/local/etc/modprobe.d/lpvo_usb_gpib.conf" + * and /usr/local/etc/udev/rules.d/99-lpvo_usb_gpib.rules. + * + */ + +static const struct usb_device_id skel_table[] = { + { USB_DEVICE(0x0403, 0x6001) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, skel_table); + +/* + * *** Diagnostics and Debug *** + * + * The module parameter "debug" controls the sending of debug messages to + * syslog. By default it is set to 0 or 1 according to GPIB_CONFIG_KERNEL_DEBUG. + * debug = 0: only register/deregister messages are generated + * 1: every action is logged + * 2: extended logging; each single exchanged byte is documented + * (about twice the log volume of [1]) + * To switch debug level: + * At module loading: modprobe lpvo_usb_gpib debug={0,1,2} + * On the fly: echo {0,1,2} > /sys/modules/lpvo_usb_gpib/parameters/debug + */ + +static int debug; +module_param(debug, int, 0644); + +#define DIA_LOG(level, format, ...) \ + do { if (debug >= (level)) \ + pr_alert("%s:%s - " format, NAME, __func__, ## __VA_ARGS__); } \ + while (0) + +/* standard and extended command sets of the usb-gpib adapter */ + +#define USB_GPIB_ON "\nIB\n" +#define USB_GPIB_OFF "\nIBO\n" +#define USB_GPIB_IBm0 "\nIBm0\n" /* do not assert REN with IFC */ +#define USB_GPIB_IBm1 "\nIBm1\n" /* assert REN with IFC */ +#define USB_GPIB_IBCL "\nIBZ\n" +#define USB_GPIB_STATUS "\nIBS\n" +#define USB_GPIB_READ "\nIB?\n" +#define USB_GPIB_READ_1 "\nIBB\n" +#define USB_GPIB_EOI "\nIBe0\n" +#define USB_GPIB_FTMO "\nIBf0\n" /* disable first byte timeout */ +#define USB_GPIB_TTMOZ "\nIBt0\n" /* disable byte timeout */ + +/* incomplete commands */ + +#define USB_GPIB_BTMO "\nIBt" /* set byte timeout */ +#define USB_GPIB_TTMO "\nIBT" /* set total timeout */ + +#define USB_GPIB_DEBUG_ON "\nIBDE\xAA\n" +#define USB_GPIB_SET_LISTEN "\nIBDT0\n" +#define USB_GPIB_SET_TALK "\nIBDT1\n" +#define USB_GPIB_SET_LINES "\nIBDC\n" +#define USB_GPIB_SET_DATA "\nIBDM\n" +#define USB_GPIB_READ_LINES "\nIBD?C\n" +#define USB_GPIB_READ_DATA "\nIBD?M\n" +#define USB_GPIB_READ_BUS "\nIBD??\n" + +/* command sequences */ + +#define USB_GPIB_UNTALK "\nIBC_\n" +#define USB_GPIB_UNLISTEN "\nIBC?\n" + +/* special characters used by the adapter */ + +#define DLE ('\020') +#define STX ('\02') +#define ETX ('\03') +#define ACK ('\06') +#define NODATA ('\03') +#define NODAV ('\011') + +#define IB_BUS_REN 0x01 +#define IB_BUS_IFC 0x02 +#define IB_BUS_NDAC 0x04 +#define IB_BUS_NRFD 0x08 +#define IB_BUS_DAV 0x10 +#define IB_BUS_EOI 0x20 +#define IB_BUS_ATN 0x40 +#define IB_BUS_SRQ 0x80 + +#define INBUF_SIZE 128 + +struct char_buf { /* used by one_char() routine */ + char *inbuf; + int last; + int nchar; +}; + +struct usb_gpib_priv { /* private data to the device */ + u8 eos; /* eos character */ + short eos_flags; /* eos mode */ + int timeout; /* current value for timeout */ + void *dev; /* the usb device private data structure */ +}; + +#define GPIB_DEV (((struct usb_gpib_priv *)board->private_data)->dev) + +#define SHOW_STATUS(board) { \ + DIA_LOG(2, "# - board %p\n", board); \ + DIA_LOG(2, "# - buffer_length %d\n", board->buffer_length); \ + DIA_LOG(2, "# - status %lx\n", board->status); \ + DIA_LOG(2, "# - use_count %d\n", board->use_count); \ + DIA_LOG(2, "# - pad %x\n", board->pad); \ + DIA_LOG(2, "# - sad %x\n", board->sad); \ + DIA_LOG(2, "# - timeout %d\n", board->usec_timeout); \ + DIA_LOG(2, "# - ppc %d\n", board->parallel_poll_configuration); \ + DIA_LOG(2, "# - t1delay %d\n", board->t1_nano_sec); \ + DIA_LOG(2, "# - online %d\n", board->online); \ + DIA_LOG(2, "# - autopoll %d\n", board->autospollers); \ + DIA_LOG(2, "# - autopoll task %p\n", board->autospoll_task); \ + DIA_LOG(2, "# - minor %d\n", board->minor); \ + DIA_LOG(2, "# - master %d\n", board->master); \ + DIA_LOG(2, "# - list %d\n", board->ist); \ + } +/* + * n = 0; + * list_for_each (l, &board->device_list) n++; + * TTY_LOG ("%s:%s - devices in list %d\n", a, b, n); + */ + +/* + * TTY_LOG - write a message to the current work terminal (if any) + */ + +#define TTY_LOG(format, ...) { \ + char buf[128]; \ + struct tty_struct *tty = get_current_tty(); \ + if (tty) { \ + snprintf(buf, 128, format, __VA_ARGS__); \ + tty->driver->ops->write(tty, buf, strlen(buf)); \ + tty->driver->ops->write(tty, "\r", 1); \ + } \ + } + +/* + * GLOBAL VARIABLES: required for + * pairing among gpib minor and usb minor. + * MAX_DEV is the max number of usb-gpib adapters; free + * to change as you like, but no more than 32 + */ + +#define MAX_DEV 8 +static struct usb_interface *lpvo_usb_interfaces[MAX_DEV]; /* registered interfaces */ +static int usb_minors[MAX_DEV]; /* usb minors */ +static int assigned_usb_minors; /* mask of filled slots */ +static struct mutex minors_lock; /* operations on usb_minors are to be protected */ + +/* + * usb-skeleton prototypes + */ + +struct usb_skel; +static ssize_t skel_do_write(struct usb_skel *, const char *, size_t); +static ssize_t skel_do_read(struct usb_skel *, char *, size_t); +static int skel_do_open(gpib_board_t *, int); +static int skel_do_release(gpib_board_t *); + +/* + * usec_diff : take difference in MICROsec between two 'timespec' + * (unix time in sec and NANOsec) + */ + +inline int usec_diff(struct timespec64 *a, struct timespec64 *b) +{ + return ((a->tv_sec - b->tv_sec) * 1000000 + + (a->tv_nsec - b->tv_nsec) / 1000); +} + +/* + * *** these routines are specific to the usb-gpib adapter *** + */ + +/** + * write_loop() - Send a byte sequence to the adapter + * + * @dev: the private device structure + * @msg: the byte sequence. + * @leng: the byte sequence length. + * + */ + +static int write_loop(void *dev, char *msg, int leng) +{ +// int nchar = 0, val; + +// do { + + return skel_do_write(dev, msg, leng); + +// if (val < 1) { +// printk (KERN_ALERT "%s:%s - write error: %d %d/%d\n", +// NAME, __func__, val, nchar, leng); +// return -EIO; +// } +// nchar +=val; +// } while (nchar < leng); +// return leng; +} + +static char printable(char x) +{ + if (x < 32 || x > 126) + return ' '; + return x; +} + +/** + * send_command() - Send a byte sequence and return a single byte reply. + * + * @board: the gpib_board_struct data area for this gpib interface + * @msg: the byte sequence. + * @leng the byte sequence length; can be given as zero and is + * computed automatically, but if 'msg' contains a zero byte, + * it has to be given explicitly. + */ + +static int send_command(gpib_board_t *board, char *msg, int leng) +{ + char buffer[64]; + int nchar, j; + int retval; + struct timespec64 before, after; + + ktime_get_real_ts64 (&before); + + if (!leng) + leng = strlen(msg); + retval = write_loop(GPIB_DEV, msg, leng); + if (retval < 0) + return retval; + + nchar = skel_do_read(GPIB_DEV, buffer, 64); + + if (nchar < 0) { + DIA_LOG(0, " return from read: %d\n", nchar); + return nchar; + } else if (nchar != 1) { + for (j = 0 ; j < leng ; j++) { + DIA_LOG(0, " Irregular reply to command: %d %x %c\n", + j, msg[j], printable(msg[j])); + } + for (j = 0 ; j < nchar ; j++) { + DIA_LOG(0, " Irregular command reply: %d %x %c\n", + j, buffer[j] & 0xff, printable(buffer[j])); + } + return -EIO; + } + ktime_get_real_ts64 (&after); + + DIA_LOG(1, "Sent %d - done %d us.\n", leng, usec_diff(&after, &before)); + + return buffer[0] & 0xff; +} + +/* + * + * set_control_line() - Set the value of a single gpib control line + * + * @board: the gpib_board_struct data area for this gpib interface + * @line: line mask + * @value: line new value (0/1) + * + */ + +static int set_control_line(gpib_board_t *board, int line, int value) +{ + char msg[] = USB_GPIB_SET_LINES; + int retval; + int leng = strlen(msg); + + DIA_LOG(1, "setting line %x to %x\n", line, value); + + retval = send_command(board, USB_GPIB_READ_LINES, 0); + + DIA_LOG(1, "old line values: %x\n", retval); + + if (retval == -EIO) + return retval; + + msg[leng - 2] = value ? (retval & ~line) : retval | line; + + retval = send_command(board, msg, 0); + + DIA_LOG(1, "operation result: %x\n", retval); + + return retval; +} + +/* + * one_char() - read one single byte from input buffer + * + * @board: the gpib_board_struct data area for this gpib interface + * @char_buf: the routine private data structure + */ + +static int one_char(gpib_board_t *board, struct char_buf *b) +{ + struct timespec64 before, after; + + if (b->nchar) { + DIA_LOG(2, "-> %x\n", b->inbuf[b->last - b->nchar]); + return b->inbuf[b->last - b->nchar--]; + } + ktime_get_real_ts64 (&before); + b->nchar = skel_do_read(GPIB_DEV, b->inbuf, INBUF_SIZE); + b->last = b->nchar; + ktime_get_real_ts64 (&after); + + DIA_LOG(2, "read %d bytes in %d usec\n", + b->nchar, usec_diff(&after, &before)); + + if (b->nchar > 0) { + DIA_LOG(2, "--> %x\n", b->inbuf[b->last - b->nchar]); + return b->inbuf[b->last - b->nchar--]; + } else if (b->nchar == 0) { + dev_alert(board->gpib_dev, "%s:%s - read returned EOF\n", NAME, __func__); + return -EIO; + } + dev_alert(board->gpib_dev, "%s:%s - read error %d\n", NAME, __func__, b->nchar); + TTY_LOG("\n *** %s *** Read Error - %s\n", NAME, + "Reset the adapter with 'gpib_config'\n"); + return -EIO; +} + +/** + * set_timeout() - set single byte / total timeouts on the adapter + * + * @board: the gpib_board_struct data area for this gpib interface + * + * For sake of speed, the operation is performed only if it + * modifies the current (saved) value. Minimum allowed timeout + * is 30 ms (T30ms -> 8); timeout disable (TNONE -> 0) currently + * not supported. + */ + +static void set_timeout(gpib_board_t *board) +{ + int n, val; + char command[sizeof(USB_GPIB_TTMO) + 6]; + struct usb_gpib_priv *data = board->private_data; + + if (data->timeout == board->usec_timeout) + return; + + n = (board->usec_timeout + 32767) / 32768; + if (n < 2) + n = 2; + + DIA_LOG(1, "Set timeout to %d us -> %d\n", board->usec_timeout, n); + + sprintf(command, "%s%d\n", USB_GPIB_BTMO, n > 255 ? 255 : n); + val = send_command(board, command, 0); + + if (val == ACK) { + if (n > 65535) + n = 65535; + sprintf(command, "%s%d\n", USB_GPIB_TTMO, n); + val = send_command(board, command, 0); + } + + if (val != ACK) { + dev_alert(board->gpib_dev, "%s:%s - error in timeout set: <%s>\n", + NAME, __func__, command); + } else { + data->timeout = board->usec_timeout; + } +} + +/* + * now the standard interface functions - attach and detach + */ + +/** + * usb_gpib_attach() - activate the usb-gpib converter board + * + * @board: the gpib_board_struct data area for this gpib interface + * @config: firmware data, if any (from gpib_config -I <file>) + * + * The channel name is ttyUSBn, with n=0 by default. Other values for n + * passed with gpib_config -b <n>. + * + * In this routine I trust that when an error code is returned + * detach() will be called. Always. + */ + +static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + int retval, j; + int base = (long)config->ibbase; + char *device_path; + int match; + struct usb_device *udev; + + DIA_LOG(0, "Board %p -t %s -m %d -a %p -u %d -l %d -b %d\n", + board, board->interface->name, board->minor, config->device_path, + config->pci_bus, config->pci_slot, base); + + board->private_data = NULL; /* to be sure - we can detach before setting */ + + /* identify device to be attached */ + + mutex_lock(&minors_lock); + + if (config->device_path) { + /* if config->device_path given, try that first */ + dev_alert(board->gpib_dev, "%s:%s - Looking for device_path: %s\n", + NAME, __func__, config->device_path); + for (j = 0 ; j < MAX_DEV ; j++) { + if ((assigned_usb_minors & 1 << j) == 0) + continue; + udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j])); + device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL); + match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev, + config->device_path); + DIA_LOG(1, "dev. %d: minor %d path: %s --> %d\n", j, + lpvo_usb_interfaces[j]->minor, device_path, match); + kfree(device_path); + if (match) + break; + } + } else if (config->pci_bus != -1 && config->pci_slot != -1) { + /* second: look for bus and slot */ + for (j = 0 ; j < MAX_DEV ; j++) { + if ((assigned_usb_minors & 1 << j) == 0) + continue; + udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j])); + DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j, + udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot); + if (config->pci_bus == udev->bus->busnum && + config->pci_slot == udev->devnum) + break; + } + } else { /* last chance: usb_minor, given as ibbase */ + for (j = 0 ; j < MAX_DEV ; j++) { + if (usb_minors[j] == base && assigned_usb_minors & 1 << j) + break; + } + } + mutex_unlock(&minors_lock); + + if (j == MAX_DEV) { + dev_alert(board->gpib_dev, "%s:%s - Requested device is not registered.\n", + NAME, __func__); + return -EIO; + } + + board->private_data = kzalloc(sizeof(struct usb_gpib_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + + retval = skel_do_open(board, usb_minors[j]); + + DIA_LOG(1, "Skel open: %d\n", retval); + + if (retval) { + TTY_LOG("%s:%s - skel open failed.\n", NAME, __func__); + kfree(board->private_data); + board->private_data = NULL; + return -ENODEV; + } + + SHOW_STATUS(board); + + retval = send_command(board, USB_GPIB_ON, 0); + DIA_LOG(1, "USB_GPIB_ON returns %x\n", retval); + if (retval != ACK) + return -EIO; + + /* We must setup debug mode because we need the extended instruction + * set to cope with the Core (gpib_common) point of view + */ + + retval = send_command(board, USB_GPIB_DEBUG_ON, 0); + DIA_LOG(1, "USB_GPIB_DEBUG_ON returns %x\n", retval); + if (retval != ACK) + return -EIO; + + /* We must keep REN off after an IFC because so it is + * assumed by the Core + */ + + retval = send_command(board, USB_GPIB_IBm0, 0); + DIA_LOG(1, "USB_GPIB_IBm0 returns %x\n", retval); + if (retval != ACK) + return -EIO; + + retval = set_control_line(board, IB_BUS_REN, 0); + if (retval != ACK) + return -EIO; + + retval = send_command(board, USB_GPIB_FTMO, 0); + DIA_LOG(1, "USB_GPIB_FTMO returns %x\n", retval); + if (retval != ACK) + return -EIO; + + SHOW_STATUS(board); + TTY_LOG("Module '%s' has been sucesfully configured\n", NAME); + return 0; +} + +/** + * usb_gpib_detach() - deactivate the usb-gpib converter board + * + * @board: the gpib_board data area for this gpib interface + * + */ + +static void usb_gpib_detach(gpib_board_t *board) +{ + int retval; + + SHOW_STATUS(board); + + DIA_LOG(0, "detaching %p\n", board); + + if (board->private_data) { + if (GPIB_DEV) { + write_loop(GPIB_DEV, USB_GPIB_OFF, strlen(USB_GPIB_OFF)); + msleep(100); + DIA_LOG(1, "%s", "GPIB off\n"); + retval = skel_do_release(board); + DIA_LOG(1, "skel release -> %d\n", retval); + } + kfree(board->private_data); + board->private_data = NULL; + } + + DIA_LOG(0, "done %p\n", board); + TTY_LOG("Module '%s' has been detached\n", NAME); +} + +/* + * Other functions follow in alphabetical order + */ +/* command */ +static int usb_gpib_command(gpib_board_t *board, + u8 *buffer, + size_t length, + size_t *bytes_written) +{ + int i, retval; + char command[6] = "IBc\n"; + + DIA_LOG(1, "enter %p\n", board); + + set_timeout(board); + + *bytes_written = 0; + for (i = 0 ; i < length ; i++) { + command[3] = buffer[i]; + retval = send_command(board, command, 5); + DIA_LOG(2, "%d ==> %x %x\n", i, buffer[i], retval); + if (retval != 0x06) + return retval; + ++(*bytes_written); + } + return 0; +} + +/** + * disable_eos() - Disable END on eos byte (END on EOI only) + * + * @board: the gpib_board data area for this gpib interface + * + * With the lpvo adapter eos can only be handled via software. + * Cannot do nothing here, but remember for future use. + */ + +static void usb_gpib_disable_eos(gpib_board_t *board) +{ + ((struct usb_gpib_priv *)board->private_data)->eos_flags &= ~REOS; + DIA_LOG(1, "done: %x\n", + ((struct usb_gpib_priv *)board->private_data)->eos_flags); +} + +/** + * enable_eos() - Enable END for reads when eos byte is received. + * + * @board: the gpib_board data area for this gpib interface + * @eos_byte: the 'eos' byte + * @compare_8_bits: if zero ignore eigthth bit when comparing + * + */ + +static int usb_gpib_enable_eos(gpib_board_t *board, + u8 eos_byte, + int compare_8_bits) +{ + struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data; + + DIA_LOG(1, "enter with %x\n", eos_byte); + pd->eos = eos_byte; + pd->eos_flags = REOS; + if (compare_8_bits) + pd->eos_flags |= BIN; + return 0; +} + +/** + * go_to_standby() - De-assert ATN + * + * @board: the gpib_board data area for this gpib interface + */ + +static int usb_gpib_go_to_standby(gpib_board_t *board) +{ + int retval = set_control_line(board, IB_BUS_ATN, 0); + + DIA_LOG(1, "done with %x\n", retval); + + if (retval == ACK) + return 0; + return -EIO; +} + +/** + * interface_clear() - Assert or de-assert IFC + * + * @board: the gpib_board data area for this gpib interface + * assert: 1: assert IFC; 0: de-assert IFC + * + * Currently on the assert request we issue the lpvo IBZ + * command that cycles IFC low for 100 usec, then we ignore + * the de-assert request. + */ + +static void usb_gpib_interface_clear(gpib_board_t *board, int assert) +{ + int retval = 0; + + DIA_LOG(1, "enter with %d\n", assert); + + if (assert) { + retval = send_command(board, USB_GPIB_IBCL, 0); + + set_bit(CIC_NUM, &board->status); + } + + DIA_LOG(1, "done with %d %d\n", assert, retval); +} + +/** + * line_status() - Read the status of the bus lines. + * + * @board: the gpib_board data area for this gpib interface + * + * We can read all lines. + */ + +#define WQT wait_queue_entry_t +#define WQH head +#define WQE entry + +static int usb_gpib_line_status(const gpib_board_t *board) +{ + int buffer; + int line_status = ValidALL; /* all lines will be read */ + struct list_head *p, *q; + WQT *item; + unsigned long flags; + int sleep = 0; + + DIA_LOG(1, "%s\n", "request"); + + /* if we are on the wait queue (board->wait), do not hurry + * reading status line; instead, pause a little + */ + + spin_lock_irqsave((spinlock_t *)&board->wait.lock, flags); + q = (struct list_head *)&board->wait.WQH; + list_for_each(p, q) { + item = container_of(p, WQT, WQE); + if (item->private == current) { + sleep = 20; + break; + } + /* pid is: ((struct task_struct *) item->private)->pid); */ + } + spin_unlock_irqrestore((spinlock_t *)&board->wait.lock, flags); + if (sleep) { + DIA_LOG(1, "we are on the wait queue - sleep %d ms\n", sleep); + msleep(sleep); + } + + buffer = send_command((gpib_board_t *)board, USB_GPIB_STATUS, 0); + + if (buffer < 0) { + dev_alert(board->gpib_dev, "%s:%s - line status read failed with %d\n", + NAME, __func__, buffer); + return -1; + } + + if ((buffer & 0x01) == 0) + line_status |= BusREN; + if ((buffer & 0x02) == 0) + line_status |= BusIFC; + if ((buffer & 0x04) == 0) + line_status |= BusNDAC; + if ((buffer & 0x08) == 0) + line_status |= BusNRFD; + if ((buffer & 0x10) == 0) + line_status |= BusDAV; + if ((buffer & 0x20) == 0) + line_status |= BusEOI; + if ((buffer & 0x40) == 0) + line_status |= BusATN; + if ((buffer & 0x80) == 0) + line_status |= BusSRQ; + + DIA_LOG(1, "done with %x %x\n", buffer, line_status); + + return line_status; +} + +/* parallel_poll */ + +static int usb_gpib_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + /* request parallel poll asserting ATN | EOI; + * we suppose ATN already asserted + */ + + int retval; + + DIA_LOG(1, "enter %p\n", board); + + retval = set_control_line(board, IB_BUS_EOI, 1); + if (retval != ACK) { + dev_alert(board->gpib_dev, "%s:%s - assert EOI failed\n", NAME, __func__); + return -EIO; + } + + *result = send_command(board, USB_GPIB_READ_DATA, 0); + + DIA_LOG(1, "done with %x\n", *result); + + retval = set_control_line(board, IB_BUS_EOI, 0); + if (retval != 0x06) { + dev_alert(board->gpib_dev, "%s:%s - unassert EOI failed\n", NAME, __func__); + return -EIO; + } + + return 0; +} + +/* read */ + +static int usb_gpib_read(gpib_board_t *board, + u8 *buffer, + size_t length, + int *end, + size_t *bytes_read) +{ +#define MAX_READ_EXCESS 16384 + + struct char_buf b = {NULL, 0}; + + int retval; + char c, nc; + int ic; + struct timespec64 before, after; + int read_count = MAX_READ_EXCESS; + struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data; + + DIA_LOG(1, "enter %p -> %zu\n", board, length); + + *bytes_read = 0; /* by default, things go wrong */ + *end = 0; + + set_timeout(board); + + /* single byte read has a special handling */ + + if (length == 1) { + char inbuf[2] = {0, 0}; + + /* read a single character */ + + ktime_get_real_ts64 (&before); + + retval = write_loop(GPIB_DEV, USB_GPIB_READ_1, strlen(USB_GPIB_READ_1)); + if (retval < 0) + return retval; + + retval = skel_do_read(GPIB_DEV, inbuf, 1); + retval += skel_do_read(GPIB_DEV, inbuf + 1, 1); + + ktime_get_real_ts64 (&after); + + DIA_LOG(1, "single read: %x %x %x in %d\n", retval, + inbuf[0], inbuf[1], + usec_diff(&after, &before)); + + /* good char / last char? */ + + if (retval == 2 && inbuf[1] == ACK) { + buffer[0] = inbuf[0]; + *bytes_read = 1; + return 0; + } + if (retval < 2) + return -EIO; + else + return -ETIME; + return 0; + } + + /* allocate buffer for multibyte read */ + + b.inbuf = kmalloc(INBUF_SIZE, GFP_KERNEL); + if (!b.inbuf) + return -ENOMEM; + + /* send read command and check <DLE><STX> sequence */ + + retval = write_loop(GPIB_DEV, USB_GPIB_READ, strlen(USB_GPIB_READ)); + if (retval < 0) + goto read_return; + + if (one_char(board, &b) != DLE || one_char(board, &b) != STX) { + dev_alert(board->gpib_dev, "%s:%s - wrong <DLE><STX> sequence\n", + NAME, __func__); + retval = -EIO; + goto read_return; + } + + /* get data flow */ + + while (1) { + ic = one_char(board, &b); + if (ic == -EIO) { + retval = -EIO; + goto read_return; + } + c = ic; + + if (c == DLE) + nc = one_char(board, &b); + if (c != DLE || nc == DLE) { + /* data byte - store into buffer */ + + if (*bytes_read == length) + break; /* data overflow */ + if (c == DLE) + c = nc; + buffer[(*bytes_read)++] = c; + if (c == pd->eos) { + *end = 1; + break; + } + + } else { + /* we are in the closing <DLE><ETX> sequence */ + + if (c == ETX) { + c = one_char(board, &b); + if (c == ACK) { + *end = 1; + retval = 0; + goto read_return; + } else { + dev_alert(board->gpib_dev, "%s:%s - %s %x\n", + NAME, __func__, + "Wrong end of message", c); + retval = -ETIME; + goto read_return; + } + } else { + dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__, + "lone <DLE> in stream"); + retval = -EIO; + goto read_return; + } + } + } + + /* we had a data overflow - flush excess data */ + + while (read_count--) { + if (one_char(board, &b) != DLE) + continue; + c = one_char(board, &b); + if (c == DLE) + continue; + if (c == ETX) { + c = one_char(board, &b); + if (c == ACK) { + if (MAX_READ_EXCESS - read_count > 1) + dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__, + "small buffer - maybe some data lost"); + retval = 0; + goto read_return; + } + break; + } + } + + dev_alert(board->gpib_dev, "%s:%s - no input end - GPIB board in odd state\n", + NAME, __func__); + retval = -EIO; + +read_return: + kfree(b.inbuf); + + DIA_LOG(1, "done with byte/status: %d %x %d\n", + (int)*bytes_read, retval, *end); + + if (retval == 0 || retval == -ETIME) { + if (send_command(board, USB_GPIB_UNTALK, sizeof(USB_GPIB_UNTALK)) == 0x06) + return retval; + return -EIO; + } + + return retval; +} + +/* remote_enable */ + +static void usb_gpib_remote_enable(gpib_board_t *board, int enable) +{ + int retval; + + retval = set_control_line(board, IB_BUS_REN, enable ? 1 : 0); + if (retval != ACK) + dev_alert(board->gpib_dev, "%s:%s - could not set REN line: %x\n", + NAME, __func__, retval); + + DIA_LOG(1, "done with %x\n", retval); +} + +/* request_system_control */ + +static void usb_gpib_request_system_control(gpib_board_t *board, + int request_control) +{ + if (request_control) + set_bit(CIC_NUM, &board->status); + else + clear_bit(CIC_NUM, &board->status); + + DIA_LOG(1, "done with %d -> %lx\n", request_control, board->status); +} + +/* take_control */ +/* beware: the sync flag is ignored; what is its real meaning? */ + +static int usb_gpib_take_control(gpib_board_t *board, int sync) +{ + int retval; + + retval = set_control_line(board, IB_BUS_ATN, 1); + + DIA_LOG(1, "done with %d %x\n", sync, retval); + + if (retval == ACK) + return 0; + return -EIO; +} + +/* update_status */ + +static unsigned int usb_gpib_update_status(gpib_board_t *board, + unsigned int clear_mask) +{ + /* There is nothing we can do here, I guess */ + + board->status &= ~clear_mask; + + DIA_LOG(1, "done with %x %lx\n", clear_mask, board->status); + + return board->status; +} + +/* write */ +/* beware: DLE characters are not escaped - can only send ASCII data */ + +static int usb_gpib_write(gpib_board_t *board, + u8 *buffer, + size_t length, + int send_eoi, + size_t *bytes_written) +{ + int retval; + char *msg; + + DIA_LOG(1, "enter %p -> %zu\n", board, length); + + set_timeout(board); + + msg = kmalloc(length + 8, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + memcpy(msg, "\nIB\020\002", 5); + memcpy(msg + 5, buffer, length); + memcpy(msg + 5 + length, "\020\003\n", 3); + + retval = send_command(board, msg, length + 8); + kfree(msg); + + DIA_LOG(1, "<%.*s> -> %x\n", (int)length, buffer, retval); + + if (retval != ACK) + return -EPIPE; + + *bytes_written = length; + + if (send_command(board, USB_GPIB_UNLISTEN, sizeof(USB_GPIB_UNLISTEN)) + != 0x06) + return -EPIPE; + + return length; +} + +/* + * *** following functions not implemented yet *** + */ + +/* parallel_poll configure */ + +static void usb_gpib_parallel_poll_configure(gpib_board_t *board, + uint8_t configuration) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); +} + +/* parallel_poll_response */ + +static void usb_gpib_parallel_poll_response(gpib_board_t *board, int ist) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); +} + +/* primary_address */ + +static int usb_gpib_primary_address(gpib_board_t *board, unsigned int address) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); + return 0; +} + +/* return_to_local */ + +static void usb_gpib_return_to_local(gpib_board_t *board) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); +} + +/* secondary_address */ + +static int usb_gpib_secondary_address(gpib_board_t *board, + unsigned int address, + int enable) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); + return 0; +} + +/* serial_poll_response */ + +static void usb_gpib_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); +} + +/* serial_poll_status */ + +static uint8_t usb_gpib_serial_poll_status(gpib_board_t *board) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); + return 0; +} + +/* t1_delay */ + +static unsigned int usb_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__); + return 0; +} + +/* + * *** module dispatch table and init/exit functions *** + */ + +gpib_interface_t usb_gpib_interface = { +name: NAME, +attach : usb_gpib_attach, +detach : usb_gpib_detach, +read : usb_gpib_read, +write : usb_gpib_write, +command : usb_gpib_command, +take_control : usb_gpib_take_control, +go_to_standby : usb_gpib_go_to_standby, +request_system_control : usb_gpib_request_system_control, +interface_clear : usb_gpib_interface_clear, +remote_enable : usb_gpib_remote_enable, +enable_eos : usb_gpib_enable_eos, +disable_eos : usb_gpib_disable_eos, +parallel_poll : usb_gpib_parallel_poll, +parallel_poll_configure : usb_gpib_parallel_poll_configure, +parallel_poll_response : usb_gpib_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : usb_gpib_line_status, +update_status : usb_gpib_update_status, +primary_address : usb_gpib_primary_address, +secondary_address : usb_gpib_secondary_address, +serial_poll_response : usb_gpib_serial_poll_response, +serial_poll_status : usb_gpib_serial_poll_status, +t1_delay : usb_gpib_t1_delay, +return_to_local : usb_gpib_return_to_local, +skip_check_for_command_acceptors : 1 +}; + +/* + * usb_gpib_init_module(), usb_gpib_exit_module() + * + * This functions are called every time a new device is detected + * and registered or is removed and unregistered. + * We must take note of created and destroyed usb minors to be used + * when usb_gpib_attach() and usb_gpib_detach() will be called on + * request by gpib_config. + */ + +static int usb_gpib_init_module(struct usb_interface *interface) +{ + int j, mask, rv; + + rv = mutex_lock_interruptible(&minors_lock); + if (rv < 0) + return rv; + + if (!assigned_usb_minors) { + gpib_register_driver(&usb_gpib_interface, THIS_MODULE); + } else { + /* check if minor is already registered - maybe useless, but if + * it happens the code is inconsistent somewhere + */ + + for (j = 0 ; j < MAX_DEV ; j++) { + if (usb_minors[j] == interface->minor && assigned_usb_minors & 1 << j) { + pr_alert("%s:%s - CODE BUG: USB minor %d registered at %d.\n", + NAME, __func__, interface->minor, j); + rv = -1; + goto exit; + } + } + } + + /* find a free slot */ + + for (j = 0 ; j < MAX_DEV ; j++) { + mask = 1 << j; + if ((assigned_usb_minors & mask) == 0) { + usb_minors[j] = interface->minor; + lpvo_usb_interfaces[j] = interface; + assigned_usb_minors |= mask; + DIA_LOG(0, "usb minor %d registered at %d\n", interface->minor, j); + rv = 0; + goto exit; + } + } + pr_alert("%s:%s - No slot available for interface %p minor %d\n", + NAME, __func__, interface, interface->minor); + rv = -1; + +exit: + mutex_unlock(&minors_lock); + return rv; +} + +static void usb_gpib_exit_module(int minor) +{ + int j; + + mutex_lock(&minors_lock); + for (j = 0 ; j < MAX_DEV ; j++) { + if (usb_minors[j] == minor && assigned_usb_minors & 1 << j) { + assigned_usb_minors &= ~(1 << j); + usb_minors[j] = -1; + if (assigned_usb_minors == 0) + gpib_unregister_driver(&usb_gpib_interface); + goto exit; + } + } + pr_alert("%s:%s - CODE BUG: USB minor %d not found.\n", NAME, __func__, minor); + +exit: + mutex_unlock(&minors_lock); +} + +/* + * Default latency time (16 msec) is too long. + * We must use 1 msec (best); anyhow, no more than 5 msec. + * + * Defines and function taken and modified from the kernel tree + * (see ftdi_sio.h and ftdi_sio.c). + * + */ + +#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ +#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER +#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40 +#define WDR_TIMEOUT 5000 /* default urb timeout */ +#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ + +#define LATENCY_TIMER 1 /* use a small latency timer: 1 ... 5 msec */ +#define LATENCY_CHANNEL 0 /* channel selection in multichannel devices */ +static int write_latency_timer(struct usb_device *udev) +{ + int rv = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + FTDI_SIO_SET_LATENCY_TIMER_REQUEST, + FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, + LATENCY_TIMER, LATENCY_CHANNEL, + NULL, 0, WDR_TIMEOUT); + if (rv < 0) + pr_alert("Unable to write latency timer: %i\n", rv); + return rv; +} + +/***************************************************************************** + * * + * The following code is a modified version of the USB Skeleton driver * + * written by Greg Kroah-Hartman and available in the kernel tree. * + * * + * Functions skel_open() and skel_release() have been rewritten and named * + * skel_do_open() and skel_do_release() to process the attach and detach * + * requests coming from gpib_config. * + * * + * Functions skel_read() and skel_write() have been split into a * + * skel_do_read() and skel_do_write(), that cover the kernel stuff of read * + * and write operations, and the original skel_read() and skel_write(), * + * that handle communication with user space and call their _do_ companion. * + * * + * Only the _do_ versions are used by the lpvo_usb_gpib driver; other ones * + * can be (optionally) maintained in the compilation to have direct access * + * to a gpib controller for debug and diagnostics. * + * * + * To avoid collisions in names, devices in user space have been renamed * + * lpvo_raw1, lpvo_raw2 .... and the usb driver has been renamed with the * + * gpib module name. * + * * + *****************************************************************************/ + +/* + * USB Skeleton driver - 2.2 + * + * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) + * + * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c + * but has been rewritten to be easier to read and use. + */ + +#include <linux/errno.h> +#include <linux/kref.h> +#include <linux/uaccess.h> +#include <linux/mutex.h> + +/* Get a minor range for your devices from the usb maintainer */ +#define USB_SKEL_MINOR_BASE 192 + +/* private defines */ + +#define MAX_TRANSFER (PAGE_SIZE - 512) +/* MAX_TRANSFER is chosen so that the VM is not stressed by + * allocations > PAGE_SIZE and the number of packets in a page + * is an integer 512 is the largest possible packet on EHCI + */ + +#define WRITES_IN_FLIGHT 1 /* we do not want more than one pending write */ +#define USER_DEVICE 1 /* compile for device(s) in user space */ + +/* Structure to hold all of our device specific stuff */ +struct usb_skel { + struct usb_device *udev; /* the usb device for this device */ + struct usb_interface *interface; /* the interface for this device */ + struct semaphore limit_sem; /* limiting the number of writes in progress */ + struct usb_anchor submitted; /* in case need to retract our submissions */ + struct urb *bulk_in_urb; /* the urb to read data with */ + unsigned char *bulk_in_buffer; /* the buffer to receive data */ + size_t bulk_in_size; /* the size of the receive buffer */ + size_t bulk_in_filled; /* number of bytes in the buffer */ + size_t bulk_in_copied; /* already copied to user space */ + __u8 bulk_in_endpoint_addr; /* the address of the bulk in endpoint */ + __u8 bulk_out_endpoint_addr; /* the address of the bulk out endpoint */ + int errors; /* the last request tanked */ + bool ongoing_read; /* a read is going on */ + spinlock_t err_lock; /* lock for errors */ + struct kref kref; + struct mutex io_mutex; /* synchronize I/O with disconnect */ + wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */ +}; + +#define to_skel_dev(d) container_of(d, struct usb_skel, kref) + +static struct usb_driver skel_driver; +static void skel_draw_down(struct usb_skel *dev); + +static void skel_delete(struct kref *kref) +{ + struct usb_skel *dev = to_skel_dev(kref); + + usb_free_urb(dev->bulk_in_urb); + usb_put_dev(dev->udev); + kfree(dev->bulk_in_buffer); + kfree(dev); +} + +/* + * skel_do_open() - to be called by usb_gpib_attach + */ + +static int skel_do_open(gpib_board_t *board, int subminor) +{ + struct usb_skel *dev; + struct usb_interface *interface; + int retval = 0; + + DIA_LOG(0, "Required minor: %d\n", subminor); + + interface = usb_find_interface(&skel_driver, subminor); + if (!interface) { + pr_err("%s - error, can't find device for minor %d\n", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + + dev = usb_get_intfdata(interface); + if (!dev) { + retval = -ENODEV; + goto exit; + } + + retval = usb_autopm_get_interface(interface); + if (retval) + goto exit; + + /* increment our usage count for the device */ + kref_get(&dev->kref); + + /* save our object in the file's private structure */ + GPIB_DEV = dev; + +exit: + return retval; +} + +/* + * skel_do_release() - to be called by usb_gpib_detach + */ + +static int skel_do_release(gpib_board_t *board) +{ + struct usb_skel *dev; + + dev = GPIB_DEV; + if (!dev) + return -ENODEV; + + /* allow the device to be autosuspended */ + mutex_lock(&dev->io_mutex); + if (dev->interface) + usb_autopm_put_interface(dev->interface); + mutex_unlock(&dev->io_mutex); + + /* decrement the count on our device */ + kref_put(&dev->kref, skel_delete); + return 0; +} + +/* + * read functions + */ + +static void skel_read_bulk_callback(struct urb *urb) +{ + struct usb_skel *dev; + unsigned long flags; + + dev = urb->context; + + spin_lock_irqsave(&dev->err_lock, flags); + /* sync/async unlink faults aren't errors */ + if (urb->status) { + if (!(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) + dev_err(&dev->interface->dev, + "%s - nonzero read bulk status received: %d\n", + __func__, urb->status); + + dev->errors = urb->status; + } else { + dev->bulk_in_filled = urb->actual_length; + } + dev->ongoing_read = 0; + spin_unlock_irqrestore(&dev->err_lock, flags); + + wake_up_interruptible(&dev->bulk_in_wait); +} + +static int skel_do_read_io(struct usb_skel *dev, size_t count) +{ + int rv; + + /* prepare a read */ + usb_fill_bulk_urb(dev->bulk_in_urb, + dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in_endpoint_addr), + dev->bulk_in_buffer, + min(dev->bulk_in_size, count), + skel_read_bulk_callback, + dev); + /* tell everybody to leave the URB alone */ + spin_lock_irq(&dev->err_lock); + dev->ongoing_read = 1; + spin_unlock_irq(&dev->err_lock); + + /* submit bulk in urb, which means no data to deliver */ + dev->bulk_in_filled = 0; + dev->bulk_in_copied = 0; + + /* do it */ + rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); + if (rv < 0) { + dev_err(&dev->interface->dev, + "%s - failed submitting read urb, error %d\n", + __func__, rv); + rv = (rv == -ENOMEM) ? rv : -EIO; + spin_lock_irq(&dev->err_lock); + dev->ongoing_read = 0; + spin_unlock_irq(&dev->err_lock); + } + + return rv; +} + +/* + * skel_do_read() - read operations from lpvo_usb_gpib + */ + +static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) +{ + int rv; + bool ongoing_io; + + /* if we cannot read at all, return EOF */ + + if (!dev->bulk_in_urb || !count) + return 0; + + DIA_LOG(1, "enter for %zu.\n", count); + +restart: /* added to comply with ftdi timeout technique */ + + /* no concurrent readers */ + + DIA_LOG(2, "restart with %zd %zd.\n", dev->bulk_in_filled, dev->bulk_in_copied); + + rv = mutex_lock_interruptible(&dev->io_mutex); + if (rv < 0) + return rv; + + if (!dev->interface) { /* disconnect() was called */ + rv = -ENODEV; + goto exit; + } + +retry: + /* if IO is under way, we must not touch things */ + spin_lock_irq(&dev->err_lock); + ongoing_io = dev->ongoing_read; + spin_unlock_irq(&dev->err_lock); + + DIA_LOG(2, "retry with %d.\n", ongoing_io); + + if (ongoing_io) { +// /* nonblocking IO shall not wait */ +// /* no file, no O_NONBLOCK; maybe provide when from user space */ +// if (file->f_flags & O_NONBLOCK) { +// rv = -EAGAIN; +// goto exit; +// } + + /* + * IO may take forever + * hence wait in an interruptible state + */ + rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read)); + if (rv < 0) + goto exit; + } + + /* errors must be reported */ + rv = dev->errors; + if (rv < 0) { + /* any error is reported once */ + dev->errors = 0; + /* to preserve notifications about reset */ + rv = (rv == -EPIPE) ? rv : -EIO; + /* report it */ + goto exit; + } + + /* + * if the buffer is filled we may satisfy the read + * else we need to start IO + */ + + if (dev->bulk_in_filled) { + /* we had read data */ + + size_t available = dev->bulk_in_filled - dev->bulk_in_copied; +// size_t chunk = min(available, count); /* compute chunk later */ + size_t chunk; + + DIA_LOG(2, "we have data: %zu %zu.\n", dev->bulk_in_filled, dev->bulk_in_copied); + + if (!available) { + /* + * all data has been used + * actual IO needs to be done + */ + /* it seems that requests for less than dev->bulk_in_size + * are not accepted + */ + rv = skel_do_read_io(dev, dev->bulk_in_size); + if (rv < 0) + goto exit; + else + goto retry; + } + + /* + * data is available - chunk tells us how much shall be copied + */ + + /* Condition dev->bulk_in_copied > 0 maybe will never happen. In case, + * signal the event and copy using the original procedure, i.e., copy + * first two bytes also + */ + + if (dev->bulk_in_copied) { + int j; + + for (j = 0 ; j < dev->bulk_in_filled ; j++) { + pr_alert("copy -> %x %zu %x\n", + j, dev->bulk_in_copied, dev->bulk_in_buffer[j]); + } + chunk = min(available, count); + memcpy(buffer, dev->bulk_in_buffer + dev->bulk_in_copied, chunk); + rv = chunk; + dev->bulk_in_copied += chunk; + + /* copy discarding first two bytes that contain ftdi chip status */ + + } else { + /* account for two bytes to be discarded */ + chunk = min(available, count + 2); + if (chunk < 2) { + pr_alert("BAD READ - chunk: %zu\n", chunk); + rv = -EIO; + goto exit; + } + + memcpy(buffer, dev->bulk_in_buffer + 2, chunk - 2); + rv = chunk; + dev->bulk_in_copied += chunk; + } + + /* + * if we are asked for more than we have, + * we start IO but don't wait + * + * No, no read ahead allowed; if the case, more data will be + * asked for by the lpvo_usb_gpib layer. + */ +// if (available < count) +// skel_do_read_io(dev, dev->bulk_in_size); + } else { + DIA_LOG(1, "no data - start read - copied: %zd.\n", dev->bulk_in_copied); + + /* no data in the buffer */ + rv = skel_do_read_io(dev, dev->bulk_in_size); + if (rv < 0) + goto exit; + else + goto retry; + } +exit: + mutex_unlock(&dev->io_mutex); + if (rv == 2) + goto restart; /* ftdi chip returns two status bytes after a latency anyhow */ + DIA_LOG(1, "exit with %d.\n", rv); + if (rv > 0) + return rv - 2; /* account for 2 discarded bytes in a valid buffer */ + return rv; +} + +/* + * write functions + */ + +static void skel_write_bulk_callback(struct urb *urb) +{ + struct usb_skel *dev; + unsigned long flags; + + dev = urb->context; + + /* sync/async unlink faults aren't errors */ + if (urb->status) { + if (!(urb->status == -ENOENT || + urb->status == -ECONNRESET || + urb->status == -ESHUTDOWN)) + dev_err(&dev->interface->dev, + "%s - nonzero write bulk status received: %d\n", + __func__, urb->status); + + spin_lock_irqsave(&dev->err_lock, flags); + dev->errors = urb->status; + spin_unlock_irqrestore(&dev->err_lock, flags); + } + + /* free up our allocated buffer */ + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + up(&dev->limit_sem); +} + +/* + * skel_do_write() - write operations from lpvo_usb_gpib + */ + +static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t count) +{ + int retval = 0; + struct urb *urb = NULL; + char *buf = NULL; + size_t writesize = min_t(size_t, count, (size_t)MAX_TRANSFER); + + /* verify that we actually have some data to write */ + if (count == 0) + goto exit; + + /* + * limit the number of URBs in flight to stop a user from using up all + * RAM + */ + /* Only one URB is used, because we can't have a pending write() and go on */ + +// if (!(file->f_flags & O_NONBLOCK)) { /* no NONBLOCK provided */ + if (down_interruptible(&dev->limit_sem)) { + retval = -ERESTARTSYS; + goto exit; + } +// } else { +// if (down_trylock(&dev->limit_sem)) { +// retval = -EAGAIN; +// goto exit; +// } +// } + + spin_lock_irq(&dev->err_lock); + retval = dev->errors; + if (retval < 0) { + /* any error is reported once */ + dev->errors = 0; + /* to preserve notifications about reset */ + retval = (retval == -EPIPE) ? retval : -EIO; + } + spin_unlock_irq(&dev->err_lock); + if (retval < 0) + goto error; + + /* create a urb, and a buffer for it, and copy the data to the urb */ + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + + buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL, + &urb->transfer_dma); + if (!buf) { + retval = -ENOMEM; + goto error; + } + + memcpy(buf, buffer, count); + + /* this lock makes sure we don't submit URBs to gone devices */ + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* disconnect() was called */ + mutex_unlock(&dev->io_mutex); + retval = -ENODEV; + goto error; + } + + /* initialize the urb properly */ + usb_fill_bulk_urb(urb, dev->udev, + usb_sndbulkpipe(dev->udev, dev->bulk_out_endpoint_addr), + buf, writesize, skel_write_bulk_callback, dev); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + usb_anchor_urb(urb, &dev->submitted); + + /* send the data out the bulk port */ + retval = usb_submit_urb(urb, GFP_KERNEL); + mutex_unlock(&dev->io_mutex); + if (retval) { + dev_err(&dev->interface->dev, + "%s - failed submitting write urb, error %d\n", + __func__, retval); + goto error_unanchor; + } + + /* + * release our reference to this urb, the USB core will eventually free + * it entirely + */ + usb_free_urb(urb); + + return writesize; + +error_unanchor: + usb_unanchor_urb(urb); +error: + if (urb) { + usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma); + usb_free_urb(urb); + } + up(&dev->limit_sem); + +exit: + return retval; +} + +/* + * services for the user space devices + */ + +#if USER_DEVICE /* conditional compilation of user space device */ + +static int skel_flush(struct file *file, fl_owner_t id) +{ + struct usb_skel *dev; + int res; + + dev = file->private_data; + if (!dev) + return -ENODEV; + + /* wait for io to stop */ + mutex_lock(&dev->io_mutex); + skel_draw_down(dev); + + /* read out errors, leave subsequent opens a clean slate */ + spin_lock_irq(&dev->err_lock); + res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0; + dev->errors = 0; + spin_unlock_irq(&dev->err_lock); + + mutex_unlock(&dev->io_mutex); + + return res; +} + +static int skel_open(struct inode *inode, struct file *file) +{ + struct usb_skel *dev; + struct usb_interface *interface; + int subminor; + int retval = 0; + + subminor = iminor(inode); + + interface = usb_find_interface(&skel_driver, subminor); + if (!interface) { + pr_err("%s - error, can't find device for minor %d\n", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + + dev = usb_get_intfdata(interface); + if (!dev) { + retval = -ENODEV; + goto exit; + } + + retval = usb_autopm_get_interface(interface); + if (retval) + goto exit; + + /* increment our usage count for the device */ + kref_get(&dev->kref); + + /* save our object in the file's private structure */ + file->private_data = dev; + +exit: + return retval; +} + +static int skel_release(struct inode *inode, struct file *file) +{ + struct usb_skel *dev; + + dev = file->private_data; + if (!dev) + return -ENODEV; + + /* allow the device to be autosuspended */ + mutex_lock(&dev->io_mutex); + if (dev->interface) + usb_autopm_put_interface(dev->interface); + mutex_unlock(&dev->io_mutex); + + /* decrement the count on our device */ + kref_put(&dev->kref, skel_delete); + return 0; +} + +/* + * user space access to read function + */ + +static ssize_t skel_read(struct file *file, char *buffer, size_t count, + loff_t *ppos) +{ + struct usb_skel *dev; + char *buf; + ssize_t rv; + + dev = file->private_data; + + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + rv = skel_do_read(dev, buf, count); + + pr_alert("%s - return with %zu\n", __func__, rv); + + if (rv > 0) { + if (copy_to_user(buffer, buf, rv)) { + kfree(buf); + return -EFAULT; + } + } + kfree(buf); + return rv; +} + +/* + * user space access to write function + */ + +static ssize_t skel_write(struct file *file, const char *user_buffer, + size_t count, loff_t *ppos) +{ + struct usb_skel *dev; + char *buf; + ssize_t rv; + + dev = file->private_data; + + buf = kmalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, user_buffer, count)) { + kfree(buf); + return -EFAULT; + } + + rv = skel_do_write(dev, buf, count); + kfree(buf); + return rv; +} +#endif + +static const struct file_operations skel_fops = { + .owner = THIS_MODULE, +#if USER_DEVICE + .read = skel_read, + .write = skel_write, + .open = skel_open, + .release = skel_release, + .flush = skel_flush, + .llseek = noop_llseek, +#endif +}; + +/* + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with the driver core + */ +#if USER_DEVICE +static struct usb_class_driver skel_class = { + .name = "lpvo_raw%d", + .fops = &skel_fops, + .minor_base = USB_SKEL_MINOR_BASE, +}; +#endif + +static int skel_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_skel *dev; + struct usb_endpoint_descriptor *bulk_in, *bulk_out; + int retval; + char *device_path; + + mutex_init(&minors_lock); /* required for handling minor numbers table */ + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + kref_init(&dev->kref); + sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); + mutex_init(&dev->io_mutex); + spin_lock_init(&dev->err_lock); + init_usb_anchor(&dev->submitted); + init_waitqueue_head(&dev->bulk_in_wait); + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + dev->interface = interface; + + /* set up the endpoint information */ + /* use only the first bulk-in and bulk-out endpoints */ + retval = usb_find_common_endpoints(interface->cur_altsetting, + &bulk_in, &bulk_out, NULL, NULL); + if (retval) { + dev_err(&interface->dev, + "Could not find both bulk-in and bulk-out endpoints\n"); + goto error; + } + + dev->bulk_in_size = usb_endpoint_maxp(bulk_in); + dev->bulk_in_endpoint_addr = bulk_in->bEndpointAddress; + dev->bulk_in_buffer = kmalloc(dev->bulk_in_size, GFP_KERNEL); + if (!dev->bulk_in_buffer) { + retval = -ENOMEM; + goto error; + } + dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!dev->bulk_in_urb) { + retval = -ENOMEM; + goto error; + } + + dev->bulk_out_endpoint_addr = bulk_out->bEndpointAddress; + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* let the world know */ + + device_path = kobject_get_path(&dev->udev->dev.kobj, GFP_KERNEL); + pr_alert("%s:%s - New lpvo_usb_device -> bus: %d dev: %d path: %s\n", NAME, __func__, + dev->udev->bus->busnum, dev->udev->devnum, device_path); + kfree(device_path); + +#if USER_DEVICE + /* we can register the device now, as it is ready */ + retval = usb_register_dev(interface, &skel_class); + if (retval) { + /* something prevented us from registering this driver */ + dev_err(&interface->dev, + "Not able to get a minor for this device.\n"); + usb_set_intfdata(interface, NULL); + goto error; + } + + /* let the user know what node this device is now attached to */ + dev_info(&interface->dev, + "lpvo_usb_gpib device now attached to lpvo_raw%d", + interface->minor); +#endif + + write_latency_timer(dev->udev); /* adjust the latency timer */ + + usb_gpib_init_module(interface); /* last, init the lpvo for this minor */ + + return 0; + +error: + /* this frees allocated memory */ + kref_put(&dev->kref, skel_delete); + + return retval; +} + +static void skel_disconnect(struct usb_interface *interface) +{ + struct usb_skel *dev; + int minor = interface->minor; + + usb_gpib_exit_module(minor); /* first, disactivate the lpvo */ + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + +#if USER_DEVICE + /* give back our minor */ + usb_deregister_dev(interface, &skel_class); +#endif + + /* prevent more I/O from starting */ + mutex_lock(&dev->io_mutex); + dev->interface = NULL; + mutex_unlock(&dev->io_mutex); + + usb_kill_anchored_urbs(&dev->submitted); + + /* decrement our usage count */ + kref_put(&dev->kref, skel_delete); + + dev_info(&interface->dev, "USB lpvo_raw #%d now disconnected", minor); +} + +static void skel_draw_down(struct usb_skel *dev) +{ + int time; + + time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); + if (!time) + usb_kill_anchored_urbs(&dev->submitted); + usb_kill_urb(dev->bulk_in_urb); +} + +static int skel_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_skel *dev = usb_get_intfdata(intf); + + if (!dev) + return 0; + skel_draw_down(dev); + return 0; +} + +static int skel_resume(struct usb_interface *intf) +{ + return 0; +} + +static int skel_pre_reset(struct usb_interface *intf) +{ + struct usb_skel *dev = usb_get_intfdata(intf); + + mutex_lock(&dev->io_mutex); + skel_draw_down(dev); + + return 0; +} + +static int skel_post_reset(struct usb_interface *intf) +{ + struct usb_skel *dev = usb_get_intfdata(intf); + + /* we are sure no URBs are active - no locking needed */ + dev->errors = -EPIPE; + mutex_unlock(&dev->io_mutex); + + return 0; +} + +static struct usb_driver skel_driver = { + .name = NAME, + .probe = skel_probe, + .disconnect = skel_disconnect, + .suspend = skel_suspend, + .resume = skel_resume, + .pre_reset = skel_pre_reset, + .post_reset = skel_post_reset, + .id_table = skel_table, + .supports_autosuspend = 1, +}; + +module_usb_driver(skel_driver); diff --git a/drivers/staging/gpib/nec7210/Makefile b/drivers/staging/gpib/nec7210/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8d4d90f211092d28581bdb1fd33ec05d2f72385f --- /dev/null +++ b/drivers/staging/gpib/nec7210/Makefile @@ -0,0 +1,4 @@ + +obj-m += nec7210.o + + diff --git a/drivers/staging/gpib/nec7210/board.h b/drivers/staging/gpib/nec7210/board.h new file mode 100644 index 0000000000000000000000000000000000000000..ac3fe38ade57269296ed7438781a412c63dd2cf6 --- /dev/null +++ b/drivers/staging/gpib/nec7210/board.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _GPIB_PCIIA_BOARD_H +#define _GPIB_PCIIA_BOARD_H + +#include "gpibP.h" +#include <linux/io.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/delay.h> + +#include "nec7210.h" + +#endif //_GPIB_PCIIA_BOARD_H + diff --git a/drivers/staging/gpib/nec7210/nec7210.c b/drivers/staging/gpib/nec7210/nec7210.c new file mode 100644 index 0000000000000000000000000000000000000000..1d995103549746f460b036f5571b6931f87d3c9b --- /dev/null +++ b/drivers/staging/gpib/nec7210/nec7210.c @@ -0,0 +1,1134 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#include "board.h" +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/dma.h> +#include <linux/bitops.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/delay.h> + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB library code for NEC uPD7210"); + +int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_byte, + int compare_8_bits) +{ + write_byte(priv, eos_byte, EOSR); + priv->auxa_bits |= HR_REOS; + if (compare_8_bits) + priv->auxa_bits |= HR_BIN; + else + priv->auxa_bits &= ~HR_BIN; + write_byte(priv, priv->auxa_bits, AUXMR); + return 0; +} +EXPORT_SYMBOL(nec7210_enable_eos); + +void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv) +{ + priv->auxa_bits &= ~HR_REOS; + write_byte(priv, priv->auxa_bits, AUXMR); +} +EXPORT_SYMBOL(nec7210_disable_eos); + +int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result) +{ + int ret; + + clear_bit(COMMAND_READY_BN, &priv->state); + + // execute parallel poll + write_byte(priv, AUX_EPP, AUXMR); + // wait for result FIXME: support timeouts + ret = wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state)); + if (ret) { + dev_dbg(board->gpib_dev, "gpib: parallel poll interrupted\n"); + return -ERESTARTSYS; + } + *result = read_byte(priv, CPTR); + + return 0; +} +EXPORT_SYMBOL(nec7210_parallel_poll); + +void nec7210_parallel_poll_configure(gpib_board_t *board, + struct nec7210_priv *priv, unsigned int configuration) +{ + write_byte(priv, PPR | configuration, AUXMR); +} +EXPORT_SYMBOL(nec7210_parallel_poll_configure); + +void nec7210_parallel_poll_response(gpib_board_t *board, struct nec7210_priv *priv, int ist) +{ + if (ist) + write_byte(priv, AUX_SPPF, AUXMR); + else + write_byte(priv, AUX_CPPF, AUXMR); +} +EXPORT_SYMBOL(nec7210_parallel_poll_response); +/* This is really only adequate for chips that do a 488.2 style reqt/reqf + * based on bit 6 of the SPMR (see chapter 11.3.3 of 488.2). For simpler chips that simply + * set rsv directly based on bit 6, we either need to do more hardware setup to expose + * the 488.2 capability (for example with NI chips), or we need to implement the + * 488.2 set srv state machine in the driver (if that is even viable). + */ +void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status) +{ + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + if (status & request_service_bit) { + priv->srq_pending = 1; + clear_bit(SPOLL_NUM, &board->status); + + } else { + priv->srq_pending = 0; + } + write_byte(priv, status, SPMR); + spin_unlock_irqrestore(&board->spinlock, flags); +} +EXPORT_SYMBOL(nec7210_serial_poll_response); + +uint8_t nec7210_serial_poll_status(gpib_board_t *board, struct nec7210_priv *priv) +{ + return read_byte(priv, SPSR); +} +EXPORT_SYMBOL(nec7210_serial_poll_status); + +int nec7210_primary_address(const gpib_board_t *board, struct nec7210_priv *priv, + unsigned int address) +{ + // put primary address in address0 + write_byte(priv, address & ADDRESS_MASK, ADR); + return 0; +} +EXPORT_SYMBOL(nec7210_primary_address); + +int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv, + unsigned int address, int enable) +{ + if (enable) { + // put secondary address in address1 + write_byte(priv, HR_ARS | (address & ADDRESS_MASK), ADR); + // go to address mode 2 + priv->reg_bits[ADMR] &= ~HR_ADM0; + priv->reg_bits[ADMR] |= HR_ADM1; + } else { + // disable address1 register + write_byte(priv, HR_ARS | HR_DT | HR_DL, ADR); + // go to address mode 1 + priv->reg_bits[ADMR] |= HR_ADM0; + priv->reg_bits[ADMR] &= ~HR_ADM1; + } + write_byte(priv, priv->reg_bits[ADMR], ADMR); + return 0; +} +EXPORT_SYMBOL(nec7210_secondary_address); + +static void update_talker_state(struct nec7210_priv *priv, unsigned int address_status_bits) +{ + if ((address_status_bits & HR_TA)) { + if ((address_status_bits & HR_NATN)) { + if (address_status_bits & HR_SPMS) + priv->talker_state = serial_poll_active; + else + priv->talker_state = talker_active; + } else { + priv->talker_state = talker_addressed; + } + } else { + priv->talker_state = talker_idle; + } +} + +static void update_listener_state(struct nec7210_priv *priv, unsigned int address_status_bits) +{ + if (address_status_bits & HR_LA) { + if ((address_status_bits & HR_NATN)) + priv->listener_state = listener_active; + else + priv->listener_state = listener_addressed; + } else { + priv->listener_state = listener_idle; + } +} + +unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv) +{ + int address_status_bits; + u8 spoll_status; + + if (!priv) + return 0; + + address_status_bits = read_byte(priv, ADSR); + if (address_status_bits & HR_CIC) + set_bit(CIC_NUM, &board->status); + else + clear_bit(CIC_NUM, &board->status); + // check for talker/listener addressed + update_talker_state(priv, address_status_bits); + if (priv->talker_state == talker_active || priv->talker_state == talker_addressed) + set_bit(TACS_NUM, &board->status); + else + clear_bit(TACS_NUM, &board->status); + update_listener_state(priv, address_status_bits); + if (priv->listener_state == listener_active || + priv->listener_state == listener_addressed) + set_bit(LACS_NUM, &board->status); + else + clear_bit(LACS_NUM, &board->status); + if (address_status_bits & HR_NATN) + clear_bit(ATN_NUM, &board->status); + else + set_bit(ATN_NUM, &board->status); + spoll_status = nec7210_serial_poll_status(board, priv); + if (priv->srq_pending && (spoll_status & request_service_bit) == 0) { + priv->srq_pending = 0; + set_bit(SPOLL_NUM, &board->status); + } +// dev_dbg(board->gpib_dev, "status 0x%x, state 0x%x\n", board->status, priv->state); + + /* we rely on the interrupt handler to set the + * rest of the status bits + */ + + return board->status; +} +EXPORT_SYMBOL(nec7210_update_status_nolock); + +unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv, + unsigned int clear_mask) +{ + unsigned long flags; + unsigned int retval; + + spin_lock_irqsave(&board->spinlock, flags); + board->status &= ~clear_mask; + retval = nec7210_update_status_nolock(board, priv); + spin_unlock_irqrestore(&board->spinlock, flags); + + return retval; +} +EXPORT_SYMBOL(nec7210_update_status); + +unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg, + unsigned int mask, unsigned int bits) +{ + priv->reg_bits[reg] &= ~mask; + priv->reg_bits[reg] |= mask & bits; + write_byte(priv, priv->reg_bits[reg], reg); + return priv->reg_bits[reg]; +} +EXPORT_SYMBOL(nec7210_set_reg_bits); + +void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode) +{ + unsigned long flags; + + mode &= HR_HANDSHAKE_MASK; + + spin_lock_irqsave(&board->spinlock, flags); + if ((priv->auxa_bits & HR_HANDSHAKE_MASK) != mode) { + priv->auxa_bits &= ~HR_HANDSHAKE_MASK; + priv->auxa_bits |= mode; + write_byte(priv, priv->auxa_bits, AUXMR); + } + spin_unlock_irqrestore(&board->spinlock, flags); +} +EXPORT_SYMBOL(nec7210_set_handshake_mode); + +uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end) +{ + unsigned long flags; + u8 data; + + spin_lock_irqsave(&board->spinlock, flags); + data = read_byte(priv, DIR); + clear_bit(READ_READY_BN, &priv->state); + if (test_and_clear_bit(RECEIVED_END_BN, &priv->state)) + *end = 1; + else + *end = 0; + spin_unlock_irqrestore(&board->spinlock, flags); + + return data; +} +EXPORT_SYMBOL(nec7210_read_data_in); + +int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous) +{ + int i; + const int timeout = 100; + int retval = 0; + unsigned int adsr_bits = 0; + + if (syncronous) + write_byte(priv, AUX_TCS, AUXMR); + else + write_byte(priv, AUX_TCA, AUXMR); + // busy wait until ATN is asserted + for (i = 0; i < timeout; i++) { + adsr_bits = read_byte(priv, ADSR); + if ((adsr_bits & HR_NATN) == 0) + break; + udelay(1); + } + if (i == timeout) + return -ETIMEDOUT; + + clear_bit(WRITE_READY_BN, &priv->state); + + return retval; +} +EXPORT_SYMBOL(nec7210_take_control); + +int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv) +{ + int i; + const int timeout = 1000; + unsigned int adsr_bits = 0; + int retval = 0; + + write_byte(priv, AUX_GTS, AUXMR); + // busy wait until ATN is released + for (i = 0; i < timeout; i++) { + adsr_bits = read_byte(priv, ADSR); + if (adsr_bits & HR_NATN) + break; + udelay(1); + } + // if busy wait has failed, try sleeping + if (i == timeout) { + for (i = 0; i < HZ; i++) { + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout(1)) + return -ERESTARTSYS; + adsr_bits = read_byte(priv, ADSR); + if (adsr_bits & HR_NATN) + break; + } + if (i == HZ) { + pr_err("nec7210: error waiting for NATN\n"); + return -ETIMEDOUT; + } + } + + clear_bit(COMMAND_READY_BN, &priv->state); + return retval; +} +EXPORT_SYMBOL(nec7210_go_to_standby); + +void nec7210_request_system_control(gpib_board_t *board, struct nec7210_priv *priv, + int request_control) +{ + if (request_control == 0) { + write_byte(priv, AUX_CREN, AUXMR); + write_byte(priv, AUX_CIFC, AUXMR); + write_byte(priv, AUX_DSC, AUXMR); + } +} +EXPORT_SYMBOL(nec7210_request_system_control); + +void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert) +{ + if (assert) + write_byte(priv, AUX_SIFC, AUXMR); + else + write_byte(priv, AUX_CIFC, AUXMR); +} +EXPORT_SYMBOL(nec7210_interface_clear); + +void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable) +{ + if (enable) + write_byte(priv, AUX_SREN, AUXMR); + else + write_byte(priv, AUX_CREN, AUXMR); +} +EXPORT_SYMBOL(nec7210_remote_enable); + +void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + if (test_bit(RFD_HOLDOFF_BN, &priv->state) && + test_bit(READ_READY_BN, &priv->state) == 0) { + write_byte(priv, AUX_FH, AUXMR); + clear_bit(RFD_HOLDOFF_BN, &priv->state); + } + spin_unlock_irqrestore(&board->spinlock, flags); +} +EXPORT_SYMBOL(nec7210_release_rfd_holdoff); + +unsigned int nec7210_t1_delay(gpib_board_t *board, struct nec7210_priv *priv, + unsigned int nano_sec) +{ + unsigned int retval; + + if (nano_sec <= 500) { + priv->auxb_bits |= HR_TRI; + retval = 500; + } else { + priv->auxb_bits &= ~HR_TRI; + retval = 2000; + } + write_byte(priv, priv->auxb_bits, AUXMR); + + return retval; +} +EXPORT_SYMBOL(nec7210_t1_delay); + +void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv) +{ + write_byte(priv, AUX_RTL, AUXMR); +} +EXPORT_SYMBOL(nec7210_return_to_local); + +static inline short nec7210_atn_has_changed(gpib_board_t *board, struct nec7210_priv *priv) +{ + short address_status_bits = read_byte(priv, ADSR); + + if (address_status_bits & HR_NATN) { + if (test_bit(ATN_NUM, &board->status)) + return 1; + else + return 0; + } else { + if (test_bit(ATN_NUM, &board->status)) + return 0; + else + return 1; + } + return -1; +} + +int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t + *buffer, size_t length, size_t *bytes_written) +{ + int retval = 0; + unsigned long flags; + + *bytes_written = 0; + + clear_bit(BUS_ERROR_BN, &priv->state); + + while (*bytes_written < length) { + if (wait_event_interruptible(board->wait, + test_bit(COMMAND_READY_BN, &priv->state) || + test_bit(BUS_ERROR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib command wait interrupted\n"); + retval = -ERESTARTSYS; + break; + } + if (test_bit(TIMO_NUM, &board->status)) + break; + if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) { + pr_err("nec7210: bus error on command byte\n"); + break; + } + + spin_lock_irqsave(&board->spinlock, flags); + clear_bit(COMMAND_READY_BN, &priv->state); + write_byte(priv, buffer[*bytes_written], CDOR); + spin_unlock_irqrestore(&board->spinlock, flags); + + ++(*bytes_written); + + if (need_resched()) + schedule(); + } + // wait for last byte to get sent + if (wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state) || + test_bit(BUS_ERROR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib command wait interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) { + dev_dbg(board->gpib_dev, "gpib command timed out\n"); + retval = -ETIMEDOUT; + } + if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) { + pr_err("nec7210: bus error on command byte\n"); + retval = -EIO; + } + + return retval; +} +EXPORT_SYMBOL(nec7210_command); + +static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval = 0; + + *bytes_read = 0; + *end = 0; + + while (*bytes_read < length) { + if (wait_event_interruptible(board->wait, + test_bit(READ_READY_BN, &priv->state) || + test_bit(DEV_CLEAR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "nec7210: pio read wait interrupted\n"); + retval = -ERESTARTSYS; + break; + } + if (test_bit(READ_READY_BN, &priv->state)) { + if (*bytes_read == 0) { + /* We set the handshake mode here because we know + * no new bytes will arrive (it has already arrived + * and is awaiting being read out of the chip) while we are changing + * modes. This ensures we can reliably keep track + * of the holdoff state. + */ + nec7210_set_handshake_mode(board, priv, HR_HLDA); + } + buffer[(*bytes_read)++] = nec7210_read_data_in(board, priv, end); + if (*end) + break; + } + if (test_bit(TIMO_NUM, &board->status)) { + dev_dbg(board->gpib_dev, "interrupted by timeout\n"); + retval = -ETIMEDOUT; + break; + } + if (test_bit(DEV_CLEAR_BN, &priv->state)) { + dev_dbg(board->gpib_dev, "interrupted by device clear\n"); + retval = -EINTR; + break; + } + + if (*bytes_read < length) + nec7210_release_rfd_holdoff(board, priv); + + if (need_resched()) + schedule(); + } + return retval; +} + +#ifdef NEC_DMA +static ssize_t __dma_read(gpib_board_t *board, struct nec7210_priv *priv, size_t length) +{ + ssize_t retval = 0; + size_t count = 0; + unsigned long flags, dma_irq_flags; + + if (length == 0) + return 0; + + spin_lock_irqsave(&board->spinlock, flags); + + dma_irq_flags = claim_dma_lock(); + disable_dma(priv->dma_channel); + /* program dma controller */ + clear_dma_ff(priv->dma_channel); + set_dma_count(priv->dma_channel, length); + set_dma_addr(priv->dma_channel, priv->dma_buffer_addr); + set_dma_mode(priv->dma_channel, DMA_MODE_READ); + release_dma_lock(dma_irq_flags); + + enable_dma(priv->dma_channel); + + set_bit(DMA_READ_IN_PROGRESS_BN, &priv->state); + clear_bit(READ_READY_BN, &priv->state); + + // enable nec7210 dma + nec7210_set_reg_bits(priv, IMR2, HR_DMAI, HR_DMAI); + + spin_unlock_irqrestore(&board->spinlock, flags); + + // wait for data to transfer + if (wait_event_interruptible(board->wait, + test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state) == 0 || + test_bit(DEV_CLEAR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "nec7210: dma read wait interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &priv->state)) + retval = -EINTR; + + // disable nec7210 dma + nec7210_set_reg_bits(priv, IMR2, HR_DMAI, 0); + + // record how many bytes we transferred + flags = claim_dma_lock(); + clear_dma_ff(priv->dma_channel); + disable_dma(priv->dma_channel); + count += length - get_dma_residue(priv->dma_channel); + release_dma_lock(flags); + + return retval ? retval : count; +} + +static ssize_t dma_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length) +{ + size_t remain = length; + size_t transfer_size; + ssize_t retval = 0; + + while (remain > 0) { + transfer_size = (priv->dma_buffer_length < remain) ? + priv->dma_buffer_length : remain; + retval = __dma_read(board, priv, transfer_size); + if (retval < 0) + break; + memcpy(buffer, priv->dma_buffer, transfer_size); + remain -= retval; + buffer += retval; + if (test_bit(RECEIVED_END_BN, &priv->state)) + break; + } + + if (retval < 0) + return retval; + + return length - remain; +} +#endif + +int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval = 0; + + *end = 0; + *bytes_read = 0; + + if (length == 0) + return 0; + + clear_bit(DEV_CLEAR_BN, &priv->state); // XXX wrong + + nec7210_release_rfd_holdoff(board, priv); + + retval = pio_read(board, priv, buffer, length, end, bytes_read); + + return retval; +} +EXPORT_SYMBOL(nec7210_read); + +static int pio_write_wait(gpib_board_t *board, struct nec7210_priv *priv, + short wake_on_lacs, short wake_on_atn, short wake_on_bus_error) +{ + // wait until byte is ready to be sent + if (wait_event_interruptible(board->wait, + (test_bit(TACS_NUM, &board->status) && + test_bit(WRITE_READY_BN, &priv->state)) || + test_bit(DEV_CLEAR_BN, &priv->state) || + (wake_on_bus_error && test_bit(BUS_ERROR_BN, &priv->state)) || + (wake_on_lacs && test_bit(LACS_NUM, &board->status)) || + (wake_on_atn && test_bit(ATN_NUM, &board->status)) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted\n"); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) { + dev_dbg(board->gpib_dev, "nec7210: write timed out\n"); + return -ETIMEDOUT; + } + if (test_bit(DEV_CLEAR_BN, &priv->state)) { + dev_dbg(board->gpib_dev, "nec7210: write interrupted by clear\n"); + return -EINTR; + } + if (wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state)) { + dev_dbg(board->gpib_dev, "nec7210: bus error on write\n"); + return -EIO; + } + return 0; +} + +static int pio_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length, size_t *bytes_written) +{ + size_t last_count = 0; + ssize_t retval = 0; + unsigned long flags; + const int max_bus_errors = (length > 1000) ? length : 1000; + int bus_error_count = 0; + *bytes_written = 0; + + clear_bit(BUS_ERROR_BN, &priv->state); + + while (*bytes_written < length) { + if (need_resched()) + schedule(); + + retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210); + if (retval == -EIO) { + /* resend last byte on bus error */ + *bytes_written = last_count; + dev_dbg(board->gpib_dev, "resending %c\n", buffer[*bytes_written]); + /* we can get unrecoverable bus errors, + * so give up after a while + */ + bus_error_count++; + if (bus_error_count > max_bus_errors) + return retval; + continue; + } else { + if (retval < 0) + return retval; + } + spin_lock_irqsave(&board->spinlock, flags); + clear_bit(BUS_ERROR_BN, &priv->state); + clear_bit(WRITE_READY_BN, &priv->state); + last_count = *bytes_written; + write_byte(priv, buffer[(*bytes_written)++], CDOR); + spin_unlock_irqrestore(&board->spinlock, flags); + } + retval = pio_write_wait(board, priv, 1, 1, priv->type == NEC7210); + return retval; +} + +#ifdef NEC_DMA +static ssize_t __dma_write(gpib_board_t *board, struct nec7210_priv *priv, dma_addr_t address, + size_t length) +{ + unsigned long flags, dma_irq_flags; + int residue = 0; + int retval = 0; + + spin_lock_irqsave(&board->spinlock, flags); + + /* program dma controller */ + dma_irq_flags = claim_dma_lock(); + disable_dma(priv->dma_channel); + clear_dma_ff(priv->dma_channel); + set_dma_count(priv->dma_channel, length); + set_dma_addr(priv->dma_channel, address); + set_dma_mode(priv->dma_channel, DMA_MODE_WRITE); + enable_dma(priv->dma_channel); + release_dma_lock(dma_irq_flags); + + // enable board's dma for output + nec7210_set_reg_bits(priv, IMR2, HR_DMAO, HR_DMAO); + + clear_bit(WRITE_READY_BN, &priv->state); + set_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state); + + spin_unlock_irqrestore(&board->spinlock, flags); + + // suspend until message is sent + if (wait_event_interruptible(board->wait, + test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0 || + test_bit(BUS_ERROR_BN, &priv->state) || + test_bit(DEV_CLEAR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + if (test_and_clear_bit(DEV_CLEAR_BN, &priv->state)) + retval = -EINTR; + if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) + retval = -EIO; + + // disable board's dma + nec7210_set_reg_bits(priv, IMR2, HR_DMAO, 0); + + dma_irq_flags = claim_dma_lock(); + clear_dma_ff(priv->dma_channel); + disable_dma(priv->dma_channel); + residue = get_dma_residue(priv->dma_channel); + release_dma_lock(dma_irq_flags); + + if (residue) + retval = -EPIPE; + + return retval ? retval : length; +} + +static ssize_t dma_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, + size_t length) +{ + size_t remain = length; + size_t transfer_size; + ssize_t retval = 0; + + while (remain > 0) { + transfer_size = (priv->dma_buffer_length < remain) ? + priv->dma_buffer_length : remain; + memcpy(priv->dma_buffer, buffer, transfer_size); + retval = __dma_write(board, priv, priv->dma_buffer_addr, transfer_size); + if (retval < 0) + break; + remain -= retval; + buffer += retval; + } + + if (retval < 0) + return retval; + + return length - remain; +} +#endif +int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + int retval = 0; + + *bytes_written = 0; + + clear_bit(DEV_CLEAR_BN, &priv->state); //XXX + + if (send_eoi) + length-- ; /* save the last byte for sending EOI */ + + if (length > 0) { + // isa dma transfer + if (0 /*priv->dma_channel*/) { +/* + * dma writes are unreliable since they can't recover from bus errors + * (which happen when ATN is asserted in the middle of a write) + */ +#ifdef NEC_DMA + retval = dma_write(board, priv, buffer, length); + if (retval < 0) + return retval; + count += retval; +#endif + } else { // PIO transfer + size_t num_bytes; + + retval = pio_write(board, priv, buffer, length, &num_bytes); + + *bytes_written += num_bytes; + if (retval < 0) + return retval; + } + } + if (send_eoi) { + size_t num_bytes; + + /* We need to wait to make sure we will immediately be able to write the data byte + * into the chip before sending the associated AUX_SEOI command. This is really + * only needed for length==1 since otherwise the earlier calls to pio_write + * will have dont the wait already. + */ + retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210); + if (retval < 0) + return retval; + /*send EOI */ + write_byte(priv, AUX_SEOI, AUXMR); + + retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + } + + return retval; +} +EXPORT_SYMBOL(nec7210_write); + +/* + * interrupt service routine + */ +irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv) +{ + int status1, status2; + + // read interrupt status (also clears status) + status1 = read_byte(priv, ISR1); + status2 = read_byte(priv, ISR2); + + return nec7210_interrupt_have_status(board, priv, status1, status2); +} +EXPORT_SYMBOL(nec7210_interrupt); + +irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board, + struct nec7210_priv *priv, int status1, int status2) +{ +#ifdef NEC_DMA + unsigned long dma_flags; +#endif + int retval = IRQ_NONE; + + // record service request in status + if (status2 & HR_SRQI) + set_bit(SRQI_NUM, &board->status); + + // change in lockout status + if (status2 & HR_LOKC) { + if (status2 & HR_LOK) + set_bit(LOK_NUM, &board->status); + else + clear_bit(LOK_NUM, &board->status); + } + + // change in remote status + if (status2 & HR_REMC) { + if (status2 & HR_REM) + set_bit(REM_NUM, &board->status); + else + clear_bit(REM_NUM, &board->status); + } + + // record reception of END + if (status1 & HR_END) { + set_bit(RECEIVED_END_BN, &priv->state); + if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE) + set_bit(RFD_HOLDOFF_BN, &priv->state); + } + + // get incoming data in PIO mode + if ((status1 & HR_DI)) { + set_bit(READ_READY_BN, &priv->state); + if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDA) + set_bit(RFD_HOLDOFF_BN, &priv->state); + } +#ifdef NEC_DMA + // check for dma read transfer complete + if (test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state)) { + dma_flags = claim_dma_lock(); + disable_dma(priv->dma_channel); + clear_dma_ff(priv->dma_channel); + if ((status1 & HR_END) || get_dma_residue(priv->dma_channel) == 0) + clear_bit(DMA_READ_IN_PROGRESS_BN, &priv->state); + else + enable_dma(priv->dma_channel); + release_dma_lock(dma_flags); + } +#endif + if ((status1 & HR_DO)) { + if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0) + set_bit(WRITE_READY_BN, &priv->state); +#ifdef NEC_DMA + if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state)) { // write data, isa dma mode + // check if dma transfer is complete + dma_flags = claim_dma_lock(); + disable_dma(priv->dma_channel); + clear_dma_ff(priv->dma_channel); + if (get_dma_residue(priv->dma_channel) == 0) { + clear_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state); + // XXX race? byte may still be in CDOR reg + } else { + clear_bit(WRITE_READY_BN, &priv->state); + enable_dma(priv->dma_channel); + } + release_dma_lock(dma_flags); + } +#endif + } + + // outgoing command can be sent + if (status2 & HR_CO) + set_bit(COMMAND_READY_BN, &priv->state); + + // command pass through received + if (status1 & HR_CPT) { + unsigned int command; + + command = read_byte(priv, CPTR) & gpib_command_mask; + write_byte(priv, AUX_NVAL, AUXMR); +// printk("gpib: command pass through 0x%x\n", command); + } + + if (status1 & HR_ERR) + set_bit(BUS_ERROR_BN, &priv->state); + + if (status1 & HR_DEC) { + unsigned short address_status_bits = read_byte(priv, ADSR); + + // ignore device clear events if we are controller in charge + if ((address_status_bits & HR_CIC) == 0) { + push_gpib_event(board, EventDevClr); + set_bit(DEV_CLEAR_BN, &priv->state); + } + } + + if (status1 & HR_DET) + push_gpib_event(board, EventDevTrg); + + // Addressing status has changed + if (status2 & HR_ADSC) + set_bit(ADR_CHANGE_BN, &priv->state); + + if ((status1 & priv->reg_bits[IMR1]) || + (status2 & (priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK)) || + nec7210_atn_has_changed(board, priv)) { + nec7210_update_status_nolock(board, priv); + dev_dbg(board->gpib_dev, "minor %i, stat %lx, isr1 0x%x, imr1 0x%x, isr2 0x%x, imr2 0x%x\n", + board->minor, board->status, status1, priv->reg_bits[IMR1], status2, + priv->reg_bits[IMR2]); + wake_up_interruptible(&board->wait); /* wake up sleeping process */ + retval = IRQ_HANDLED; + } + + return retval; +} +EXPORT_SYMBOL(nec7210_interrupt_have_status); + +void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board) +{ + /* 7210 chip reset */ + write_byte(priv, AUX_CR, AUXMR); + + /* disable all interrupts */ + priv->reg_bits[IMR1] = 0; + write_byte(priv, priv->reg_bits[IMR1], IMR1); + priv->reg_bits[IMR2] = 0; + write_byte(priv, priv->reg_bits[IMR2], IMR2); + write_byte(priv, 0, SPMR); + + /* clear registers by reading */ + read_byte(priv, CPTR); + read_byte(priv, ISR1); + read_byte(priv, ISR2); + + /* parallel poll unconfigure */ + write_byte(priv, PPR | HR_PPU, AUXMR); + + priv->reg_bits[ADMR] = HR_TRM0 | HR_TRM1; + + priv->auxa_bits = AUXRA | HR_HLDA; + write_byte(priv, priv->auxa_bits, AUXMR); + + write_byte(priv, AUXRE | 0, AUXMR); + + /* set INT pin to active high, enable command pass through of unknown commands */ + priv->auxb_bits = AUXRB | HR_CPTE; + write_byte(priv, priv->auxb_bits, AUXMR); + write_byte(priv, AUXRE, AUXMR); +} +EXPORT_SYMBOL(nec7210_board_reset); + +void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board) +{ + /* set GPIB address */ + nec7210_primary_address(board, priv, board->pad); + nec7210_secondary_address(board, priv, board->sad, board->sad >= 0); + + // enable interrupts + priv->reg_bits[IMR1] = HR_ERRIE | HR_DECIE | HR_ENDIE | + HR_DETIE | HR_CPTIE | HR_DOIE | HR_DIIE; + priv->reg_bits[IMR2] = IMR2_ENABLE_INTR_MASK; + write_byte(priv, priv->reg_bits[IMR1], IMR1); + write_byte(priv, priv->reg_bits[IMR2], IMR2); + + write_byte(priv, AUX_PON, AUXMR); +} +EXPORT_SYMBOL(nec7210_board_online); + +#ifdef CONFIG_HAS_IOPORT +/* wrappers for io */ +uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num) +{ + return inb((unsigned long)(priv->iobase) + register_num * priv->offset); +} +EXPORT_SYMBOL(nec7210_ioport_read_byte); + +void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num) +{ + if (register_num == AUXMR) + /* locking makes absolutely sure noone accesses the + * AUXMR register faster than once per microsecond + */ + nec7210_locking_ioport_write_byte(priv, data, register_num); + else + outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset); +} +EXPORT_SYMBOL(nec7210_ioport_write_byte); + +/* locking variants of io wrappers, for chips that page-in registers */ +uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num) +{ + u8 retval; + unsigned long flags; + + spin_lock_irqsave(&priv->register_page_lock, flags); + retval = inb((unsigned long)(priv->iobase) + register_num * priv->offset); + spin_unlock_irqrestore(&priv->register_page_lock, flags); + return retval; +} +EXPORT_SYMBOL(nec7210_locking_ioport_read_byte); + +void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, + unsigned int register_num) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->register_page_lock, flags); + if (register_num == AUXMR) + udelay(1); + outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset); + spin_unlock_irqrestore(&priv->register_page_lock, flags); +} +EXPORT_SYMBOL(nec7210_locking_ioport_write_byte); +#endif + +uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num) +{ + return readb(priv->iobase + register_num * priv->offset); +} +EXPORT_SYMBOL(nec7210_iomem_read_byte); + +void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num) +{ + if (register_num == AUXMR) + /* locking makes absolutely sure noone accesses the + * AUXMR register faster than once per microsecond + */ + nec7210_locking_iomem_write_byte(priv, data, register_num); + else + writeb(data, priv->iobase + register_num * priv->offset); +} +EXPORT_SYMBOL(nec7210_iomem_write_byte); + +uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num) +{ + u8 retval; + unsigned long flags; + + spin_lock_irqsave(&priv->register_page_lock, flags); + retval = readb(priv->iobase + register_num * priv->offset); + spin_unlock_irqrestore(&priv->register_page_lock, flags); + return retval; +} +EXPORT_SYMBOL(nec7210_locking_iomem_read_byte); + +void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, + unsigned int register_num) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->register_page_lock, flags); + if (register_num == AUXMR) + udelay(1); + writeb(data, priv->iobase + register_num * priv->offset); + spin_unlock_irqrestore(&priv->register_page_lock, flags); +} +EXPORT_SYMBOL(nec7210_locking_iomem_write_byte); + +static int __init nec7210_init_module(void) +{ + return 0; +} + +static void __exit nec7210_exit_module(void) +{ +} + +module_init(nec7210_init_module); +module_exit(nec7210_exit_module); diff --git a/drivers/staging/gpib/ni_usb/Makefile b/drivers/staging/gpib/ni_usb/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e22b3b21a62c6b9533d16fbad99e5f4d26c1ffad --- /dev/null +++ b/drivers/staging/gpib/ni_usb/Makefile @@ -0,0 +1,4 @@ + +obj-m += ni_usb_gpib.o + + diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..b7b6fb1be379032b894e2b0cb7d0325c83bf4b07 --- /dev/null +++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c @@ -0,0 +1,2640 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * driver for National Instruments usb to gpib adapters + * copyright : (C) 2004 by Frank Mori Hess + ***************************************************************************/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include "ni_usb_gpib.h" +#include "gpibP.h" +#include "nec7210.h" +#include "tnt4882_registers.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for National Instruments USB devices"); + +#define MAX_NUM_NI_USB_INTERFACES 128 +static struct usb_interface *ni_usb_driver_interfaces[MAX_NUM_NI_USB_INTERFACES]; + +static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status); +static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits); +static void ni_usb_stop(struct ni_usb_priv *ni_priv); + +static DEFINE_MUTEX(ni_usb_hotplug_lock); + +//calculates a reasonable timeout in that can be passed to usb functions +static inline unsigned long ni_usb_timeout_msecs(unsigned int usec) +{ + if (usec == 0) + return 0; + return 2000 + usec / 500; +}; + +// returns timeout code byte for use in ni-usb-b instructions +static unsigned short ni_usb_timeout_code(unsigned int usec) +{ + if (usec == 0) + return 0xf0; + else if (usec <= 10) + return 0xf1; + else if (usec <= 30) + return 0xf2; + else if (usec <= 100) + return 0xf3; + else if (usec <= 300) + return 0xf4; + else if (usec <= 1000) + return 0xf5; + else if (usec <= 3000) + return 0xf6; + else if (usec <= 10000) + return 0xf7; + else if (usec <= 30000) + return 0xf8; + else if (usec <= 100000) + return 0xf9; + else if (usec <= 300000) + return 0xfa; + else if (usec <= 1000000) + return 0xfb; + else if (usec <= 3000000) + return 0xfc; + else if (usec <= 10000000) + return 0xfd; + else if (usec <= 30000000) + return 0xfe; + else if (usec <= 100000000) + return 0xff; + else if (usec <= 300000000) + return 0x01; + /* NI driver actually uses 0xff for timeout T1000s, which is a bug in their code. + * I've verified on a usb-b that a code of 0x2 is correct for a 1000 sec timeout + */ + else if (usec <= 1000000000) + return 0x02; + pr_err("%s: bug? usec is greater than 1e9\n", __func__); + return 0xf0; +} + +static void ni_usb_bulk_complete(struct urb *urb) +{ + struct ni_usb_urb_ctx *context = urb->context; + +// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__, +// urb->status, urb->error_count, urb->actual_length); + up(&context->complete); +} + +static void ni_usb_timeout_handler(struct timer_list *t) +{ + struct ni_usb_priv *ni_priv = from_timer(ni_priv, t, bulk_timer); + struct ni_usb_urb_ctx *context = &ni_priv->context; + + context->timed_out = 1; + up(&context->complete); +}; + +// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases +static int ni_usb_nonblocking_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data, + int data_length, int *actual_data_length, + int timeout_msecs) +{ + struct usb_device *usb_dev; + int retval; + unsigned int out_pipe; + struct ni_usb_urb_ctx *context = &ni_priv->context; + + *actual_data_length = 0; + mutex_lock(&ni_priv->bulk_transfer_lock); + if (!ni_priv->bus_interface) { + mutex_unlock(&ni_priv->bulk_transfer_lock); + return -ENODEV; + } + if (ni_priv->bulk_urb) { + mutex_unlock(&ni_priv->bulk_transfer_lock); + return -EAGAIN; + } + ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ni_priv->bulk_urb) { + mutex_unlock(&ni_priv->bulk_transfer_lock); + return -ENOMEM; + } + usb_dev = interface_to_usbdev(ni_priv->bus_interface); + out_pipe = usb_sndbulkpipe(usb_dev, ni_priv->bulk_out_endpoint); + sema_init(&context->complete, 0); + context->timed_out = 0; + usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, out_pipe, data, data_length, + &ni_usb_bulk_complete, context); + + if (timeout_msecs) + mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); + + retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL); + if (retval) { + del_timer_sync(&ni_priv->bulk_timer); + usb_free_urb(ni_priv->bulk_urb); + ni_priv->bulk_urb = NULL; + dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", + __func__, retval); + mutex_unlock(&ni_priv->bulk_transfer_lock); + return retval; + } + mutex_unlock(&ni_priv->bulk_transfer_lock); + down(&context->complete); // wait for ni_usb_bulk_complete + if (context->timed_out) { + usb_kill_urb(ni_priv->bulk_urb); + dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__); + retval = -ETIMEDOUT; + } else { + retval = ni_priv->bulk_urb->status; + } + + del_timer_sync(&ni_priv->bulk_timer); + *actual_data_length = ni_priv->bulk_urb->actual_length; + mutex_lock(&ni_priv->bulk_transfer_lock); + usb_free_urb(ni_priv->bulk_urb); + ni_priv->bulk_urb = NULL; + mutex_unlock(&ni_priv->bulk_transfer_lock); + return retval; +} + +static int ni_usb_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data, int data_length, + int *actual_data_length, int timeout_msecs) +{ + int retval; + int timeout_msecs_remaining = timeout_msecs; + + retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length, actual_data_length, + timeout_msecs_remaining); + while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) { + usleep_range(1000, 1500); + retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length, + actual_data_length, + timeout_msecs_remaining); + if (timeout_msecs != 0) + --timeout_msecs_remaining; + } + if (timeout_msecs != 0 && timeout_msecs_remaining <= 0) + return -ETIMEDOUT; + return retval; +} + +// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases +static int ni_usb_nonblocking_receive_bulk_msg(struct ni_usb_priv *ni_priv, + void *data, int data_length, + int *actual_data_length, int timeout_msecs, + int interruptible) +{ + struct usb_device *usb_dev; + int retval; + unsigned int in_pipe; + struct ni_usb_urb_ctx *context = &ni_priv->context; + + *actual_data_length = 0; + mutex_lock(&ni_priv->bulk_transfer_lock); + if (!ni_priv->bus_interface) { + mutex_unlock(&ni_priv->bulk_transfer_lock); + return -ENODEV; + } + if (ni_priv->bulk_urb) { + mutex_unlock(&ni_priv->bulk_transfer_lock); + return -EAGAIN; + } + ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ni_priv->bulk_urb) { + mutex_unlock(&ni_priv->bulk_transfer_lock); + return -ENOMEM; + } + usb_dev = interface_to_usbdev(ni_priv->bus_interface); + in_pipe = usb_rcvbulkpipe(usb_dev, ni_priv->bulk_in_endpoint); + sema_init(&context->complete, 0); + context->timed_out = 0; + usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, in_pipe, data, data_length, + &ni_usb_bulk_complete, context); + + if (timeout_msecs) + mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); + + //printk("%s: submitting urb\n", __func__); + retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL); + if (retval) { + del_timer_sync(&ni_priv->bulk_timer); + usb_free_urb(ni_priv->bulk_urb); + ni_priv->bulk_urb = NULL; + dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n", + __func__, retval); + mutex_unlock(&ni_priv->bulk_transfer_lock); + return retval; + } + mutex_unlock(&ni_priv->bulk_transfer_lock); + if (interruptible) { + if (down_interruptible(&context->complete)) { + /* If we got interrupted by a signal while + * waiting for the usb gpib to respond, we + * should send a stop command so it will + * finish up with whatever it was doing and + * send its response now. + */ + ni_usb_stop(ni_priv); + retval = -ERESTARTSYS; + /* now do an uninterruptible wait, it shouldn't take long + * for the board to respond now. + */ + down(&context->complete); + } + } else { + down(&context->complete); + } + if (context->timed_out) { + usb_kill_urb(ni_priv->bulk_urb); + dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__); + retval = -ETIMEDOUT; + } else { + if (ni_priv->bulk_urb->status) + retval = ni_priv->bulk_urb->status; + } + del_timer_sync(&ni_priv->bulk_timer); + *actual_data_length = ni_priv->bulk_urb->actual_length; + mutex_lock(&ni_priv->bulk_transfer_lock); + usb_free_urb(ni_priv->bulk_urb); + ni_priv->bulk_urb = NULL; + mutex_unlock(&ni_priv->bulk_transfer_lock); + return retval; +} + +static int ni_usb_receive_bulk_msg(struct ni_usb_priv *ni_priv, void *data, + int data_length, int *actual_data_length, int timeout_msecs, + int interruptible) +{ + int retval; + int timeout_msecs_remaining = timeout_msecs; + + retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length, + actual_data_length, timeout_msecs_remaining, + interruptible); + while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) { + usleep_range(1000, 1500); + retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length, + actual_data_length, + timeout_msecs_remaining, + interruptible); + if (timeout_msecs != 0) + --timeout_msecs_remaining; + } + if (timeout_msecs && timeout_msecs_remaining <= 0) + return -ETIMEDOUT; + return retval; +} + +static int ni_usb_receive_control_msg(struct ni_usb_priv *ni_priv, __u8 request, + __u8 requesttype, __u16 value, __u16 index, + void *data, __u16 size, int timeout_msecs) +{ + struct usb_device *usb_dev; + int retval; + unsigned int in_pipe; + + mutex_lock(&ni_priv->control_transfer_lock); + if (!ni_priv->bus_interface) { + mutex_unlock(&ni_priv->control_transfer_lock); + return -ENODEV; + } + usb_dev = interface_to_usbdev(ni_priv->bus_interface); + in_pipe = usb_rcvctrlpipe(usb_dev, 0); + retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data, + size, timeout_msecs); + mutex_unlock(&ni_priv->control_transfer_lock); + return retval; +} + +static void ni_usb_soft_update_status(gpib_board_t *board, unsigned int ni_usb_ibsta, + unsigned int clear_mask) +{ + static const unsigned int ni_usb_ibsta_mask = SRQI | ATN | CIC | REM | LACS | TACS | LOK; + + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + unsigned int need_monitoring_bits = ni_usb_ibsta_monitor_mask; + unsigned long flags; + + board->status &= ~clear_mask; + board->status &= ~ni_usb_ibsta_mask; + board->status |= ni_usb_ibsta & ni_usb_ibsta_mask; + //FIXME should generate events on DTAS and DCAS + + spin_lock_irqsave(&board->spinlock, flags); +/* remove set status bits from monitored set why ?***/ + ni_priv->monitored_ibsta_bits &= ~ni_usb_ibsta; + need_monitoring_bits &= ~ni_priv->monitored_ibsta_bits; /* mm - monitored set */ + spin_unlock_irqrestore(&board->spinlock, flags); + dev_dbg(&usb_dev->dev, "%s: need_monitoring_bits=0x%x\n", __func__, need_monitoring_bits); + + if (need_monitoring_bits & ~ni_usb_ibsta) + ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); + else if (need_monitoring_bits & ni_usb_ibsta) + wake_up_interruptible(&board->wait); + + dev_dbg(&usb_dev->dev, "%s: ni_usb_ibsta=0x%x\n", __func__, ni_usb_ibsta); +} + +static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status) +{ + u16 count; + + status->id = buffer[0]; + status->ibsta = (buffer[1] << 8) | buffer[2]; + status->error_code = buffer[3]; + count = buffer[4] | (buffer[5] << 8); + count = ~count; + count++; + status->count = count; + return 8; +}; + +static void ni_usb_dump_raw_block(const u8 *raw_data, int length) +{ + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true); +} + +static int ni_usb_parse_register_read_block(const u8 *raw_data, unsigned int *results, + int num_results) +{ + int i = 0; + int j; + int unexpected = 0; + static const int results_per_chunk = 3; + + for (j = 0; j < num_results;) { + int k; + + if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_START_ID) { + pr_err("%s: parse error: wrong start id\n", __func__); + unexpected = 1; + } + for (k = 0; k < results_per_chunk && j < num_results; ++k) + results[j++] = raw_data[i++]; + } + while (i % 4) + i++; + if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_END_ID) { + pr_err("%s: parse error: wrong end id\n", __func__); + unexpected = 1; + } + if (raw_data[i++] % results_per_chunk != num_results % results_per_chunk) { + pr_err("%s: parse error: wrong count=%i for NIUSB_REGISTER_READ_DATA_END\n", + __func__, (int)raw_data[i - 1]); + unexpected = 1; + } + while (i % 4) { + if (raw_data[i++] != 0) { + pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", + __func__, i - 1, (int)raw_data[i - 1]); + unexpected = 1; + } + } + if (unexpected) + ni_usb_dump_raw_block(raw_data, i); + return i; +} + +static int ni_usb_parse_termination_block(const u8 *buffer) +{ + int i = 0; + + if (buffer[i++] != NIUSB_TERM_ID || + buffer[i++] != 0x0 || + buffer[i++] != 0x0 || + buffer[i++] != 0x0) { + pr_err("%s: received unexpected termination block\n", __func__); + pr_err(" expected: 0x%x 0x%x 0x%x 0x%x\n", + NIUSB_TERM_ID, 0x0, 0x0, 0x0); + pr_err(" received: 0x%x 0x%x 0x%x 0x%x\n", + buffer[i - 4], buffer[i - 3], buffer[i - 2], buffer[i - 1]); + } + return i; +}; + +static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_block *status, + u8 *parsed_data, int parsed_data_length, + int *actual_bytes_read) +{ + static const int ibrd_data_block_length = 0xf; + static const int ibrd_extended_data_block_length = 0x1e; + int data_block_length = 0; + int i = 0; + int j = 0; + int k; + unsigned int adr1_bits; + int num_data_blocks = 0; + struct ni_usb_status_block register_write_status; + int unexpected = 0; + + while (raw_data[i] == NIUSB_IBRD_DATA_ID || raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) { + if (raw_data[i] == NIUSB_IBRD_DATA_ID) { + data_block_length = ibrd_data_block_length; + } else if (raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) { + data_block_length = ibrd_extended_data_block_length; + if (raw_data[++i] != 0) { + pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", + __func__, i, (int)raw_data[i]); + unexpected = 1; + } + } else { + pr_err("%s: logic bug!\n", __func__); + return -EINVAL; + } + ++i; + for (k = 0; k < data_block_length; k++) { + if (j < parsed_data_length) + parsed_data[j++] = raw_data[i++]; + else + ++i; + } + ++num_data_blocks; + } + i += ni_usb_parse_status_block(&raw_data[i], status); + if (status->id != NIUSB_IBRD_STATUS_ID) { + pr_err("%s: bug: status->id=%i, != ibrd_status_id\n", __func__, status->id); + return -EIO; + } + adr1_bits = raw_data[i++]; + if (num_data_blocks) { + *actual_bytes_read = (num_data_blocks - 1) * data_block_length + raw_data[i++]; + } else { + ++i; + *actual_bytes_read = 0; + } + if (*actual_bytes_read > j) + pr_err("%s: bug: discarded data. actual_bytes_read=%i, j=%i\n", + __func__, *actual_bytes_read, j); + for (k = 0; k < 2; k++) + if (raw_data[i++] != 0) { + pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", + __func__, i - 1, (int)raw_data[i - 1]); + unexpected = 1; + } + i += ni_usb_parse_status_block(&raw_data[i], ®ister_write_status); + if (register_write_status.id != NIUSB_REG_WRITE_ID) { + pr_err("%s: unexpected data: register write status id=0x%x, expected 0x%x\n", + __func__, register_write_status.id, NIUSB_REG_WRITE_ID); + unexpected = 1; + } + if (raw_data[i++] != 2) { + pr_err("%s: unexpected data: register write count=%i, expected 2\n", + __func__, (int)raw_data[i - 1]); + unexpected = 1; + } + for (k = 0; k < 3; k++) + if (raw_data[i++] != 0) { + pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n", + __func__, i - 1, (int)raw_data[i - 1]); + unexpected = 1; + } + i += ni_usb_parse_termination_block(&raw_data[i]); + if (unexpected) + ni_usb_dump_raw_block(raw_data, i); + return i; +} + +static int ni_usb_parse_reg_write_status_block(const u8 *raw_data, + struct ni_usb_status_block *status, + int *writes_completed) +{ + int i = 0; + + i += ni_usb_parse_status_block(raw_data, status); + *writes_completed = raw_data[i++]; + while (i % 4) + i++; + return i; +} + +static int ni_usb_write_registers(struct ni_usb_priv *ni_priv, + const struct ni_usb_register *writes, int num_writes, + unsigned int *ibsta) +{ + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int retval; + u8 *out_data, *in_data; + int out_data_length; + static const int in_data_length = 0x20; + int bytes_written = 0, bytes_read = 0; + int i = 0; + int j; + struct ni_usb_status_block status; + static const int bytes_per_write = 3; + int reg_writes_completed; + + out_data_length = num_writes * bytes_per_write + 0x10; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) { + dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + return -ENOMEM; + } + i += ni_usb_bulk_register_write_header(&out_data[i], num_writes); + for (j = 0; j < num_writes; j++) + i += ni_usb_bulk_register_write(&out_data[i], writes[j]); + while (i % 4) + out_data[i++] = 0x00; + i += ni_usb_bulk_termination(&out_data[i]); + if (i > out_data_length) + dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__); + + mutex_lock(&ni_priv->addressed_transfer_lock); + + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return retval; + } + + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + return -ENOMEM; + } + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); + if (retval || bytes_read != 16) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + ni_usb_dump_raw_block(in_data, bytes_read); + kfree(in_data); + return retval; + } + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + ni_usb_parse_reg_write_status_block(in_data, &status, ®_writes_completed); + //FIXME parse extra 09 status bits and termination + kfree(in_data); + if (status.id != NIUSB_REG_WRITE_ID) { + dev_err(&usb_dev->dev, "%s: parse error, id=0x%x != NIUSB_REG_WRITE_ID\n", + __func__, status.id); + return -EIO; + } + if (status.error_code) { + dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x\n", + __func__, status.error_code); + return -EIO; + } + if (reg_writes_completed != num_writes) { + dev_err(&usb_dev->dev, "%s: reg_writes_completed=%i, num_writes=%i\n", + __func__, reg_writes_completed, num_writes); + return -EIO; + } + if (ibsta) + *ibsta = status.ibsta; + return 0; +} + +// interface functions +static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read) +{ + int retval, parse_retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + static const int out_data_length = 0x20; + int in_data_length; + int usb_bytes_written = 0, usb_bytes_read = 0; + int i = 0; + int complement_count; + int actual_length; + struct ni_usb_status_block status; + static const int max_read_length = 0xffff; + struct ni_usb_register reg; + + *bytes_read = 0; + if (length > max_read_length) { + length = max_read_length; + dev_err(&usb_dev->dev, "%s: read length too long\n", __func__); + } + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + out_data[i++] = 0x0a; + out_data[i++] = ni_priv->eos_mode >> 8; + out_data[i++] = ni_priv->eos_char; + out_data[i++] = ni_usb_timeout_code(board->usec_timeout); + complement_count = length - 1; + complement_count = ~complement_count; + out_data[i++] = complement_count & 0xff; + out_data[i++] = (complement_count >> 8) & 0xff; + out_data[i++] = 0x0; + out_data[i++] = 0x0; + i += ni_usb_bulk_register_write_header(&out_data[i], 2); + reg.device = NIUSB_SUBDEV_TNT4882; + reg.address = nec7210_to_tnt4882_offset(AUXMR); + reg.value = AUX_HLDI; + i += ni_usb_bulk_register_write(&out_data[i], reg); + reg.value = AUX_CLEAR_END; + i += ni_usb_bulk_register_write(&out_data[i], reg); + while (i % 4) // pad with zeros to 4-byte boundary + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + + mutex_lock(&ni_priv->addressed_transfer_lock); + + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written, 1000); + kfree(out_data); + if (retval || usb_bytes_written != i) { + if (retval == 0) + retval = -EIO; + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", + __func__, retval, usb_bytes_written, i); + mutex_unlock(&ni_priv->addressed_transfer_lock); + return retval; + } + + in_data_length = (length / 30 + 1) * 0x20 + 0x20; + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + return -ENOMEM; + } + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read, + ni_usb_timeout_msecs(board->usec_timeout), 1); + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + if (retval == -ERESTARTSYS) { + } else if (retval) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n", + __func__, retval, usb_bytes_read); + kfree(in_data); + return retval; + } + parse_retval = parse_board_ibrd_readback(in_data, &status, buffer, length, &actual_length); + if (parse_retval != usb_bytes_read) { + if (parse_retval >= 0) + parse_retval = -EIO; + dev_err(&usb_dev->dev, "%s: retval=%i usb_bytes_read=%i\n", + __func__, parse_retval, usb_bytes_read); + kfree(in_data); + return parse_retval; + } + if (actual_length != length - status.count) { + dev_err(&usb_dev->dev, "%s: actual_length=%i expected=%li\n", + __func__, actual_length, (long)(length - status.count)); + ni_usb_dump_raw_block(in_data, usb_bytes_read); + } + kfree(in_data); + switch (status.error_code) { + case NIUSB_NO_ERROR: + retval = 0; + break; + case NIUSB_ABORTED_ERROR: + /* this is expected if ni_usb_receive_bulk_msg got + * interrupted by a signal and returned -ERESTARTSYS + */ + break; + case NIUSB_ATN_STATE_ERROR: + retval = -EIO; + dev_err(&usb_dev->dev, "%s: read when ATN set\n", __func__); + break; + case NIUSB_ADDRESSING_ERROR: + retval = -EIO; + break; + case NIUSB_TIMEOUT_ERROR: + retval = -ETIMEDOUT; + break; + case NIUSB_EOSMODE_ERROR: + dev_err(&usb_dev->dev, "%s: driver bug, we should have been able to avoid NIUSB_EOSMODE_ERROR.\n", + __func__); + retval = -EINVAL; + break; + default: + dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code); + retval = -EIO; + break; + } + ni_usb_soft_update_status(board, status.ibsta, 0); + if (status.ibsta & END) + *end = 1; + else + *end = 0; + *bytes_read = actual_length; + return retval; +} + +static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + int out_data_length; + static const int in_data_length = 0x10; + int usb_bytes_written = 0, usb_bytes_read = 0; + int i = 0, j; + int complement_count; + struct ni_usb_status_block status; + static const int max_write_length = 0xffff; + + *bytes_written = 0; + if (length > max_write_length) { + length = max_write_length; + send_eoi = 0; + dev_err(&usb_dev->dev, "%s: write length too long\n", __func__); + } + out_data_length = length + 0x10; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + out_data[i++] = 0x0d; + complement_count = length - 1; + complement_count = ~complement_count; + out_data[i++] = complement_count & 0xff; + out_data[i++] = (complement_count >> 8) & 0xff; + out_data[i++] = ni_usb_timeout_code(board->usec_timeout); + out_data[i++] = 0x0; + out_data[i++] = 0x0; + if (send_eoi) + out_data[i++] = 0x8; + else + out_data[i++] = 0x0; + out_data[i++] = 0x0; + for (j = 0; j < length; j++) + out_data[i++] = buffer[j]; + while (i % 4) // pad with zeros to 4-byte boundary + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + + mutex_lock(&ni_priv->addressed_transfer_lock); + + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written, + ni_usb_timeout_msecs(board->usec_timeout)); + kfree(out_data); + if (retval || usb_bytes_written != i) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", + __func__, retval, usb_bytes_written, i); + return retval; + } + + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) + return -ENOMEM; + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read, + ni_usb_timeout_msecs(board->usec_timeout), 1); + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + if ((retval && retval != -ERESTARTSYS) || usb_bytes_read != 12) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n", + __func__, retval, usb_bytes_read); + kfree(in_data); + return retval; + } + ni_usb_parse_status_block(in_data, &status); + kfree(in_data); + switch (status.error_code) { + case NIUSB_NO_ERROR: + retval = 0; + break; + case NIUSB_ABORTED_ERROR: + /* this is expected if ni_usb_receive_bulk_msg got + * interrupted by a signal and returned -ERESTARTSYS + */ + break; + case NIUSB_ADDRESSING_ERROR: + dev_err(&usb_dev->dev, "%s: Addressing error retval %d error code=%i\n", + __func__, retval, status.error_code); + retval = -ENXIO; + break; + case NIUSB_NO_LISTENER_ERROR: + retval = -ECOMM; + break; + case NIUSB_TIMEOUT_ERROR: + retval = -ETIMEDOUT; + break; + default: + dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", + __func__, status.error_code); + retval = -EPIPE; + break; + } + ni_usb_soft_update_status(board, status.ibsta, 0); + *bytes_written = length - status.count; + return retval; +} + +static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *command_bytes_written) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + int out_data_length; + static const int in_data_length = 0x10; + int bytes_written = 0, bytes_read = 0; + int i = 0, j; + unsigned int complement_count; + struct ni_usb_status_block status; + // usb-b gives error 4 if you try to send more than 16 command bytes at once + static const int max_command_length = 0x10; + + *command_bytes_written = 0; + if (length > max_command_length) + length = max_command_length; + out_data_length = length + 0x10; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + out_data[i++] = 0x0c; + complement_count = length - 1; + complement_count = ~complement_count; + out_data[i++] = complement_count; + out_data[i++] = 0x0; + out_data[i++] = ni_usb_timeout_code(board->usec_timeout); + for (j = 0; j < length; j++) + out_data[i++] = buffer[j]; + while (i % 4) // pad with zeros to 4-byte boundary + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + + mutex_lock(&ni_priv->addressed_transfer_lock); + + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, + ni_usb_timeout_msecs(board->usec_timeout)); + kfree(out_data); + if (retval || bytes_written != i) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return retval; + } + + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + return -ENOMEM; + } + + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, + ni_usb_timeout_msecs(board->usec_timeout), 1); + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + kfree(in_data); + return retval; + } + ni_usb_parse_status_block(in_data, &status); + kfree(in_data); + *command_bytes_written = length - status.count; + switch (status.error_code) { + case NIUSB_NO_ERROR: + break; + case NIUSB_ABORTED_ERROR: + /* this is expected if ni_usb_receive_bulk_msg got + * interrupted by a signal and returned -ERESTARTSYS + */ + break; + case NIUSB_NO_BUS_ERROR: + return -ENOTCONN; + case NIUSB_EOSMODE_ERROR: + dev_err(&usb_dev->dev, "%s: got eosmode error. Driver bug?\n", __func__); + return -EIO; + case NIUSB_TIMEOUT_ERROR: + return -ETIMEDOUT; + default: + dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code); + return -EIO; + } + ni_usb_soft_update_status(board, status.ibsta, 0); + return 0; +} + +static int ni_usb_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written) +{ + size_t count; + int retval; + + *bytes_written = 0; + while (*bytes_written < length) { + retval = ni_usb_command_chunk(board, buffer + *bytes_written, + length - *bytes_written, &count); + *bytes_written += count; + if (retval < 0) + return retval; + } + return 0; +} + +static int ni_usb_take_control(gpib_board_t *board, int synchronous) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + static const int out_data_length = 0x10; + static const int in_data_length = 0x10; + int bytes_written = 0, bytes_read = 0; + int i = 0; + struct ni_usb_status_block status; + + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + out_data[i++] = NIUSB_IBCAC_ID; + if (synchronous) + out_data[i++] = 0x1; + else + out_data[i++] = 0x0; + out_data[i++] = 0x0; + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + + mutex_lock(&ni_priv->addressed_transfer_lock); + + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval || bytes_written != i) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return retval; + } + + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + return -ENOMEM; + } + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 1); + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) { + if (retval == 0) + retval = -EIO; + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + kfree(in_data); + return retval; + } + ni_usb_parse_status_block(in_data, &status); + kfree(in_data); + ni_usb_soft_update_status(board, status.ibsta, 0); + return retval; +} + +static int ni_usb_go_to_standby(gpib_board_t *board) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + static const int out_data_length = 0x10; + static const int in_data_length = 0x20; + int bytes_written = 0, bytes_read = 0; + int i = 0; + struct ni_usb_status_block status; + + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + + out_data[i++] = NIUSB_IBGTS_ID; + out_data[i++] = 0x0; + out_data[i++] = 0x0; + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + + mutex_lock(&ni_priv->addressed_transfer_lock); + + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval || bytes_written != i) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return retval; + } + + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + return -ENOMEM; + } + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + if (retval || bytes_read != 12) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + kfree(in_data); + return retval; + } + ni_usb_parse_status_block(in_data, &status); + kfree(in_data); + if (status.id != NIUSB_IBGTS_ID) + dev_err(&usb_dev->dev, "%s: bug: status.id 0x%x != INUSB_IBGTS_ID\n", + __func__, status.id); + ni_usb_soft_update_status(board, status.ibsta, 0); + return 0; +} + +static void ni_usb_request_system_control(gpib_board_t *board, int request_control) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[4]; + unsigned int ibsta; + + if (request_control) { + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = CMDR; + writes[i].value = SETSC; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CIFC; + i++; + } else { + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CREN; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CIFC; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_DSC; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = CMDR; + writes[i].value = CLRSC; + i++; + } + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return; // retval; + } + if (!request_control) + ni_priv->ren_state = 0; + ni_usb_soft_update_status(board, ibsta, 0); + return; // 0; +} + +//FIXME maybe the interface should have a "pulse interface clear" function that can return an error? +static void ni_usb_interface_clear(gpib_board_t *board, int assert) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + static const int out_data_length = 0x10; + static const int in_data_length = 0x10; + int bytes_written = 0, bytes_read = 0; + int i = 0; + struct ni_usb_status_block status; + + // FIXME: we are going to pulse when assert is true, and ignore otherwise + if (assert == 0) + return; + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) { + dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + return; + } + out_data[i++] = NIUSB_IBSIC_ID; + out_data[i++] = 0x0; + out_data[i++] = 0x0; + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval || bytes_written != i) { + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return; + } + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) + return; + + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); + if (retval || bytes_read != 12) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + kfree(in_data); + return; + } + ni_usb_parse_status_block(in_data, &status); + kfree(in_data); + ni_usb_soft_update_status(board, status.ibsta, 0); +} + +static void ni_usb_remote_enable(gpib_board_t *board, int enable) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct ni_usb_register reg; + unsigned int ibsta; + + reg.device = NIUSB_SUBDEV_TNT4882; + reg.address = nec7210_to_tnt4882_offset(AUXMR); + if (enable) + reg.value = AUX_SREN; + else + reg.value = AUX_CREN; + retval = ni_usb_write_registers(ni_priv, ®, 1, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return; //retval; + } + ni_priv->ren_state = enable; + ni_usb_soft_update_status(board, ibsta, 0); + return;// 0; +} + +static int ni_usb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct ni_usb_priv *ni_priv = board->private_data; + + ni_priv->eos_char = eos_byte; + ni_priv->eos_mode |= REOS; + if (compare_8_bits) + ni_priv->eos_mode |= BIN; + else + ni_priv->eos_mode &= ~BIN; + return 0; +} + +static void ni_usb_disable_eos(gpib_board_t *board) +{ + struct ni_usb_priv *ni_priv = board->private_data; + /* adapter gets unhappy if you don't zero all the bits + * for the eos mode and eos char (returns error 4 on reads). + */ + ni_priv->eos_mode = 0; + ni_priv->eos_char = 0; +} + +static unsigned int ni_usb_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + static const int buffer_length = 8; + u8 *buffer; + struct ni_usb_status_block status; + + //printk("%s: receive control pipe is %i\n", __func__, pipe); + buffer = kmalloc(buffer_length, GFP_KERNEL); + if (!buffer) + return board->status; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x200, 0x0, buffer, buffer_length, 1000); + if (retval != buffer_length) { + dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval); + kfree(buffer); + return board->status; + } + ni_usb_parse_status_block(buffer, &status); + kfree(buffer); + ni_usb_soft_update_status(board, status.ibsta, clear_mask); + return board->status; +} + +// tells ni-usb to immediately stop an ongoing i/o operation +static void ni_usb_stop(struct ni_usb_priv *ni_priv) +{ + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int retval; + static const int buffer_length = 8; + u8 *buffer; + struct ni_usb_status_block status; + + //printk("%s: receive control pipe is %i\n", __func__, pipe); + buffer = kmalloc(buffer_length, GFP_KERNEL); + if (!buffer) + return; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_STOP_REQUEST, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0, 0x0, buffer, buffer_length, 1000); + if (retval != buffer_length) { + dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval); + kfree(buffer); + return; + } + ni_usb_parse_status_block(buffer, &status); + kfree(buffer); +} + +static int ni_usb_primary_address(gpib_board_t *board, unsigned int address) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[2]; + unsigned int ibsta; + + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(ADR); + writes[i].value = address; + i++; + writes[i].device = NIUSB_SUBDEV_UNKNOWN2; + writes[i].address = 0x0; + writes[i].value = address; + i++; + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return 0; +} + +static int ni_usb_write_sad(struct ni_usb_register *writes, int address, int enable) +{ + unsigned int adr_bits, admr_bits; + int i = 0; + + adr_bits = HR_ARS; + admr_bits = HR_TRM0 | HR_TRM1; + if (enable) { + adr_bits |= address; + admr_bits |= HR_ADM1; + } else { + adr_bits |= HR_DT | HR_DL; + admr_bits |= HR_ADM0; + } + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(ADR); + writes[i].value = adr_bits; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(ADMR); + writes[i].value = admr_bits; + i++; + writes[i].device = NIUSB_SUBDEV_UNKNOWN2; + writes[i].address = 0x1; + writes[i].value = enable ? MSA(address) : 0x0; + i++; + return i; +} + +static int ni_usb_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[3]; + unsigned int ibsta; + + i += ni_usb_write_sad(writes, address, enable); + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return 0; +} + +static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + static const int out_data_length = 0x10; + static const int in_data_length = 0x20; + int bytes_written = 0, bytes_read = 0; + int i = 0; + int j = 0; + struct ni_usb_status_block status; + + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + + out_data[i++] = NIUSB_IBRPP_ID; + out_data[i++] = 0xf0; //FIXME: this should be the parallel poll timeout code + out_data[i++] = 0x0; + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + /*FIXME: 1000 should use parallel poll timeout (not supported yet)*/ + retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); + + kfree(out_data); + if (retval || bytes_written != i) { + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return retval; + } + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) + return -ENOMEM; + + /*FIXME: should use parallel poll timeout (not supported yet)*/ + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, + &bytes_read, 1000, 1); + + if (retval && retval != -ERESTARTSYS) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + kfree(in_data); + return retval; + } + j += ni_usb_parse_status_block(in_data, &status); + *result = in_data[j++]; + kfree(in_data); + ni_usb_soft_update_status(board, status.ibsta, 0); + return retval; +} + +static void ni_usb_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[1]; + unsigned int ibsta; + + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = PPR | config; + i++; + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return;// retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return;// 0; +} + +static void ni_usb_parallel_poll_response(gpib_board_t *board, int ist) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[1]; + unsigned int ibsta; + + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + if (ist) + writes[i].value = AUX_SPPF; + else + writes[i].value = AUX_CPPF; + i++; + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return;// retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return;// 0; +} + +static void ni_usb_serial_poll_response(gpib_board_t *board, u8 status) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[1]; + unsigned int ibsta; + + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(SPMR); + writes[i].value = status; + i++; + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return;// retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return;// 0; +} + +static uint8_t ni_usb_serial_poll_status(gpib_board_t *board) +{ + return 0; +} + +static void ni_usb_return_to_local(gpib_board_t *board) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int i = 0; + struct ni_usb_register writes[1]; + unsigned int ibsta; + + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_RTL; + i++; + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return;// retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return;// 0; +} + +static int ni_usb_line_status(const gpib_board_t *board) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + u8 *out_data, *in_data; + static const int out_data_length = 0x20; + static const int in_data_length = 0x20; + int bytes_written = 0, bytes_read = 0; + int i = 0; + unsigned int bsr_bits; + int line_status = ValidALL; + // NI windows driver reads 0xd(HSSEL), 0xc (ARD0), 0x1f (BSR) + + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) + return -ENOMEM; + + /* line status gets called during ibwait */ + retval = mutex_trylock(&ni_priv->addressed_transfer_lock); + + if (retval == 0) { + kfree(out_data); + return -EBUSY; + } + i += ni_usb_bulk_register_read_header(&out_data[i], 1); + i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_TNT4882, BSR); + while (i % 4) + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); + kfree(out_data); + if (retval || bytes_written != i) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + if (retval != -EAGAIN) + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n", + __func__, retval, bytes_written, i); + return retval; + } + + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) { + mutex_unlock(&ni_priv->addressed_transfer_lock); + dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__); + return -ENOMEM; + } + retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, in_data, in_data_length, + &bytes_read, 1000, 0); + + mutex_unlock(&ni_priv->addressed_transfer_lock); + + if (retval) { + if (retval != -EAGAIN) + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + kfree(in_data); + return retval; + } + + ni_usb_parse_register_read_block(in_data, &bsr_bits, 1); + kfree(in_data); + if (bsr_bits & BCSR_REN_BIT) + line_status |= BusREN; + if (bsr_bits & BCSR_IFC_BIT) + line_status |= BusIFC; + if (bsr_bits & BCSR_SRQ_BIT) + line_status |= BusSRQ; + if (bsr_bits & BCSR_EOI_BIT) + line_status |= BusEOI; + if (bsr_bits & BCSR_NRFD_BIT) + line_status |= BusNRFD; + if (bsr_bits & BCSR_NDAC_BIT) + line_status |= BusNDAC; + if (bsr_bits & BCSR_DAV_BIT) + line_status |= BusDAV; + if (bsr_bits & BCSR_ATN_BIT) + line_status |= BusATN; + return line_status; +} + +static int ni_usb_setup_t1_delay(struct ni_usb_register *reg, unsigned int nano_sec, + unsigned int *actual_ns) +{ + int i = 0; + + *actual_ns = 2000; + + reg[i].device = NIUSB_SUBDEV_TNT4882; + reg[i].address = nec7210_to_tnt4882_offset(AUXMR); + if (nano_sec <= 1100) { + reg[i].value = AUXRI | USTD | SISB; + *actual_ns = 1100; + } else { + reg[i].value = AUXRI | SISB; + } + i++; + reg[i].device = NIUSB_SUBDEV_TNT4882; + reg[i].address = nec7210_to_tnt4882_offset(AUXMR); + if (nano_sec <= 500) { + reg[i].value = AUXRB | HR_TRI; + *actual_ns = 500; + } else { + reg[i].value = AUXRB; + } + i++; + reg[i].device = NIUSB_SUBDEV_TNT4882; + reg[i].address = KEYREG; + if (nano_sec <= 350) { + reg[i].value = MSTD; + *actual_ns = 350; + } else { + reg[i].value = 0x0; + } + i++; + return i; +} + +static unsigned int ni_usb_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct ni_usb_register writes[3]; + unsigned int ibsta; + unsigned int actual_ns; + int i; + + i = ni_usb_setup_t1_delay(writes, nano_sec, &actual_ns); + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return -1; //FIXME should change return type to int for error reporting + } + board->t1_nano_sec = actual_ns; + ni_usb_soft_update_status(board, ibsta, 0); + return actual_ns; +} + +static int ni_usb_allocate_private(gpib_board_t *board) +{ + struct ni_usb_priv *ni_priv; + + board->private_data = kmalloc(sizeof(struct ni_usb_priv), GFP_KERNEL); + if (!board->private_data) + return -ENOMEM; + ni_priv = board->private_data; + memset(ni_priv, 0, sizeof(struct ni_usb_priv)); + mutex_init(&ni_priv->bulk_transfer_lock); + mutex_init(&ni_priv->control_transfer_lock); + mutex_init(&ni_priv->interrupt_transfer_lock); + mutex_init(&ni_priv->addressed_transfer_lock); + return 0; +} + +static void ni_usb_free_private(struct ni_usb_priv *ni_priv) +{ + usb_free_urb(ni_priv->interrupt_urb); + kfree(ni_priv); +} + +#define NUM_INIT_WRITES 26 +static int ni_usb_setup_init(gpib_board_t *board, struct ni_usb_register *writes) +{ + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + unsigned int mask, actual_ns; + int i = 0; + + writes[i].device = NIUSB_SUBDEV_UNKNOWN3; + writes[i].address = 0x10; + writes[i].value = 0x0; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = CMDR; + writes[i].value = SOFT_RESET; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + mask = AUXRA | HR_HLDA; + if (ni_priv->eos_mode & BIN) + mask |= HR_BIN; + writes[i].value = mask; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = AUXCR; + writes[i].value = mask; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = HSSEL; + writes[i].value = TNT_ONE_CHIP_BIT; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CR; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = IMR0; + writes[i].value = TNT_IMR0_ALWAYS_BITS; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(IMR1); + writes[i].value = 0x0; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(IMR2); + writes[i].value = 0x0; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = IMR3; + writes[i].value = 0x0; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_HLDI; + i++; + + i += ni_usb_setup_t1_delay(&writes[i], board->t1_nano_sec, &actual_ns); + + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUXRG | NTNL_BIT; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = CMDR; + if (board->master) + mask = SETSC; // set system controller + else + mask = CLRSC; // clear system controller + writes[i].value = mask; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CIFC; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(ADR); + writes[i].value = board->pad; + i++; + writes[i].device = NIUSB_SUBDEV_UNKNOWN2; + writes[i].address = 0x0; + writes[i].value = board->pad; + i++; + + i += ni_usb_write_sad(&writes[i], board->sad, board->sad >= 0); + + writes[i].device = NIUSB_SUBDEV_UNKNOWN2; + writes[i].address = 0x2; // could this be a timeout ? + writes[i].value = 0xfd; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = 0xf; // undocumented address + writes[i].value = 0x11; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_PON; + i++; + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CPPF; + i++; + if (i > NUM_INIT_WRITES) { + dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i); + return 0; + } + return i; +} + +static int ni_usb_init(gpib_board_t *board) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + struct ni_usb_register *writes; + unsigned int ibsta; + int writes_len; + + writes = kmalloc_array(NUM_INIT_WRITES, sizeof(*writes), GFP_KERNEL); + if (!writes) + return -ENOMEM; + + writes_len = ni_usb_setup_init(board, writes); + if (writes_len) + retval = ni_usb_write_registers(ni_priv, writes, writes_len, &ibsta); + else + return -EFAULT; + kfree(writes); + if (retval) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return retval; + } + ni_usb_soft_update_status(board, ibsta, 0); + return 0; +} + +static void ni_usb_interrupt_complete(struct urb *urb) +{ + gpib_board_t *board = urb->context; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int retval; + struct ni_usb_status_block status; + unsigned long flags; + +// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__, +// urb->status, urb->error_count, urb->actual_length); + + switch (urb->status) { + /* success */ + case 0: + break; + /* unlinked, don't resubmit */ + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* other error, resubmit */ + retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC); + if (retval) + dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); + return; + } + + ni_usb_parse_status_block(urb->transfer_buffer, &status); +// printk("debug: ibsta=0x%x\n", status.ibsta); + + spin_lock_irqsave(&board->spinlock, flags); + ni_priv->monitored_ibsta_bits &= ~status.ibsta; +// printk("debug: monitored_ibsta_bits=0x%x\n", ni_priv->monitored_ibsta_bits); + spin_unlock_irqrestore(&board->spinlock, flags); + + wake_up_interruptible(&board->wait); + + retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC); + if (retval) + dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__); +} + +static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits) +{ + int retval; + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + static const int buffer_length = 8; + u8 *buffer; + struct ni_usb_status_block status; + unsigned long flags; + //printk("%s: receive control pipe is %i\n", __func__, pipe); + buffer = kmalloc(buffer_length, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + spin_lock_irqsave(&board->spinlock, flags); + ni_priv->monitored_ibsta_bits = ni_usb_ibsta_monitor_mask & monitored_bits; +// dev_err(&usb_dev->dev, "debug: %s: monitored_ibsta_bits=0x%x\n", +// __func__, ni_priv->monitored_ibsta_bits); + spin_unlock_irqrestore(&board->spinlock, flags); + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x300, ni_usb_ibsta_monitor_mask & monitored_bits, + buffer, buffer_length, 1000); + if (retval != buffer_length) { + dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval); + kfree(buffer); + return -1; + } + ni_usb_parse_status_block(buffer, &status); + kfree(buffer); + return 0; +} + +static int ni_usb_setup_urbs(gpib_board_t *board) +{ + struct ni_usb_priv *ni_priv = board->private_data; + struct usb_device *usb_dev; + int int_pipe; + int retval; + + if (ni_priv->interrupt_in_endpoint < 0) + return 0; + + mutex_lock(&ni_priv->interrupt_transfer_lock); + if (!ni_priv->bus_interface) { + mutex_unlock(&ni_priv->interrupt_transfer_lock); + return -ENODEV; + } + ni_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ni_priv->interrupt_urb) { + mutex_unlock(&ni_priv->interrupt_transfer_lock); + return -ENOMEM; + } + usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int_pipe = usb_rcvintpipe(usb_dev, ni_priv->interrupt_in_endpoint); + usb_fill_int_urb(ni_priv->interrupt_urb, usb_dev, int_pipe, ni_priv->interrupt_buffer, + sizeof(ni_priv->interrupt_buffer), &ni_usb_interrupt_complete, board, 1); + retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL); + mutex_unlock(&ni_priv->interrupt_transfer_lock); + if (retval) { + dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n", + __func__, retval); + return retval; + } + return 0; +} + +static void ni_usb_cleanup_urbs(struct ni_usb_priv *ni_priv) +{ + if (ni_priv && ni_priv->bus_interface) { + if (ni_priv->interrupt_urb) + usb_kill_urb(ni_priv->interrupt_urb); + if (ni_priv->bulk_urb) + usb_kill_urb(ni_priv->bulk_urb); + } +} + +static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv) +{ + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int retval; + u8 *out_data; + u8 *in_data; + static const int out_data_length = 0x20; + static const int in_data_length = 0x20; + int bytes_written = 0, bytes_read = 0; + int i = 0; + static const int num_reads = 4; + unsigned int results[4]; + int j; + unsigned int serial_number; + +// printk("%s: %s\n", __func__); + in_data = kmalloc(in_data_length, GFP_KERNEL); + if (!in_data) + return -ENOMEM; + + out_data = kmalloc(out_data_length, GFP_KERNEL); + if (!out_data) { + kfree(in_data); + return -ENOMEM; + } + i += ni_usb_bulk_register_read_header(&out_data[i], num_reads); + i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_1_REG); + i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_2_REG); + i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_3_REG); + i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_4_REG); + while (i % 4) + out_data[i++] = 0x0; + i += ni_usb_bulk_termination(&out_data[i]); + retval = ni_usb_send_bulk_msg(ni_priv, out_data, out_data_length, &bytes_written, 1000); + if (retval) { + dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%li\n", + __func__, + retval, bytes_written, (long)out_data_length); + goto serial_out; + } + retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); + if (retval) { + dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n", + __func__, retval, bytes_read); + ni_usb_dump_raw_block(in_data, bytes_read); + goto serial_out; + } + if (ARRAY_SIZE(results) < num_reads) { + dev_err(&usb_dev->dev, "Setup bug\n"); + retval = -EINVAL; + goto serial_out; + } + ni_usb_parse_register_read_block(in_data, results, num_reads); + serial_number = 0; + for (j = 0; j < num_reads; ++j) + serial_number |= (results[j] & 0xff) << (8 * j); + dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number); + retval = 0; +serial_out: + kfree(in_data); + kfree(out_data); + return retval; +} + +static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) +{ + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + static const int buffer_size = 0x10; + static const int timeout = 50; + static const int msec_sleep_duration = 100; + int i; int retval; + int j; + int unexpected = 0; + unsigned int serial_number; + u8 *buffer; + + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_SERIAL_NUMBER_REQUEST, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0, 0x0, buffer, buffer_size, 1000); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", + __func__, NI_USB_SERIAL_NUMBER_REQUEST, retval); + goto ready_out; + } + j = 0; + if (buffer[j] != NI_USB_SERIAL_NUMBER_REQUEST) { + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n", + __func__, j, (int)buffer[j], NI_USB_SERIAL_NUMBER_REQUEST); + unexpected = 1; + } + if (unexpected) + ni_usb_dump_raw_block(buffer, retval); + // NI-USB-HS+ pads the serial with 0x0 to make 16 bytes + if (retval != 5 && retval != 16) { + dev_err(&usb_dev->dev, "%s: received unexpected number of bytes = %i, expected 5 or 16\n", + __func__, retval); + ni_usb_dump_raw_block(buffer, retval); + } + serial_number = 0; + serial_number |= buffer[++j]; + serial_number |= (buffer[++j] << 8); + serial_number |= (buffer[++j] << 16); + serial_number |= (buffer[++j] << 24); + dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number); + for (i = 0; i < timeout; ++i) { + int ready = 0; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_POLL_READY_REQUEST, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0, 0x0, buffer, buffer_size, 100); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", + __func__, NI_USB_POLL_READY_REQUEST, retval); + goto ready_out; + } + j = 0; + unexpected = 0; + if (buffer[j] != NI_USB_POLL_READY_REQUEST) { // [0] + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n", + __func__, j, (int)buffer[j], NI_USB_POLL_READY_REQUEST); + unexpected = 1; + } + ++j; + if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [1] HS+ sends 0x0 + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + if (buffer[++j] != 0x0) { // [2] + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n", + __func__, j, (int)buffer[j], 0x0); + unexpected = 1; + } + ++j; + // MC usb-488 (and sometimes NI-USB-HS?) sends 0x8 here; MC usb-488A sends 0x7 here + // NI-USB-HS+ sends 0x0 + if (buffer[j] != 0x1 && buffer[j] != 0x8 && buffer[j] != 0x7 && buffer[j] != 0x0) { + // [3] + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x1, 0x7 or 0x8\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + ++j; + // NI-USB-HS+ sends 0 here + if (buffer[j] != 0x30 && buffer[j] != 0x0) { // [4] + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x30\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + ++j; + // MC usb-488 (and sometimes NI-USB-HS?) and NI-USB-HS+ sends 0x0 here + if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [5] + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + if (buffer[++j] != 0x0) { // [6] + ready = 1; + // NI-USB-HS+ sends 0xf here + if (buffer[j] != 0x2 && buffer[j] != 0xe && buffer[j] != 0xf && + buffer[j] != 0x16) { + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf or 0x16\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + } + if (buffer[++j] != 0x0) { // [7] + ready = 1; + // MC usb-488 sends 0x5 here; MC usb-488A sends 0x6 here + if (buffer[j] != 0x3 && buffer[j] != 0x5 && buffer[j] != 0x6 && + buffer[j] != 0x8) { + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x3 or 0x5, 0x6 or 0x08\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + } + ++j; + if (buffer[j] != 0x0 && buffer[j] != 0x2) { // [8] MC usb-488 sends 0x2 here + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x2\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + ++j; + // MC usb-488A and NI-USB-HS sends 0x3 here; NI-USB-HS+ sends 0x30 here + if (buffer[j] != 0x0 && buffer[j] != 0x3 && buffer[j] != 0x30) { // [9] + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x3 or 0x30\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + if (buffer[++j] != 0x0) { + ready = 1; + if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e) { +// [10] MC usb-488 sends 0x7 here + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07 or 0x6e\n", + __func__, j, (int)buffer[j]); + unexpected = 1; + } + } + if (unexpected) + ni_usb_dump_raw_block(buffer, retval); + if (ready) + break; + retval = msleep_interruptible(msec_sleep_duration); + if (retval) { + dev_err(&usb_dev->dev, "ni_usb_gpib: msleep interrupted\n"); + retval = -ERESTARTSYS; + goto ready_out; + } + } + retval = 0; + +ready_out: + kfree(buffer); + dev_dbg(&usb_dev->dev, "%s: exit retval=%d\n", __func__, retval); + return retval; +} + +/* This does some extra init for HS+ models, as observed on Windows. One of the + * control requests causes the LED to stop blinking. + * I'm not sure what the other 2 requests do. None of these requests are actually required + * for the adapter to work, maybe they do some init for the analyzer interface + * (which we don't use). + */ +static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv) +{ + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int retval; + u8 *buffer; + static const int buffer_size = 16; + int transfer_size; + + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + do { + transfer_size = 16; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0x48_REQUEST, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x0, 0x0, buffer, transfer_size, 1000); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", + __func__, NI_USB_HS_PLUS_0x48_REQUEST, retval); + break; + } + // expected response data: 48 f3 30 00 00 00 00 00 00 00 00 00 00 00 00 00 + if (buffer[0] != NI_USB_HS_PLUS_0x48_REQUEST) + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n", + __func__, (int)buffer[0], NI_USB_HS_PLUS_0x48_REQUEST); + + transfer_size = 2; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_LED_REQUEST, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0x1, 0x0, buffer, transfer_size, 1000); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", + __func__, NI_USB_HS_PLUS_LED_REQUEST, retval); + break; + } + // expected response data: 4b 00 + if (buffer[0] != NI_USB_HS_PLUS_LED_REQUEST) + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n", + __func__, (int)buffer[0], NI_USB_HS_PLUS_LED_REQUEST); + + transfer_size = 9; + + retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0xf8_REQUEST, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0x0, 0x1, buffer, transfer_size, 1000); + if (retval < 0) { + dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n", + __func__, NI_USB_HS_PLUS_0xf8_REQUEST, retval); + break; + } + // expected response data: f8 01 00 00 00 01 00 00 00 + if (buffer[0] != NI_USB_HS_PLUS_0xf8_REQUEST) + dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n", + __func__, (int)buffer[0], NI_USB_HS_PLUS_0xf8_REQUEST); + + } while (0); + + // cleanup + kfree(buffer); + return retval; +} + +static inline int ni_usb_device_match(struct usb_interface *interface, + const gpib_board_config_t *config) +{ + if (gpib_match_device_path(&interface->dev, config->device_path) == 0) + return 0; + return 1; +} + +static int ni_usb_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + int retval; + int i; + struct ni_usb_priv *ni_priv; + int product_id; + struct usb_device *usb_dev; + + mutex_lock(&ni_usb_hotplug_lock); + retval = ni_usb_allocate_private(board); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + ni_priv = board->private_data; + for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { + if (ni_usb_driver_interfaces[i] && + !usb_get_intfdata(ni_usb_driver_interfaces[i]) && + ni_usb_device_match(ni_usb_driver_interfaces[i], config)) { + ni_priv->bus_interface = ni_usb_driver_interfaces[i]; + usb_set_intfdata(ni_usb_driver_interfaces[i], board); + usb_dev = interface_to_usbdev(ni_priv->bus_interface); + dev_info(&usb_dev->dev, + "bus %d dev num %d attached to gpib minor %d, NI usb interface %i\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + break; + } + } + if (i == MAX_NUM_NI_USB_INTERFACES) { + mutex_unlock(&ni_usb_hotplug_lock); + pr_err("No supported NI usb gpib adapters found, have you loaded its firmware?\n"); + return -ENODEV; + } + if (usb_reset_configuration(interface_to_usbdev(ni_priv->bus_interface))) + dev_err(&usb_dev->dev, "ni_usb_gpib: usb_reset_configuration() failed.\n"); + + product_id = le16_to_cpu(usb_dev->descriptor.idProduct); + ni_priv->product_id = product_id; + + timer_setup(&ni_priv->bulk_timer, ni_usb_timeout_handler, 0); + + switch (product_id) { + case USB_DEVICE_ID_NI_USB_B: + ni_priv->bulk_out_endpoint = NIUSB_B_BULK_OUT_ENDPOINT; + ni_priv->bulk_in_endpoint = NIUSB_B_BULK_IN_ENDPOINT; + ni_priv->interrupt_in_endpoint = NIUSB_B_INTERRUPT_IN_ENDPOINT; + ni_usb_b_read_serial_number(ni_priv); + break; + case USB_DEVICE_ID_NI_USB_HS: + case USB_DEVICE_ID_MC_USB_488: + case USB_DEVICE_ID_KUSB_488A: + ni_priv->bulk_out_endpoint = NIUSB_HS_BULK_OUT_ENDPOINT; + ni_priv->bulk_in_endpoint = NIUSB_HS_BULK_IN_ENDPOINT; + ni_priv->interrupt_in_endpoint = NIUSB_HS_INTERRUPT_IN_ENDPOINT; + retval = ni_usb_hs_wait_for_ready(ni_priv); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + break; + case USB_DEVICE_ID_NI_USB_HS_PLUS: + ni_priv->bulk_out_endpoint = NIUSB_HS_PLUS_BULK_OUT_ENDPOINT; + ni_priv->bulk_in_endpoint = NIUSB_HS_PLUS_BULK_IN_ENDPOINT; + ni_priv->interrupt_in_endpoint = NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT; + retval = ni_usb_hs_wait_for_ready(ni_priv); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + retval = ni_usb_hs_plus_extra_init(ni_priv); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + break; + default: + mutex_unlock(&ni_usb_hotplug_lock); + dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id %x\n", + product_id); + return -EINVAL; + } + + retval = ni_usb_setup_urbs(board); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + retval = ni_usb_set_interrupt_monitor(board, 0); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + + board->t1_nano_sec = 500; + + retval = ni_usb_init(board); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + + mutex_unlock(&ni_usb_hotplug_lock); + dev_info(&usb_dev->dev, "%s: attached\n", __func__); + return retval; +} + +static int ni_usb_shutdown_hardware(struct ni_usb_priv *ni_priv) +{ + struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); + int retval; + int i = 0; + struct ni_usb_register writes[2]; + static const int writes_length = ARRAY_SIZE(writes); + unsigned int ibsta; + +// printk("%s: %s\n", __func__); + writes[i].device = NIUSB_SUBDEV_TNT4882; + writes[i].address = nec7210_to_tnt4882_offset(AUXMR); + writes[i].value = AUX_CR; + i++; + writes[i].device = NIUSB_SUBDEV_UNKNOWN3; + writes[i].address = 0x10; + writes[i].value = 0x0; + i++; + if (i > writes_length) { + dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i); + return -EINVAL; + } + retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); + if (retval) { + dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval); + return retval; + } + return 0; +} + +static void ni_usb_detach(gpib_board_t *board) +{ + struct ni_usb_priv *ni_priv; + + mutex_lock(&ni_usb_hotplug_lock); +// under windows, software unplug does chip_reset nec7210 aux command, +// then writes 0x0 to address 0x10 of device 3 + ni_priv = board->private_data; + if (ni_priv) { + if (ni_priv->bus_interface) { + ni_usb_set_interrupt_monitor(board, 0); + ni_usb_shutdown_hardware(ni_priv); + usb_set_intfdata(ni_priv->bus_interface, NULL); + } + mutex_lock(&ni_priv->bulk_transfer_lock); + mutex_lock(&ni_priv->control_transfer_lock); + mutex_lock(&ni_priv->interrupt_transfer_lock); + ni_usb_cleanup_urbs(ni_priv); + ni_usb_free_private(ni_priv); + } + mutex_unlock(&ni_usb_hotplug_lock); +} + +gpib_interface_t ni_usb_gpib_interface = { +name: "ni_usb_b", +attach : ni_usb_attach, +detach : ni_usb_detach, +read : ni_usb_read, +write : ni_usb_write, +command : ni_usb_command, +take_control : ni_usb_take_control, +go_to_standby : ni_usb_go_to_standby, +request_system_control : ni_usb_request_system_control, +interface_clear : ni_usb_interface_clear, +remote_enable : ni_usb_remote_enable, +enable_eos : ni_usb_enable_eos, +disable_eos : ni_usb_disable_eos, +parallel_poll : ni_usb_parallel_poll, +parallel_poll_configure : ni_usb_parallel_poll_configure, +parallel_poll_response : ni_usb_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : ni_usb_line_status, +update_status : ni_usb_update_status, +primary_address : ni_usb_primary_address, +secondary_address : ni_usb_secondary_address, +serial_poll_response : ni_usb_serial_poll_response, +serial_poll_status : ni_usb_serial_poll_status, +t1_delay : ni_usb_t1_delay, +return_to_local : ni_usb_return_to_local, +skip_check_for_command_acceptors : 1 +}; + +// Table with the USB-devices: just now only testing IDs +static struct usb_device_id ni_usb_driver_device_table[] = { + {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_B)}, + {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS)}, + // gpib-usb-hs+ has a second interface for the analyzer, which we ignore + {USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS_PLUS, 0)}, + {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_KUSB_488A)}, + {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_MC_USB_488)}, + {} /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, ni_usb_driver_device_table); + +static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_device *usb_dev = interface_to_usbdev(interface); + int i; + char *path; + static const int path_length = 1024; + + mutex_lock(&ni_usb_hotplug_lock); + usb_get_dev(usb_dev); + for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { + if (!ni_usb_driver_interfaces[i]) { + ni_usb_driver_interfaces[i] = interface; + usb_set_intfdata(interface, NULL); + break; + } + } + if (i == MAX_NUM_NI_USB_INTERFACES) { + usb_put_dev(usb_dev); + mutex_unlock(&ni_usb_hotplug_lock); + dev_err(&usb_dev->dev, "%s: ni_usb_driver_interfaces[] full\n", __func__); + return -1; + } + path = kmalloc(path_length, GFP_KERNEL); + if (!path) { + usb_put_dev(usb_dev); + mutex_unlock(&ni_usb_hotplug_lock); + return -ENOMEM; + } + usb_make_path(usb_dev, path, path_length); + dev_info(&usb_dev->dev, "ni_usb_gpib: probe succeeded for path: %s\n", path); + kfree(path); + mutex_unlock(&ni_usb_hotplug_lock); + return 0; +} + +static void ni_usb_driver_disconnect(struct usb_interface *interface) +{ + struct usb_device *usb_dev = interface_to_usbdev(interface); + int i; + + mutex_lock(&ni_usb_hotplug_lock); + for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { + if (ni_usb_driver_interfaces[i] == interface) { + gpib_board_t *board = usb_get_intfdata(interface); + + if (board) { + struct ni_usb_priv *ni_priv = board->private_data; + + if (ni_priv) { + mutex_lock(&ni_priv->bulk_transfer_lock); + mutex_lock(&ni_priv->control_transfer_lock); + mutex_lock(&ni_priv->interrupt_transfer_lock); + ni_usb_cleanup_urbs(ni_priv); + ni_priv->bus_interface = NULL; + mutex_unlock(&ni_priv->interrupt_transfer_lock); + mutex_unlock(&ni_priv->control_transfer_lock); + mutex_unlock(&ni_priv->bulk_transfer_lock); + } + } + ni_usb_driver_interfaces[i] = NULL; + break; + } + } + if (i == MAX_NUM_NI_USB_INTERFACES) + dev_err(&usb_dev->dev, "%s: unable to find interface in ni_usb_driver_interfaces[]? bug?\n", + __func__); + usb_put_dev(usb_dev); + mutex_unlock(&ni_usb_hotplug_lock); +} + +static int ni_usb_driver_suspend(struct usb_interface *interface, pm_message_t message) +{ + struct usb_device *usb_dev = interface_to_usbdev(interface); + gpib_board_t *board; + int i, retval; + + mutex_lock(&ni_usb_hotplug_lock); + + for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { + if (ni_usb_driver_interfaces[i] == interface) { + board = usb_get_intfdata(interface); + if (board) + break; + } + } + if (i == MAX_NUM_NI_USB_INTERFACES) { + mutex_unlock(&ni_usb_hotplug_lock); + return 0; + } + + struct ni_usb_priv *ni_priv = board->private_data; + + if (ni_priv) { + ni_usb_set_interrupt_monitor(board, 0); + retval = ni_usb_shutdown_hardware(ni_priv); + if (retval) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + if (ni_priv->interrupt_urb) { + mutex_lock(&ni_priv->interrupt_transfer_lock); + ni_usb_cleanup_urbs(ni_priv); + mutex_unlock(&ni_priv->interrupt_transfer_lock); + } + dev_info(&usb_dev->dev, + "bus %d dev num %d gpib minor %d, ni usb interface %i suspended\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + } + + mutex_unlock(&ni_usb_hotplug_lock); + return 0; +} + +static int ni_usb_driver_resume(struct usb_interface *interface) +{ + struct usb_device *usb_dev = interface_to_usbdev(interface); + + gpib_board_t *board; + int i, retval; + + mutex_lock(&ni_usb_hotplug_lock); + + for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { + if (ni_usb_driver_interfaces[i] == interface) { + board = usb_get_intfdata(interface); + if (board) + break; + } + } + if (i == MAX_NUM_NI_USB_INTERFACES) { + mutex_unlock(&ni_usb_hotplug_lock); + return 0; + } + + struct ni_usb_priv *ni_priv = board->private_data; + + if (ni_priv) { + if (ni_priv->interrupt_urb) { + mutex_lock(&ni_priv->interrupt_transfer_lock); + retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL); + if (retval) { + dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n", + __func__, retval); + mutex_unlock(&ni_priv->interrupt_transfer_lock); + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + mutex_unlock(&ni_priv->interrupt_transfer_lock); + } else { + dev_err(&usb_dev->dev, "%s: bug! int urb not set up\n", __func__); + mutex_unlock(&ni_usb_hotplug_lock); + return -EINVAL; + } + + switch (ni_priv->product_id) { + case USB_DEVICE_ID_NI_USB_B: + ni_usb_b_read_serial_number(ni_priv); + break; + case USB_DEVICE_ID_NI_USB_HS: + case USB_DEVICE_ID_MC_USB_488: + case USB_DEVICE_ID_KUSB_488A: + retval = ni_usb_hs_wait_for_ready(ni_priv); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + break; + case USB_DEVICE_ID_NI_USB_HS_PLUS: + retval = ni_usb_hs_wait_for_ready(ni_priv); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + retval = ni_usb_hs_plus_extra_init(ni_priv); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + break; + default: + mutex_unlock(&ni_usb_hotplug_lock); + dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id\n"); + return -EINVAL; + } + + retval = ni_usb_set_interrupt_monitor(board, 0); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + + retval = ni_usb_init(board); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); + if (retval < 0) { + mutex_unlock(&ni_usb_hotplug_lock); + return retval; + } + if (board->master) + ni_usb_interface_clear(board, 1); // this is a pulsed action + if (ni_priv->ren_state) + ni_usb_remote_enable(board, 1); + + dev_info(&usb_dev->dev, + "bus %d dev num %d gpib minor %d, ni usb interface %i resumed\n", + usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); + } + + mutex_unlock(&ni_usb_hotplug_lock); + return 0; +} + +static struct usb_driver ni_usb_bus_driver = { + .name = "ni_usb_gpib", + .probe = ni_usb_driver_probe, + .disconnect = ni_usb_driver_disconnect, + .suspend = ni_usb_driver_suspend, + .resume = ni_usb_driver_resume, + .id_table = ni_usb_driver_device_table, +}; + +static int __init ni_usb_init_module(void) +{ + int i; + + pr_info("ni_usb_gpib driver loading\n"); + for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) + ni_usb_driver_interfaces[i] = NULL; + usb_register(&ni_usb_bus_driver); + gpib_register_driver(&ni_usb_gpib_interface, THIS_MODULE); + + return 0; +} + +static void __exit ni_usb_exit_module(void) +{ + pr_info("ni_usb_gpib driver unloading\n"); + gpib_unregister_driver(&ni_usb_gpib_interface); + usb_deregister(&ni_usb_bus_driver); +} + +module_init(ni_usb_init_module); +module_exit(ni_usb_exit_module); diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.h b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h new file mode 100644 index 0000000000000000000000000000000000000000..9b21dfa0f3f6d12480a86bdf3a9ecade24eaeb8a --- /dev/null +++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2004 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _NI_USB_GPIB_H +#define _NI_USB_GPIB_H + +#include <linux/mutex.h> +#include <linux/semaphore.h> +#include <linux/usb.h> +#include <linux/timer.h> +#include "gpibP.h" + +enum { + USB_VENDOR_ID_NI = 0x3923 +}; + +enum { + USB_DEVICE_ID_NI_USB_B = 0x702a, + USB_DEVICE_ID_NI_USB_B_PREINIT = 0x702b, // device id before firmware is loaded + USB_DEVICE_ID_NI_USB_HS = 0x709b, + USB_DEVICE_ID_NI_USB_HS_PLUS = 0x7618, + USB_DEVICE_ID_KUSB_488A = 0x725c, + USB_DEVICE_ID_MC_USB_488 = 0x725d +}; + +enum ni_usb_device { + NIUSB_SUBDEV_TNT4882 = 1, + NIUSB_SUBDEV_UNKNOWN2 = 2, + NIUSB_SUBDEV_UNKNOWN3 = 3, +}; + +enum endpoint_addresses { + NIUSB_B_BULK_OUT_ENDPOINT = 0x2, + NIUSB_B_BULK_IN_ENDPOINT = 0x2, + NIUSB_B_BULK_IN_ALT_ENDPOINT = 0x6, + NIUSB_B_INTERRUPT_IN_ENDPOINT = 0x4, +}; + +enum hs_enpoint_addresses { + NIUSB_HS_BULK_OUT_ENDPOINT = 0x2, + NIUSB_HS_BULK_OUT_ALT_ENDPOINT = 0x6, + NIUSB_HS_BULK_IN_ENDPOINT = 0x4, + NIUSB_HS_BULK_IN_ALT_ENDPOINT = 0x8, + NIUSB_HS_INTERRUPT_IN_ENDPOINT = 0x1, +}; + +enum hs_plus_endpoint_addresses { + NIUSB_HS_PLUS_BULK_OUT_ENDPOINT = 0x1, + NIUSB_HS_PLUS_BULK_OUT_ALT_ENDPOINT = 0x4, + NIUSB_HS_PLUS_BULK_IN_ENDPOINT = 0x2, + NIUSB_HS_PLUS_BULK_IN_ALT_ENDPOINT = 0x5, + NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT = 0x3, +}; + +struct ni_usb_urb_ctx { + struct semaphore complete; + unsigned timed_out : 1; +}; + +// struct which defines private_data for ni_usb devices +struct ni_usb_priv { + struct usb_interface *bus_interface; + int bulk_out_endpoint; + int bulk_in_endpoint; + int interrupt_in_endpoint; + u8 eos_char; + unsigned short eos_mode; + unsigned int monitored_ibsta_bits; + struct urb *bulk_urb; + struct urb *interrupt_urb; + u8 interrupt_buffer[0x11]; + struct mutex addressed_transfer_lock; // protect transfer lock + struct mutex bulk_transfer_lock; // protect bulk message sends + struct mutex control_transfer_lock; // protect control messages + struct mutex interrupt_transfer_lock; // protect interrupt messages + struct timer_list bulk_timer; + struct ni_usb_urb_ctx context; + int product_id; + unsigned short ren_state; +}; + +struct ni_usb_status_block { + short id; + unsigned short ibsta; + short error_code; + unsigned short count; +}; + +struct ni_usb_register { + enum ni_usb_device device; + short address; + unsigned short value; +}; + +enum ni_usb_bulk_ids { + NIUSB_IBCAC_ID = 0x1, + NIUSB_UNKNOWN3_ID = 0x3, // device level function id? + NIUSB_TERM_ID = 0x4, + NIUSB_IBGTS_ID = 0x6, + NIUSB_IBRPP_ID = 0x7, + NIUSB_REG_READ_ID = 0x8, + NIUSB_REG_WRITE_ID = 0x9, + NIUSB_IBSIC_ID = 0xf, + NIUSB_REGISTER_READ_DATA_START_ID = 0x34, + NIUSB_REGISTER_READ_DATA_END_ID = 0x35, + NIUSB_IBRD_DATA_ID = 0x36, + NIUSB_IBRD_EXTENDED_DATA_ID = 0x37, + NIUSB_IBRD_STATUS_ID = 0x38 +}; + +enum ni_usb_error_codes { + NIUSB_NO_ERROR = 0, + /* NIUSB_ABORTED_ERROR occurs when I/O is interrupted early by + * doing a NI_USB_STOP_REQUEST on the control endpoint. + */ + NIUSB_ABORTED_ERROR = 1, + // NIUSB_READ_ATN_ERROR occurs when you do a board read while + // ATN is set + NIUSB_ATN_STATE_ERROR = 2, + // NIUSB_ADDRESSING_ERROR occurs when you do a board + // read/write as CIC but are not in LACS/TACS + NIUSB_ADDRESSING_ERROR = 3, + /* NIUSB_EOSMODE_ERROR occurs on reads if any eos mode or char + * bits are set when REOS is not set. + * Have also seen error 4 if you try to send more than 16 + * command bytes at once on a usb-b. + */ + NIUSB_EOSMODE_ERROR = 4, + // NIUSB_NO_BUS_ERROR occurs when you try to write a command + // byte but there are no devices connected to the gpib bus + NIUSB_NO_BUS_ERROR = 5, + // NIUSB_NO_LISTENER_ERROR occurs when you do a board write as + // CIC with no listener + NIUSB_NO_LISTENER_ERROR = 8, + // get NIUSB_TIMEOUT_ERROR on board read/write timeout + NIUSB_TIMEOUT_ERROR = 10, +}; + +enum ni_usb_control_requests { + NI_USB_STOP_REQUEST = 0x20, + NI_USB_WAIT_REQUEST = 0x21, + NI_USB_POLL_READY_REQUEST = 0x40, + NI_USB_SERIAL_NUMBER_REQUEST = 0x41, + NI_USB_HS_PLUS_0x48_REQUEST = 0x48, + NI_USB_HS_PLUS_LED_REQUEST = 0x4b, + NI_USB_HS_PLUS_0xf8_REQUEST = 0xf8 +}; + +static const unsigned int ni_usb_ibsta_monitor_mask = + SRQI | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS; + +static inline int nec7210_to_tnt4882_offset(int offset) +{ + return 2 * offset; +}; + +static inline int ni_usb_bulk_termination(u8 *buffer) +{ + int i = 0; + + buffer[i++] = NIUSB_TERM_ID; + buffer[i++] = 0x0; + buffer[i++] = 0x0; + buffer[i++] = 0x0; + return i; +} + +enum ni_usb_unknown3_register { + SERIAL_NUMBER_4_REG = 0x8, + SERIAL_NUMBER_3_REG = 0x9, + SERIAL_NUMBER_2_REG = 0xa, + SERIAL_NUMBER_1_REG = 0xb, +}; + +static inline int ni_usb_bulk_register_write_header(u8 *buffer, int num_writes) +{ + int i = 0; + + buffer[i++] = NIUSB_REG_WRITE_ID; + buffer[i++] = num_writes; + buffer[i++] = 0x0; + return i; +} + +static inline int ni_usb_bulk_register_write(u8 *buffer, struct ni_usb_register reg) +{ + int i = 0; + + buffer[i++] = reg.device; + buffer[i++] = reg.address; + buffer[i++] = reg.value; + return i; +} + +static inline int ni_usb_bulk_register_read_header(u8 *buffer, int num_reads) +{ + int i = 0; + + buffer[i++] = NIUSB_REG_READ_ID; + buffer[i++] = num_reads; + return i; +} + +static inline int ni_usb_bulk_register_read(u8 *buffer, int device, int address) +{ + int i = 0; + + buffer[i++] = device; + buffer[i++] = address; + return i; +} + +#endif // _NI_USB_GPIB_H diff --git a/drivers/staging/gpib/pc2/Makefile b/drivers/staging/gpib/pc2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8148425e0f8760a771474c5578baf802927feba1 --- /dev/null +++ b/drivers/staging/gpib/pc2/Makefile @@ -0,0 +1,5 @@ + +obj-m += pc2_gpib.o + + + diff --git a/drivers/staging/gpib/pc2/pc2_gpib.c b/drivers/staging/gpib/pc2/pc2_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..7b3b34f4734168eb01859ae1bfe428dcb6fb8783 --- /dev/null +++ b/drivers/staging/gpib/pc2/pc2_gpib.c @@ -0,0 +1,656 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/bitops.h> +#include <asm/dma.h> +#include <linux/dma-mapping.h> +#include <linux/string.h> +#include <linux/init.h> +#include "nec7210.h" +#include "gpibP.h" + +// struct which defines private_data for pc2 driver +struct pc2_priv { + struct nec7210_priv nec7210_priv; + unsigned int irq; + // io address that clears interrupt for pc2a (0x2f0 + irq) + unsigned int clear_intr_addr; +}; + +// pc2 uses 8 consecutive io addresses +static const int pc2_iosize = 8; +static const int pc2a_iosize = 8; +static const int pc2_2a_iosize = 16; + +// offset between io addresses of successive nec7210 registers +static const int pc2a_reg_offset = 0x400; +static const int pc2_reg_offset = 1; + +//interrupt service routine +static irqreturn_t pc2_interrupt(int irq, void *arg); +static irqreturn_t pc2a_interrupt(int irq, void *arg); + +// pc2 specific registers and bits + +// interrupt clear register address +static const int pc2a_clear_intr_iobase = 0x2f0; +static inline unsigned int CLEAR_INTR_REG(unsigned int irq) +{ + return pc2a_clear_intr_iobase + irq; +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for PC2/PC2a and compatible devices"); + +static int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void pc2_detach(gpib_board_t *board); +static void pc2a_detach(gpib_board_t *board); +static void pc2_2a_detach(gpib_board_t *board); + +/* + * GPIB interrupt service routines + */ + +irqreturn_t pc2_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct pc2_priv *priv = board->private_data; + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = nec7210_interrupt(board, &priv->nec7210_priv); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +irqreturn_t pc2a_interrupt(int irq, void *arg) +{ + gpib_board_t *board = arg; + struct pc2_priv *priv = board->private_data; + int status1, status2; + unsigned long flags; + irqreturn_t retval; + + spin_lock_irqsave(&board->spinlock, flags); + // read interrupt status (also clears status) + status1 = read_byte(&priv->nec7210_priv, ISR1); + status2 = read_byte(&priv->nec7210_priv, ISR2); + /* clear interrupt circuit */ + if (priv->irq) + outb(0xff, CLEAR_INTR_REG(priv->irq)); + retval = nec7210_interrupt_have_status(board, &priv->nec7210_priv, status1, status2); + spin_unlock_irqrestore(&board->spinlock, flags); + return retval; +} + +// wrappers for interface functions +static int pc2_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); +} + +static int pc2_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +static int pc2_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +static int pc2_take_control(gpib_board_t *board, int synchronous) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +static int pc2_go_to_standby(gpib_board_t *board) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +static void pc2_request_system_control(gpib_board_t *board, int request_control) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_request_system_control(board, &priv->nec7210_priv, request_control); +} + +static void pc2_interface_clear(gpib_board_t *board, int assert) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +static void pc2_remote_enable(gpib_board_t *board, int enable) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +static int pc2_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +static void pc2_disable_eos(gpib_board_t *board) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +static unsigned int pc2_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); +} + +static int pc2_primary_address(gpib_board_t *board, unsigned int address) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +static int pc2_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +static int pc2_parallel_poll(gpib_board_t *board, uint8_t *result) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_parallel_poll(board, &priv->nec7210_priv, result); +} + +static void pc2_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); +} + +static void pc2_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +static void pc2_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_serial_poll_response(board, &priv->nec7210_priv, status); +} + +static uint8_t pc2_serial_poll_status(gpib_board_t *board) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +static unsigned int pc2_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct pc2_priv *priv = board->private_data; + + return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec); +} + +static void pc2_return_to_local(gpib_board_t *board) +{ + struct pc2_priv *priv = board->private_data; + + nec7210_return_to_local(board, &priv->nec7210_priv); +} + +gpib_interface_t pc2_interface = { +name: "pcII", +attach : pc2_attach, +detach : pc2_detach, +read : pc2_read, +write : pc2_write, +command : pc2_command, +take_control : pc2_take_control, +go_to_standby : pc2_go_to_standby, +request_system_control : pc2_request_system_control, +interface_clear : pc2_interface_clear, +remote_enable : pc2_remote_enable, +enable_eos : pc2_enable_eos, +disable_eos : pc2_disable_eos, +parallel_poll : pc2_parallel_poll, +parallel_poll_configure : pc2_parallel_poll_configure, +parallel_poll_response : pc2_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, +update_status : pc2_update_status, +primary_address : pc2_primary_address, +secondary_address : pc2_secondary_address, +serial_poll_response : pc2_serial_poll_response, +serial_poll_status : pc2_serial_poll_status, +t1_delay : pc2_t1_delay, +return_to_local : pc2_return_to_local, +}; + +gpib_interface_t pc2a_interface = { +name: "pcIIa", +attach : pc2a_attach, +detach : pc2a_detach, +read : pc2_read, +write : pc2_write, +command : pc2_command, +take_control : pc2_take_control, +go_to_standby : pc2_go_to_standby, +request_system_control : pc2_request_system_control, +interface_clear : pc2_interface_clear, +remote_enable : pc2_remote_enable, +enable_eos : pc2_enable_eos, +disable_eos : pc2_disable_eos, +parallel_poll : pc2_parallel_poll, +parallel_poll_configure : pc2_parallel_poll_configure, +parallel_poll_response : pc2_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, +update_status : pc2_update_status, +primary_address : pc2_primary_address, +secondary_address : pc2_secondary_address, +serial_poll_response : pc2_serial_poll_response, +serial_poll_status : pc2_serial_poll_status, +t1_delay : pc2_t1_delay, +return_to_local : pc2_return_to_local, +}; + +gpib_interface_t pc2a_cb7210_interface = { +name: "pcIIa_cb7210", +attach : pc2a_cb7210_attach, +detach : pc2a_detach, +read : pc2_read, +write : pc2_write, +command : pc2_command, +take_control : pc2_take_control, +go_to_standby : pc2_go_to_standby, +request_system_control : pc2_request_system_control, +interface_clear : pc2_interface_clear, +remote_enable : pc2_remote_enable, +enable_eos : pc2_enable_eos, +disable_eos : pc2_disable_eos, +parallel_poll : pc2_parallel_poll, +parallel_poll_configure : pc2_parallel_poll_configure, +parallel_poll_response : pc2_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, //XXX +update_status : pc2_update_status, +primary_address : pc2_primary_address, +secondary_address : pc2_secondary_address, +serial_poll_response : pc2_serial_poll_response, +serial_poll_status : pc2_serial_poll_status, +t1_delay : pc2_t1_delay, +return_to_local : pc2_return_to_local, +}; + +gpib_interface_t pc2_2a_interface = { +name: "pcII_IIa", +attach : pc2_2a_attach, +detach : pc2_2a_detach, +read : pc2_read, +write : pc2_write, +command : pc2_command, +take_control : pc2_take_control, +go_to_standby : pc2_go_to_standby, +request_system_control : pc2_request_system_control, +interface_clear : pc2_interface_clear, +remote_enable : pc2_remote_enable, +enable_eos : pc2_enable_eos, +disable_eos : pc2_disable_eos, +parallel_poll : pc2_parallel_poll, +parallel_poll_configure : pc2_parallel_poll_configure, +parallel_poll_response : pc2_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, +update_status : pc2_update_status, +primary_address : pc2_primary_address, +secondary_address : pc2_secondary_address, +serial_poll_response : pc2_serial_poll_response, +serial_poll_status : pc2_serial_poll_status, +t1_delay : pc2_t1_delay, +return_to_local : pc2_return_to_local, +}; + +static int allocate_private(gpib_board_t *board) +{ + struct pc2_priv *priv; + + board->private_data = kmalloc(sizeof(struct pc2_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + priv = board->private_data; + memset(priv, 0, sizeof(struct pc2_priv)); + init_nec7210_private(&priv->nec7210_priv); + return 0; +} + +static void free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +static int pc2_generic_attach(gpib_board_t *board, const gpib_board_config_t *config, + enum nec7210_chipset chipset) +{ + struct pc2_priv *pc2_priv; + struct nec7210_priv *nec_priv; + + board->status = 0; + if (allocate_private(board)) + return -ENOMEM; + pc2_priv = board->private_data; + nec_priv = &pc2_priv->nec7210_priv; + nec_priv->read_byte = nec7210_ioport_read_byte; + nec_priv->write_byte = nec7210_ioport_write_byte; + nec_priv->type = chipset; + +#ifndef PC2_DMA + /* board->dev hasn't been initialized, so forget about DMA until this driver + * is adapted to use isa_register_driver. + */ + if (config->ibdma) + pr_err("DMA disabled for pc2 gpib, driver needs to be adapted to use isa_register_driver to get a struct device*"); +#else + if (config->ibdma) { + nec_priv->dma_buffer_length = 0x1000; + nec_priv->dma_buffer = dma_alloc_coherent(board->dev, + nec_priv->dma_buffer_length, & + nec_priv->dma_buffer_addr, GFP_ATOMIC); + if (!nec_priv->dma_buffer) + return -ENOMEM; + + // request isa dma channel + if (request_dma(config->ibdma, "pc2")) { + pr_err("gpib: can't request DMA %d\n", config->ibdma); + return -1; + } + nec_priv->dma_channel = config->ibdma; + } +#endif + + return 0; +} + +int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + int isr_flags = 0; + struct pc2_priv *pc2_priv; + struct nec7210_priv *nec_priv; + int retval; + + retval = pc2_generic_attach(board, config, NEC7210); + if (retval) + return retval; + + pc2_priv = board->private_data; + nec_priv = &pc2_priv->nec7210_priv; + nec_priv->offset = pc2_reg_offset; + + if (request_region((unsigned long)config->ibbase, pc2_iosize, "pc2") == 0) { + pr_err("gpib: ioports are already in use\n"); + return -1; + } + nec_priv->iobase = config->ibbase; + + nec7210_board_reset(nec_priv, board); + + // install interrupt handler + if (config->ibirq) { + if (request_irq(config->ibirq, pc2_interrupt, isr_flags, "pc2", board)) { + pr_err("gpib: can't request IRQ %d\n", config->ibirq); + return -1; + } + } + pc2_priv->irq = config->ibirq; + /* poll so we can detect assertion of ATN */ + if (gpib_request_pseudo_irq(board, pc2_interrupt)) { + pr_err("pc2_gpib: failed to allocate pseudo_irq\n"); + return -1; + } + /* set internal counter register for 8 MHz input clock */ + write_byte(nec_priv, ICR | 8, AUXMR); + + nec7210_board_online(nec_priv, board); + + return 0; +} + +void pc2_detach(gpib_board_t *board) +{ + struct pc2_priv *pc2_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (pc2_priv) { + nec_priv = &pc2_priv->nec7210_priv; +#ifdef PC2_DMA + if (nec_priv->dma_channel) + free_dma(nec_priv->dma_channel); +#endif + gpib_free_pseudo_irq(board); + if (pc2_priv->irq) + free_irq(pc2_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + release_region((unsigned long)(nec_priv->iobase), pc2_iosize); + } + if (nec_priv->dma_buffer) { + dma_free_coherent(board->dev, nec_priv->dma_buffer_length, + nec_priv->dma_buffer, nec_priv->dma_buffer_addr); + nec_priv->dma_buffer = NULL; + } + } + free_private(board); +} + +static int pc2a_common_attach(gpib_board_t *board, const gpib_board_config_t *config, + unsigned int num_registers, enum nec7210_chipset chipset) +{ + unsigned int i, j; + struct pc2_priv *pc2_priv; + struct nec7210_priv *nec_priv; + int retval; + + retval = pc2_generic_attach(board, config, chipset); + if (retval) + return retval; + + pc2_priv = board->private_data; + nec_priv = &pc2_priv->nec7210_priv; + nec_priv->offset = pc2a_reg_offset; + + switch ((unsigned long)(config->ibbase)) { + case 0x02e1: + case 0x22e1: + case 0x42e1: + case 0x62e1: + break; + default: + pr_err("PCIIa base range invalid, must be one of 0x[0246]2e1, but is 0x%p\n", + config->ibbase); + return -1; + } + + if (config->ibirq) { + if (config->ibirq < 2 || config->ibirq > 7) { + pr_err("pc2_gpib: illegal interrupt level %i\n", config->ibirq); + return -1; + } + } else { + pr_err("pc2_gpib: interrupt disabled, using polling mode (slow)\n"); + } +#ifdef CHECK_IOPORTS + unsigned int err = 0; + + for (i = 0; i < num_registers; i++) { + if (check_region((unsigned long)config->ibbase + i * pc2a_reg_offset, 1)) + err++; + } + if (config->ibirq && check_region(pc2a_clear_intr_iobase + config->ibirq, 1)) + err++; + if (err) { + pr_err("gpib: ioports are already in use"); + return -1; + } +#endif + for (i = 0; i < num_registers; i++) { + if (!request_region((unsigned long)config->ibbase + + i * pc2a_reg_offset, 1, "pc2a")) { + pr_err("gpib: ioports are already in use"); + for (j = 0; j < i; j++) + release_region((unsigned long)(config->ibbase) + + j * pc2a_reg_offset, 1); + return -1; + } + } + nec_priv->iobase = config->ibbase; + if (config->ibirq) { + if (!request_region(pc2a_clear_intr_iobase + config->ibirq, 1, "pc2a")) { + pr_err("gpib: ioports are already in use"); + return -1; + } + pc2_priv->clear_intr_addr = pc2a_clear_intr_iobase + config->ibirq; + if (request_irq(config->ibirq, pc2a_interrupt, 0, "pc2a", board)) { + pr_err("gpib: can't request IRQ %d\n", config->ibirq); + return -1; + } + } + pc2_priv->irq = config->ibirq; + /* poll so we can detect assertion of ATN */ + if (gpib_request_pseudo_irq(board, pc2_interrupt)) { + pr_err("pc2_gpib: failed to allocate pseudo_irq\n"); + return -1; + } + + // make sure interrupt is clear + if (pc2_priv->irq) + outb(0xff, CLEAR_INTR_REG(pc2_priv->irq)); + + nec7210_board_reset(nec_priv, board); + + /* set internal counter register for 8 MHz input clock */ + write_byte(nec_priv, ICR | 8, AUXMR); + + nec7210_board_online(nec_priv, board); + + return 0; +} + +int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + return pc2a_common_attach(board, config, pc2a_iosize, NEC7210); +} + +int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + return pc2a_common_attach(board, config, pc2a_iosize, CB7210); +} + +int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + return pc2a_common_attach(board, config, pc2_2a_iosize, NAT4882); +} + +static void pc2a_common_detach(gpib_board_t *board, unsigned int num_registers) +{ + int i; + struct pc2_priv *pc2_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (pc2_priv) { + nec_priv = &pc2_priv->nec7210_priv; +#ifdef PC2_DMA + if (nec_priv->dma_channel) + free_dma(nec_priv->dma_channel); +#endif + gpib_free_pseudo_irq(board); + if (pc2_priv->irq) + free_irq(pc2_priv->irq, board); + if (nec_priv->iobase) { + nec7210_board_reset(nec_priv, board); + for (i = 0; i < num_registers; i++) + release_region((unsigned long)nec_priv->iobase + + i * pc2a_reg_offset, 1); + } + if (pc2_priv->clear_intr_addr) + release_region(pc2_priv->clear_intr_addr, 1); + if (nec_priv->dma_buffer) { + dma_free_coherent(board->dev, nec_priv->dma_buffer_length, + nec_priv->dma_buffer, + nec_priv->dma_buffer_addr); + nec_priv->dma_buffer = NULL; + } + } + free_private(board); +} + +void pc2a_detach(gpib_board_t *board) +{ + pc2a_common_detach(board, pc2a_iosize); +} + +void pc2_2a_detach(gpib_board_t *board) +{ + pc2a_common_detach(board, pc2_2a_iosize); +} + +static int __init pc2_init_module(void) +{ + gpib_register_driver(&pc2_interface, THIS_MODULE); + gpib_register_driver(&pc2a_interface, THIS_MODULE); + gpib_register_driver(&pc2a_cb7210_interface, THIS_MODULE); + gpib_register_driver(&pc2_2a_interface, THIS_MODULE); + + return 0; +} + +static void __exit pc2_exit_module(void) +{ + gpib_unregister_driver(&pc2_interface); + gpib_unregister_driver(&pc2a_interface); + gpib_unregister_driver(&pc2a_cb7210_interface); + gpib_unregister_driver(&pc2_2a_interface); +} + +module_init(pc2_init_module); +module_exit(pc2_exit_module); + diff --git a/drivers/staging/gpib/tms9914/Makefile b/drivers/staging/gpib/tms9914/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..81b7e3cf104c0ed5528aaa20d2155c20067de23f --- /dev/null +++ b/drivers/staging/gpib/tms9914/Makefile @@ -0,0 +1,6 @@ + +obj-m += tms9914.o + + + + diff --git a/drivers/staging/gpib/tms9914/tms9914.c b/drivers/staging/gpib/tms9914/tms9914.c new file mode 100644 index 0000000000000000000000000000000000000000..152b243b845b50927814786cf220e43c75b2cd4f --- /dev/null +++ b/drivers/staging/gpib/tms9914/tms9914.c @@ -0,0 +1,910 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/dma.h> +#include <linux/io.h> +#include <linux/bitops.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/delay.h> + +#include "gpibP.h" +#include "tms9914.h" + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB library for tms9914"); + +static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv); + +int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int synchronous) +{ + int i; + const int timeout = 100; + + if (synchronous) + write_byte(priv, AUX_TCS, AUXCR); + else + write_byte(priv, AUX_TCA, AUXCR); + // busy wait until ATN is asserted + for (i = 0; i < timeout; i++) { + if ((read_byte(priv, ADSR) & HR_ATN)) + break; + udelay(1); + } + if (i == timeout) + return -ETIMEDOUT; + + clear_bit(WRITE_READY_BN, &priv->state); + + return 0; +} +EXPORT_SYMBOL_GPL(tms9914_take_control); + +/* The agilent 82350B has a buggy implementation of tcs which interferes with the + * operation of tca. It appears to be based on the controller state machine + * described in the TI 9900 TMS9914A data manual published in 1982. This + * manual describes tcs as putting the controller into a CWAS + * state where it waits indefinitely for ANRS and ignores tca. Since a + * functioning tca is far more important than tcs, we work around the + * problem by never issuing tcs. + * + * I don't know if this problem exists in the real tms9914a or just in the fpga + * of the 82350B. For now, only the agilent_82350b uses this workaround. + * The rest of the tms9914 based drivers still use tms9914_take_control + * directly (which does issue tcs). + */ +int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv, int synchronous) +{ + if (synchronous) + return -ETIMEDOUT; + return tms9914_take_control(board, priv, synchronous); +} +EXPORT_SYMBOL_GPL(tms9914_take_control_workaround); + +int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv) +{ + int i; + const int timeout = 1000; + + write_byte(priv, AUX_GTS, AUXCR); + // busy wait until ATN is released + for (i = 0; i < timeout; i++) { + if ((read_byte(priv, ADSR) & HR_ATN) == 0) + break; + udelay(1); + } + if (i == timeout) { + pr_err("error waiting for NATN\n"); + return -ETIMEDOUT; + } + + clear_bit(COMMAND_READY_BN, &priv->state); + + return 0; +} +EXPORT_SYMBOL_GPL(tms9914_go_to_standby); + +void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert) +{ + if (assert) { + write_byte(priv, AUX_SIC | AUX_CS, AUXCR); + + set_bit(CIC_NUM, &board->status); + } else { + write_byte(priv, AUX_SIC, AUXCR); + } +} +EXPORT_SYMBOL_GPL(tms9914_interface_clear); + +void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable) +{ + if (enable) + write_byte(priv, AUX_SRE | AUX_CS, AUXCR); + else + write_byte(priv, AUX_SRE, AUXCR); +} +EXPORT_SYMBOL_GPL(tms9914_remote_enable); + +void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv, + int request_control) +{ + if (request_control) { + write_byte(priv, AUX_RQC, AUXCR); + } else { + clear_bit(CIC_NUM, &board->status); + write_byte(priv, AUX_RLC, AUXCR); + } +} +EXPORT_SYMBOL_GPL(tms9914_request_system_control); + +unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv, + unsigned int nano_sec) +{ + static const int clock_period = 200; // assuming 5Mhz input clock + int num_cycles; + + num_cycles = 12; + + if (nano_sec <= 8 * clock_period) { + write_byte(priv, AUX_STDL | AUX_CS, AUXCR); + num_cycles = 8; + } else { + write_byte(priv, AUX_STDL, AUXCR); + } + + if (nano_sec <= 4 * clock_period) { + write_byte(priv, AUX_VSTDL | AUX_CS, AUXCR); + num_cycles = 4; + } else { + write_byte(priv, AUX_VSTDL, AUXCR); + } + + return num_cycles * clock_period; +} +EXPORT_SYMBOL_GPL(tms9914_t1_delay); + +void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv) +{ + write_byte(priv, AUX_RTL, AUXCR); +} +EXPORT_SYMBOL_GPL(tms9914_return_to_local); + +void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode) +{ + switch (mode) { + case TMS9914_HOLDOFF_NONE: + write_byte(priv, AUX_HLDE, AUXCR); + write_byte(priv, AUX_HLDA, AUXCR); + break; + case TMS9914_HOLDOFF_EOI: + write_byte(priv, AUX_HLDE | AUX_CS, AUXCR); + write_byte(priv, AUX_HLDA, AUXCR); + break; + case TMS9914_HOLDOFF_ALL: + write_byte(priv, AUX_HLDE, AUXCR); + write_byte(priv, AUX_HLDA | AUX_CS, AUXCR); + break; + default: + pr_err("%s: bug! bad holdoff mode %i\n", __func__, mode); + break; + } + priv->holdoff_mode = mode; +} +EXPORT_SYMBOL_GPL(tms9914_set_holdoff_mode); + +void tms9914_release_holdoff(struct tms9914_priv *priv) +{ + if (priv->holdoff_active) { + write_byte(priv, AUX_RHDF, AUXCR); + priv->holdoff_active = 0; + } +} +EXPORT_SYMBOL_GPL(tms9914_release_holdoff); + +int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_byte, + int compare_8_bits) +{ + priv->eos = eos_byte; + priv->eos_flags = REOS; + if (compare_8_bits) + priv->eos_flags |= BIN; + return 0; +} +EXPORT_SYMBOL(tms9914_enable_eos); + +void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv) +{ + priv->eos_flags &= ~REOS; +} +EXPORT_SYMBOL(tms9914_disable_eos); + +int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result) +{ + // execute parallel poll + write_byte(priv, AUX_CS | AUX_RPP, AUXCR); + udelay(2); + *result = read_byte(priv, CPTR); + // clear parallel poll state + write_byte(priv, AUX_RPP, AUXCR); + return 0; +} +EXPORT_SYMBOL(tms9914_parallel_poll); + +static void set_ppoll_reg(struct tms9914_priv *priv, int enable, + unsigned int dio_line, int sense, int ist) +{ + u8 dio_byte; + + if (enable && ((sense && ist) || (!sense && !ist))) { + dio_byte = 1 << (dio_line - 1); + write_byte(priv, dio_byte, PPR); + } else { + write_byte(priv, 0, PPR); + } +} + +void tms9914_parallel_poll_configure(gpib_board_t *board, + struct tms9914_priv *priv, uint8_t config) +{ + priv->ppoll_enable = (config & PPC_DISABLE) == 0; + priv->ppoll_line = (config & PPC_DIO_MASK) + 1; + priv->ppoll_sense = (config & PPC_SENSE) != 0; + set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, board->ist); +} +EXPORT_SYMBOL(tms9914_parallel_poll_configure); + +void tms9914_parallel_poll_response(gpib_board_t *board, + struct tms9914_priv *priv, int ist) +{ + set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, ist); +} +EXPORT_SYMBOL(tms9914_parallel_poll_response); + +void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status) +{ + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + write_byte(priv, status, SPMR); + priv->spoll_status = status; + if (status & request_service_bit) + write_byte(priv, AUX_RSV2 | AUX_CS, AUXCR); + else + write_byte(priv, AUX_RSV2, AUXCR); + spin_unlock_irqrestore(&board->spinlock, flags); +} +EXPORT_SYMBOL(tms9914_serial_poll_response); + +uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv) +{ + u8 status; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + status = priv->spoll_status; + spin_unlock_irqrestore(&board->spinlock, flags); + + return status; +} +EXPORT_SYMBOL(tms9914_serial_poll_status); + +int tms9914_primary_address(gpib_board_t *board, struct tms9914_priv *priv, unsigned int address) +{ + // put primary address in address0 + write_byte(priv, address & ADDRESS_MASK, ADR); + return 0; +} +EXPORT_SYMBOL(tms9914_primary_address); + +int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv, + unsigned int address, int enable) +{ + if (enable) + priv->imr1_bits |= HR_APTIE; + else + priv->imr1_bits &= ~HR_APTIE; + + write_byte(priv, priv->imr1_bits, IMR1); + return 0; +} +EXPORT_SYMBOL(tms9914_secondary_address); + +unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv, + unsigned int clear_mask) +{ + unsigned long flags; + unsigned int retval; + + spin_lock_irqsave(&board->spinlock, flags); + retval = update_status_nolock(board, priv); + board->status &= ~clear_mask; + spin_unlock_irqrestore(&board->spinlock, flags); + + return retval; +} +EXPORT_SYMBOL(tms9914_update_status); + +static void update_talker_state(struct tms9914_priv *priv, unsigned int address_status_bits) +{ + if (address_status_bits & HR_TA) { + if (address_status_bits & HR_ATN) + priv->talker_state = talker_addressed; + else + /* this could also be serial_poll_active, but the tms9914 provides no + * way to distinguish, so we'll assume talker_active + */ + priv->talker_state = talker_active; + } else { + priv->talker_state = talker_idle; + } +} + +static void update_listener_state(struct tms9914_priv *priv, unsigned int address_status_bits) +{ + if (address_status_bits & HR_LA) { + if (address_status_bits & HR_ATN) + priv->listener_state = listener_addressed; + else + priv->listener_state = listener_active; + } else { + priv->listener_state = listener_idle; + } +} + +static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv) +{ + int address_status; + int bsr_bits; + + address_status = read_byte(priv, ADSR); + + // check for remote/local + if (address_status & HR_REM) + set_bit(REM_NUM, &board->status); + else + clear_bit(REM_NUM, &board->status); + // check for lockout + if (address_status & HR_LLO) + set_bit(LOK_NUM, &board->status); + else + clear_bit(LOK_NUM, &board->status); + // check for ATN + if (address_status & HR_ATN) + set_bit(ATN_NUM, &board->status); + else + clear_bit(ATN_NUM, &board->status); + // check for talker/listener addressed + update_talker_state(priv, address_status); + if (priv->talker_state == talker_active || priv->talker_state == talker_addressed) + set_bit(TACS_NUM, &board->status); + else + clear_bit(TACS_NUM, &board->status); + + update_listener_state(priv, address_status); + if (priv->listener_state == listener_active || priv->listener_state == listener_addressed) + set_bit(LACS_NUM, &board->status); + else + clear_bit(LACS_NUM, &board->status); + // Check for SRQI - not reset elsewhere except in autospoll + if (board->status & SRQI) { + bsr_bits = read_byte(priv, BSR); + if (!(bsr_bits & BSR_SRQ_BIT)) + clear_bit(SRQI_NUM, &board->status); + } + + dev_dbg(board->gpib_dev, "status 0x%lx, state 0x%lx\n", board->status, priv->state); + + return board->status; +} + +int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv) +{ + int bsr_bits; + int status = ValidALL; + + bsr_bits = read_byte(priv, BSR); + + if (bsr_bits & BSR_REN_BIT) + status |= BusREN; + if (bsr_bits & BSR_IFC_BIT) + status |= BusIFC; + if (bsr_bits & BSR_SRQ_BIT) + status |= BusSRQ; + if (bsr_bits & BSR_EOI_BIT) + status |= BusEOI; + if (bsr_bits & BSR_NRFD_BIT) + status |= BusNRFD; + if (bsr_bits & BSR_NDAC_BIT) + status |= BusNDAC; + if (bsr_bits & BSR_DAV_BIT) + status |= BusDAV; + if (bsr_bits & BSR_ATN_BIT) + status |= BusATN; + + return status; +} +EXPORT_SYMBOL(tms9914_line_status); + +static int check_for_eos(struct tms9914_priv *priv, uint8_t byte) +{ + static const u8 seven_bit_compare_mask = 0x7f; + + if ((priv->eos_flags & REOS) == 0) + return 0; + + if (priv->eos_flags & BIN) { + if (priv->eos == byte) + return 1; + } else { + if ((priv->eos & seven_bit_compare_mask) == (byte & seven_bit_compare_mask)) + return 1; + } + return 0; +} + +static int wait_for_read_byte(gpib_board_t *board, struct tms9914_priv *priv) +{ + if (wait_event_interruptible(board->wait, + test_bit(READ_READY_BN, &priv->state) || + test_bit(DEV_CLEAR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_debug("gpib: pio read wait interrupted\n"); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + return -ETIMEDOUT; + + if (test_bit(DEV_CLEAR_BN, &priv->state)) + return -EINTR; + return 0; +} + +static inline uint8_t tms9914_read_data_in(gpib_board_t *board, struct tms9914_priv *priv, int *end) +{ + unsigned long flags; + u8 data; + + spin_lock_irqsave(&board->spinlock, flags); + clear_bit(READ_READY_BN, &priv->state); + data = read_byte(priv, DIR); + if (test_and_clear_bit(RECEIVED_END_BN, &priv->state)) + *end = 1; + else + *end = 0; + switch (priv->holdoff_mode) { + case TMS9914_HOLDOFF_EOI: + if (*end) + priv->holdoff_active = 1; + break; + case TMS9914_HOLDOFF_ALL: + priv->holdoff_active = 1; + break; + case TMS9914_HOLDOFF_NONE: + break; + default: + pr_err("%s: bug! bad holdoff mode %i\n", __func__, priv->holdoff_mode); + break; + } + spin_unlock_irqrestore(&board->spinlock, flags); + + return data; +} + +static int pio_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval = 0; + + *bytes_read = 0; + *end = 0; + while (*bytes_read < length && *end == 0) { + tms9914_release_holdoff(priv); + retval = wait_for_read_byte(board, priv); + if (retval < 0) + return retval; + buffer[(*bytes_read)++] = tms9914_read_data_in(board, priv, end); + + if (check_for_eos(priv, buffer[*bytes_read - 1])) + *end = 1; + } + + return retval; +} + +int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, int *end, size_t *bytes_read) +{ + ssize_t retval = 0; + size_t num_bytes; + + *end = 0; + *bytes_read = 0; + if (length == 0) + return 0; + + clear_bit(DEV_CLEAR_BN, &priv->state); + + // transfer data (except for last byte) + if (length > 1) { + if (priv->eos_flags & REOS) + tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL); + else + tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_EOI); + // PIO transfer + retval = pio_read(board, priv, buffer, length - 1, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + return retval; + buffer += num_bytes; + length -= num_bytes; + } + // read last bytes if we havn't received an END yet + if (*end == 0) { + // make sure we holdoff after last byte read + tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL); + retval = pio_read(board, priv, buffer, length, end, &num_bytes); + *bytes_read += num_bytes; + if (retval < 0) + return retval; + } + return 0; +} +EXPORT_SYMBOL(tms9914_read); + +static int pio_write_wait(gpib_board_t *board, struct tms9914_priv *priv) +{ + // wait until next byte is ready to be sent + if (wait_event_interruptible(board->wait, + test_bit(WRITE_READY_BN, &priv->state) || + test_bit(BUS_ERROR_BN, &priv->state) || + test_bit(DEV_CLEAR_BN, &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted!\n"); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + return -ETIMEDOUT; + if (test_bit(BUS_ERROR_BN, &priv->state)) + return -EIO; + if (test_bit(DEV_CLEAR_BN, &priv->state)) + return -EINTR; + + return 0; +} + +static int pio_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, size_t *bytes_written) +{ + ssize_t retval = 0; + unsigned long flags; + + *bytes_written = 0; + while (*bytes_written < length) { + retval = pio_write_wait(board, priv); + if (retval < 0) + break; + + spin_lock_irqsave(&board->spinlock, flags); + clear_bit(WRITE_READY_BN, &priv->state); + write_byte(priv, buffer[(*bytes_written)++], CDOR); + spin_unlock_irqrestore(&board->spinlock, flags); + } + retval = pio_write_wait(board, priv); + if (retval < 0) + return retval; + + return length; +} + +int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written) +{ + ssize_t retval = 0; + + *bytes_written = 0; + if (length == 0) + return 0; + + clear_bit(BUS_ERROR_BN, &priv->state); + clear_bit(DEV_CLEAR_BN, &priv->state); + + if (send_eoi) + length-- ; /* save the last byte for sending EOI */ + + if (length > 0) { + size_t num_bytes; + // PIO transfer + retval = pio_write(board, priv, buffer, length, &num_bytes); + *bytes_written += num_bytes; + if (retval < 0) + return retval; + } + if (send_eoi) { + size_t num_bytes; + /*send EOI */ + write_byte(priv, AUX_SEOI, AUXCR); + + retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes); + *bytes_written += num_bytes; + } + return retval; +} +EXPORT_SYMBOL(tms9914_write); + +static void check_my_address_state(gpib_board_t *board, struct tms9914_priv *priv, int cmd_byte) +{ + if (cmd_byte == MLA(board->pad)) { + priv->primary_listen_addressed = 1; + // become active listener + if (board->sad < 0) + write_byte(priv, AUX_LON | AUX_CS, AUXCR); + } else if (board->sad >= 0 && priv->primary_listen_addressed && + cmd_byte == MSA(board->sad)) { + // become active listener + write_byte(priv, AUX_LON | AUX_CS, AUXCR); + } else if (cmd_byte != MLA(board->pad) && (cmd_byte & 0xe0) == LAD) { + priv->primary_listen_addressed = 0; + } else if (cmd_byte == UNL) { + priv->primary_listen_addressed = 0; + write_byte(priv, AUX_LON, AUXCR); + } else if (cmd_byte == MTA(board->pad)) { + priv->primary_talk_addressed = 1; + if (board->sad < 0) + //make active talker + write_byte(priv, AUX_TON | AUX_CS, AUXCR); + } else if (board->sad >= 0 && priv->primary_talk_addressed && + cmd_byte == MSA(board->sad)) { + // become active talker + write_byte(priv, AUX_TON | AUX_CS, AUXCR); + } else if (cmd_byte != MTA(board->pad) && (cmd_byte & 0xe0) == TAD) { + // Other Talk Address + priv->primary_talk_addressed = 0; + write_byte(priv, AUX_TON, AUXCR); + } else if (cmd_byte == UNT) { + priv->primary_talk_addressed = 0; + write_byte(priv, AUX_TON, AUXCR); + } +} + +int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, + size_t length, size_t *bytes_written) +{ + int retval = 0; + unsigned long flags; + + *bytes_written = 0; + while (*bytes_written < length) { + if (wait_event_interruptible(board->wait, + test_bit(COMMAND_READY_BN, + &priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_debug("gpib command wait interrupted\n"); + break; + } + if (test_bit(TIMO_NUM, &board->status)) + break; + + spin_lock_irqsave(&board->spinlock, flags); + clear_bit(COMMAND_READY_BN, &priv->state); + write_byte(priv, buffer[*bytes_written], CDOR); + spin_unlock_irqrestore(&board->spinlock, flags); + + check_my_address_state(board, priv, buffer[*bytes_written]); + + ++(*bytes_written); + } + // wait until last command byte is written + if (wait_event_interruptible(board->wait, + test_bit(COMMAND_READY_BN, + &priv->state) || test_bit(TIMO_NUM, &board->status))) + retval = -ERESTARTSYS; + if (test_bit(TIMO_NUM, &board->status)) + retval = -ETIMEDOUT; + + return retval; +} +EXPORT_SYMBOL(tms9914_command); + +irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv) +{ + int status0, status1; + + // read interrupt status (also clears status) + status0 = read_byte(priv, ISR0); + status1 = read_byte(priv, ISR1); + return tms9914_interrupt_have_status(board, priv, status0, status1); +} +EXPORT_SYMBOL(tms9914_interrupt); + +irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv, + int status0, int status1) +{ + // record reception of END + if (status0 & HR_END) + set_bit(RECEIVED_END_BN, &priv->state); + // get incoming data in PIO mode + if ((status0 & HR_BI)) + set_bit(READ_READY_BN, &priv->state); + if ((status0 & HR_BO)) { + if (read_byte(priv, ADSR) & HR_ATN) + set_bit(COMMAND_READY_BN, &priv->state); + else + set_bit(WRITE_READY_BN, &priv->state); + } + + if (status0 & HR_SPAS) { + priv->spoll_status &= ~request_service_bit; + write_byte(priv, priv->spoll_status, SPMR); + //FIXME: set SPOLL status bit + } + // record service request in status + if (status1 & HR_SRQ) + set_bit(SRQI_NUM, &board->status); + // have been addressed (with secondary addressing disabled) + if (status1 & HR_MA) + // clear dac holdoff + write_byte(priv, AUX_VAL, AUXCR); + // unrecognized command received + if (status1 & HR_UNC) { + unsigned short command_byte = read_byte(priv, CPTR) & gpib_command_mask; + + switch (command_byte) { + case PPConfig: + priv->ppoll_configure_state = 1; + /* AUX_PTS generates another UNC interrupt on the next command byte + * if it is in the secondary address group (such as PPE and PPD). + */ + write_byte(priv, AUX_PTS, AUXCR); + write_byte(priv, AUX_VAL, AUXCR); + break; + case PPU: + tms9914_parallel_poll_configure(board, priv, command_byte); + write_byte(priv, AUX_VAL, AUXCR); + break; + default: + if (is_PPE(command_byte) || is_PPD(command_byte)) { + if (priv->ppoll_configure_state) { + tms9914_parallel_poll_configure(board, priv, command_byte); + write_byte(priv, AUX_VAL, AUXCR); + } else {// bad parallel poll configure byte + // clear dac holdoff + write_byte(priv, AUX_INVAL, AUXCR); + } + } else { + // printk("tms9914: unrecognized gpib command pass thru 0x%x\n", + // command_byte); + // clear dac holdoff + write_byte(priv, AUX_INVAL, AUXCR); + } + break; + } + + if (in_primary_command_group(command_byte) && command_byte != PPConfig) + priv->ppoll_configure_state = 0; + } + + if (status1 & HR_ERR) { + dev_dbg(board->gpib_dev, "gpib bus error\n"); + set_bit(BUS_ERROR_BN, &priv->state); + } + + if (status1 & HR_IFC) { + push_gpib_event(board, EventIFC); + clear_bit(CIC_NUM, &board->status); + } + + if (status1 & HR_GET) { + push_gpib_event(board, EventDevTrg); + // clear dac holdoff + write_byte(priv, AUX_VAL, AUXCR); + } + + if (status1 & HR_DCAS) { + push_gpib_event(board, EventDevClr); + // clear dac holdoff + write_byte(priv, AUX_VAL, AUXCR); + set_bit(DEV_CLEAR_BN, &priv->state); + } + + // check for being addressed with secondary addressing + if (status1 & HR_APT) { + if (board->sad < 0) + pr_err("tms9914: bug, APT interrupt without secondary addressing?\n"); + if ((read_byte(priv, CPTR) & gpib_command_mask) == MSA(board->sad)) + write_byte(priv, AUX_VAL, AUXCR); + else + write_byte(priv, AUX_INVAL, AUXCR); + } + + if ((status0 & priv->imr0_bits) || (status1 & priv->imr1_bits)) { +// dev_dbg(board->gpib_dev, "isr0 0x%x, imr0 0x%x, isr1 0x%x, imr1 0x%x\n", +// status0, priv->imr0_bits, status1, priv->imr1_bits); + update_status_nolock(board, priv); + wake_up_interruptible(&board->wait); + } + return IRQ_HANDLED; +} +EXPORT_SYMBOL(tms9914_interrupt_have_status); + +void tms9914_board_reset(struct tms9914_priv *priv) +{ + /* chip reset */ + write_byte(priv, AUX_CHIP_RESET | AUX_CS, AUXCR); + + /* disable all interrupts */ + priv->imr0_bits = 0; + write_byte(priv, priv->imr0_bits, IMR0); + priv->imr1_bits = 0; + write_byte(priv, priv->imr1_bits, IMR1); + write_byte(priv, AUX_DAI | AUX_CS, AUXCR); + + /* clear registers by reading */ + read_byte(priv, CPTR); + read_byte(priv, ISR0); + read_byte(priv, ISR1); + + write_byte(priv, 0, SPMR); + + /* parallel poll unconfigure */ + write_byte(priv, 0, PPR); + // request for data holdoff + tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL); +} +EXPORT_SYMBOL_GPL(tms9914_board_reset); + +void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv) +{ + /* set GPIB address */ + tms9914_primary_address(board, priv, board->pad); + tms9914_secondary_address(board, priv, board->sad, board->sad >= 0); + + // enable tms9914 interrupts + priv->imr0_bits |= HR_MACIE | HR_RLCIE | HR_ENDIE | HR_BOIE | HR_BIIE | + HR_SPASIE; + priv->imr1_bits |= HR_MAIE | HR_SRQIE | HR_UNCIE | HR_ERRIE | HR_IFCIE | + HR_GETIE | HR_DCASIE; + write_byte(priv, priv->imr0_bits, IMR0); + write_byte(priv, priv->imr1_bits, IMR1); + write_byte(priv, AUX_DAI, AUXCR); + + // turn off reset state + write_byte(priv, AUX_CHIP_RESET, AUXCR); +} +EXPORT_SYMBOL_GPL(tms9914_online); + +#ifdef CONFIG_HAS_IOPORT +// wrapper for inb +uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num) +{ + return inb((unsigned long)(priv->iobase) + register_num * priv->offset); +} +EXPORT_SYMBOL_GPL(tms9914_ioport_read_byte); + +// wrapper for outb +void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num) +{ + outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset); + if (register_num == AUXCR) + udelay(1); +} +EXPORT_SYMBOL_GPL(tms9914_ioport_write_byte); +#endif + +// wrapper for readb +uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num) +{ + return readb(priv->iobase + register_num * priv->offset); +} +EXPORT_SYMBOL_GPL(tms9914_iomem_read_byte); + +// wrapper for writeb +void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num) +{ + writeb(data, priv->iobase + register_num * priv->offset); + if (register_num == AUXCR) + udelay(1); +} +EXPORT_SYMBOL_GPL(tms9914_iomem_write_byte); + +static int __init tms9914_init_module(void) +{ + return 0; +} + +static void __exit tms9914_exit_module(void) +{ +} + +module_init(tms9914_init_module); +module_exit(tms9914_exit_module); + diff --git a/drivers/staging/gpib/tnt4882/Makefile b/drivers/staging/gpib/tnt4882/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f767c990db7a09e0fdac2a9c12ace2dcf4bbacb7 --- /dev/null +++ b/drivers/staging/gpib/tnt4882/Makefile @@ -0,0 +1,7 @@ +ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA +obj-m += tnt4882.o + +tnt4882-objs := tnt4882_gpib.o mite.o + + + diff --git a/drivers/staging/gpib/tnt4882/mite.c b/drivers/staging/gpib/tnt4882/mite.c new file mode 100644 index 0000000000000000000000000000000000000000..0edf34d243e9e897806bfc2b575b14dc98dda97d --- /dev/null +++ b/drivers/staging/gpib/tnt4882/mite.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2 + +/* + * Hardware driver for NI Mite PCI interface chip, + * adapted from COMEDI + * + * Copyright (C) 1997-8 David A. Schleef + * Copyright (C) 2002 Frank Mori Hess + * + * The PCI-MIO E series driver was originally written by + * Tomasz Motylewski <...>, and ported to comedi by ds. + * + * References for specifications: + * + * 321747b.pdf Register Level Programmer Manual (obsolete) + * 321747c.pdf Register Level Programmer Manual (new) + * DAQ-STC reference manual + * + * Other possibly relevant info: + * + * 320517c.pdf User manual (obsolete) + * 320517f.pdf User manual (new) + * 320889a.pdf delete + * 320906c.pdf maximum signal ratings + * 321066a.pdf about 16x + * 321791a.pdf discontinuation of at-mio-16e-10 rev. c + * 321808a.pdf about at-mio-16e-10 rev P + * 321837a.pdf discontinuation of at-mio-16de-10 rev d + * 321838a.pdf about at-mio-16de-10 rev N + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/io.h> +#include <linux/slab.h> + +#include "mite.h" + +#define PCI_MITE_SIZE 4096 +#define PCI_DAQ_SIZE 4096 + +struct mite_struct *mite_devices; + +#define TOP_OF_PAGE(x) ((x) | (~(PAGE_MASK))) + +void mite_init(void) +{ + struct pci_dev *pcidev; + struct mite_struct *mite; + + for (pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, NULL); + pcidev; + pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, pcidev)) { + mite = kzalloc(sizeof(*mite), GFP_KERNEL); + if (!mite) + return; + + mite->pcidev = pcidev; + pci_dev_get(mite->pcidev); + mite->next = mite_devices; + mite_devices = mite; + } +} + +int mite_setup(struct mite_struct *mite) +{ + u32 addr; + + if (pci_enable_device(mite->pcidev)) { + pr_err("mite: error enabling mite.\n"); + return -EIO; + } + pci_set_master(mite->pcidev); + if (pci_request_regions(mite->pcidev, "mite")) { + pr_err("mite: failed to request mite io regions.\n"); + return -EIO; + } + addr = pci_resource_start(mite->pcidev, 0); + mite->mite_phys_addr = addr; + mite->mite_io_addr = ioremap(addr, pci_resource_len(mite->pcidev, 0)); + if (!mite->mite_io_addr) { + pr_err("mite: failed to remap mite io memory address.\n"); + return -ENOMEM; + } + pr_info("mite: 0x%08lx mapped to %p\n", mite->mite_phys_addr, mite->mite_io_addr); + addr = pci_resource_start(mite->pcidev, 1); + mite->daq_phys_addr = addr; + mite->daq_io_addr = ioremap(mite->daq_phys_addr, pci_resource_len(mite->pcidev, 1)); + if (!mite->daq_io_addr) { + pr_err("mite: failed to remap daq io memory address.\n"); + return -ENOMEM; + } + pr_info("mite: daq: 0x%08lx mapped to %p\n", mite->daq_phys_addr, mite->daq_io_addr); + writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR); + mite->used = 1; + return 0; +} + +void mite_cleanup(void) +{ + struct mite_struct *mite, *next; + + for (mite = mite_devices; mite; mite = next) { + next = mite->next; + if (mite->pcidev) + pci_dev_put(mite->pcidev); + kfree(mite); + } +} + +void mite_unsetup(struct mite_struct *mite) +{ + if (!mite) + return; + if (mite->mite_io_addr) { + iounmap(mite->mite_io_addr); + mite->mite_io_addr = NULL; + } + if (mite->daq_io_addr) { + iounmap(mite->daq_io_addr); + mite->daq_io_addr = NULL; + } + if (mite->mite_phys_addr) { + pci_release_regions(mite->pcidev); + pci_disable_device(mite->pcidev); + mite->mite_phys_addr = 0; + } + mite->used = 0; +} + +void mite_list_devices(void) +{ + struct mite_struct *mite, *next; + + pr_info("Available NI PCI device IDs:"); + if (mite_devices) + for (mite = mite_devices; mite; mite = next) { + next = mite->next; + pr_info(" 0x%04x", mite_device_id(mite)); + if (mite->used) + pr_info("(used)"); + } + pr_info("\n"); +} + +int mite_bytes_transferred(struct mite_struct *mite, int chan) +{ + int dar, fcr; + + dar = readl(mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(chan)); + fcr = readl(mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(chan)) & 0x000000FF; + return dar - fcr; +} + +int mite_dma_tcr(struct mite_struct *mite) +{ + int tcr; + int lkar; + + lkar = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_LKAR); + tcr = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_TCR); + MDPRINTK("lkar=0x%08x tcr=%d\n", lkar, tcr); + + return tcr; +} + +void mite_dma_disarm(struct mite_struct *mite) +{ + int chor; + + /* disarm */ + chor = CHOR_ABORT; + writel(chor, mite->mite_io_addr + CHAN_OFFSET(0) + MITE_CHOR); +} + +void mite_dump_regs(struct mite_struct *mite) +{ + void *addr = 0; + unsigned long temp = 0; + + pr_info("mite address is =0x%p\n", mite->mite_io_addr); + + addr = mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(0); + pr_info("mite status[CHOR]at 0x%p =0x%08lx\n", addr, temp = readl(addr)); + //mite_decode(mite_CHOR_strings,temp); + addr = mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(0); + pr_info("mite status[CHCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr)); + //mite_decode(mite_CHCR_strings,temp); + addr = mite->mite_io_addr + MITE_TCR + CHAN_OFFSET(0); + pr_info("mite status[TCR] at 0x%p =0x%08x\n", addr, readl(addr)); + addr = mite->mite_io_addr + MITE_MCR + CHAN_OFFSET(0); + pr_info("mite status[MCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr)); + //mite_decode(mite_MCR_strings,temp); + addr = mite->mite_io_addr + MITE_MAR + CHAN_OFFSET(0); + pr_info("mite status[MAR] at 0x%p =0x%08x\n", addr, readl(addr)); + addr = mite->mite_io_addr + MITE_DCR + CHAN_OFFSET(0); + pr_info("mite status[DCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr)); + //mite_decode(mite_CR_strings,temp); + addr = mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(0); + pr_info("mite status[DAR] at 0x%p =0x%08x\n", addr, readl(addr)); + addr = mite->mite_io_addr + MITE_LKCR + CHAN_OFFSET(0); + pr_info("mite status[LKCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr)); + //mite_decode(mite_CR_strings,temp); + addr = mite->mite_io_addr + MITE_LKAR + CHAN_OFFSET(0); + pr_info("mite status[LKAR]at 0x%p =0x%08x\n", addr, readl(addr)); + + addr = mite->mite_io_addr + MITE_CHSR + CHAN_OFFSET(0); + pr_info("mite status[CHSR]at 0x%p =0x%08lx\n", addr, temp = readl(addr)); + //mite_decode(mite_CHSR_strings,temp); + addr = mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(0); + pr_info("mite status[FCR] at 0x%p =0x%08x\n\n", addr, readl(addr)); +} + diff --git a/drivers/staging/gpib/tnt4882/mite.h b/drivers/staging/gpib/tnt4882/mite.h new file mode 100644 index 0000000000000000000000000000000000000000..6454d069b8cc4e3d3519d492e9fc537fc14f4478 --- /dev/null +++ b/drivers/staging/gpib/tnt4882/mite.h @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: GPL-2 */ + +/* + * Hardware driver for NI Mite PCI interface chip + * + * Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov> + */ + +#ifndef _MITE_H_ +#define _MITE_H_ + +#include <linux/pci.h> + +#define PCI_VENDOR_ID_NATINST 0x1093 + +//#define DEBUG_MITE + +#ifdef DEBUG_MITE +#define MDPRINTK(format, args...) pr_debug(format, ## args) +#else +#define MDPRINTK(args...) +#endif + +#define MITE_RING_SIZE 3000 +struct mite_dma_chain { + u32 count; + u32 addr; + u32 next; +}; + +struct mite_struct { + struct mite_struct *next; + int used; + + struct pci_dev *pcidev; + unsigned long mite_phys_addr; + void *mite_io_addr; + unsigned long daq_phys_addr; + void *daq_io_addr; + + int DMA_CheckNearEnd; + + struct mite_dma_chain ring[MITE_RING_SIZE]; +}; + +extern struct mite_struct *mite_devices; + +extern inline unsigned int mite_irq(struct mite_struct *mite) +{ + return mite->pcidev->irq; +}; + +extern inline unsigned int mite_device_id(struct mite_struct *mite) +{ + return mite->pcidev->device; +}; + +void mite_init(void); +void mite_cleanup(void); +int mite_setup(struct mite_struct *mite); +void mite_unsetup(struct mite_struct *mite); +void mite_list_devices(void); + +int mite_dma_tcr(struct mite_struct *mite); + +void mite_dma_arm(struct mite_struct *mite); +void mite_dma_disarm(struct mite_struct *mite); + +void mite_dump_regs(struct mite_struct *mite); +void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, int dir); +int mite_bytes_transferred(struct mite_struct *mite, int chan); + +#define CHAN_OFFSET(x) (0x100 * (x)) + +/* DMA base for chan 0 is 0x500, chan 1 is 0x600 */ + +#define MITE_CHOR 0x500 +#define CHOR_DMARESET BIT(31) +#define CHOR_SET_SEND_TC BIT(11) +#define CHOR_CLR_SEND_TC BIT(10) +#define CHOR_SET_LPAUSE BIT(9) +#define CHOR_CLR_LPAUSE BIT(8) +#define CHOR_CLRDONE BIT(7) +#define CHOR_CLRRB BIT(6) +#define CHOR_CLRLC BIT(5) +#define CHOR_FRESET BIT(4) +#define CHOR_ABORT BIT(3) +#define CHOR_STOP BIT(2) +#define CHOR_CONT BIT(1) +#define CHOR_START BIT(0) +#define CHOR_PON (CHOR_CLR_SEND_TC | CHOR_CLR_LPAUSE) + +#define MITE_CHCR 0x504 +#define CHCR_SET_DMA_IE BIT(31) +#define CHCR_CLR_DMA_IE BIT(30) +#define CHCR_SET_LINKP_IE BIT(29) +#define CHCR_CLR_LINKP_IE BIT(28) +#define CHCR_SET_SAR_IE BIT(27) +#define CHCR_CLR_SAR_IE BIT(26) +#define CHCR_SET_DONE_IE BIT(25) +#define CHCR_CLR_DONE_IE BIT(24) +#define CHCR_SET_MRDY_IE BIT(23) +#define CHCR_CLR_MRDY_IE BIT(22) +#define CHCR_SET_DRDY_IE BIT(21) +#define CHCR_CLR_DRDY_IE BIT(20) +#define CHCR_SET_LC_IE BIT(19) +#define CHCR_CLR_LC_IE BIT(18) +#define CHCR_SET_CONT_RB_IE BIT(17) +#define CHCR_CLR_CONT_RB_IE BIT(16) +#define CHCR_FIFODIS BIT(15) +#define CHCR_FIFO_ON 0 +#define CHCR_BURSTEN BIT(14) +#define CHCR_NO_BURSTEN 0 +#define CHCR_NFTP(x) ((x) << 11) +#define CHCR_NFTP0 CHCR_NFTP(0) +#define CHCR_NFTP1 CHCR_NFTP(1) +#define CHCR_NFTP2 CHCR_NFTP(2) +#define CHCR_NFTP4 CHCR_NFTP(3) +#define CHCR_NFTP8 CHCR_NFTP(4) +#define CHCR_NFTP16 CHCR_NFTP(5) +#define CHCR_NETP(x) ((x) << 11) +#define CHCR_NETP0 CHCR_NETP(0) +#define CHCR_NETP1 CHCR_NETP(1) +#define CHCR_NETP2 CHCR_NETP(2) +#define CHCR_NETP4 CHCR_NETP(3) +#define CHCR_NETP8 CHCR_NETP(4) +#define CHCR_CHEND1 BIT(5) +#define CHCR_CHEND0 BIT(4) +#define CHCR_DIR BIT(3) +#define CHCR_DEV_TO_MEM CHCR_DIR +#define CHCR_MEM_TO_DEV 0 +#define CHCR_NORMAL ((0) << 0) +#define CHCR_CONTINUE ((1) << 0) +#define CHCR_RINGBUFF ((2) << 0) +#define CHCR_LINKSHORT ((4) << 0) +#define CHCR_LINKLONG ((5) << 0) +#define CHCRPON (CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | \ + CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | \ + CHCR_CLR_LC_IE | CHCR_CLR_CONT_IE) + +#define MITE_TCR 0x508 + +/* CR bits */ +#define CR_RL(x) ((x) << 21) +#define CR_RL0 CR_RL(0) +#define CR_RL1 CR_RL(1) +#define CR_RL2 CR_RL(2) +#define CR_RL4 CR_RL(3) +#define CR_RL8 CR_RL(4) +#define CR_RL16 CR_RL(5) +#define CR_RL32 CR_RL(6) +#define CR_RL64 CR_RL(7) +#define CR_RD(x) ((x) << 19) +#define CR_RD0 CR_RD(0) +#define CR_RD32 CR_RD(1) +#define CR_RD512 CR_RD(2) +#define CR_RD8192 CR_RD(3) +#define CR_REQS(x) ((x) << 16) +#define CR_REQSDRQ0 CR_REQS(4) +#define CR_REQSDRQ1 CR_REQS(5) +#define CR_REQSDRQ2 CR_REQS(6) +#define CR_REQSDRQ3 CR_REQS(7) +#define CR_ASEQX(x) ((x) << 10) +#define CR_ASEQX0 CR_ASEQX(0) +#define CR_ASEQDONT CR_ASEQX0 +#define CR_ASEQXP1 CR_ASEQX(1) +#define CR_ASEQUP CR_ASEQXP1 +#define CR_ASEQXP2 CR_ASEQX(2) +#define CR_ASEQDOWN CR_ASEQXP2 +#define CR_ASEQXP4 CR_ASEQX(3) +#define CR_ASEQXP8 CR_ASEQX(4) +#define CR_ASEQXP16 CR_ASEQX(5) +#define CR_ASEQXP32 CR_ASEQX(6) +#define CR_ASEQXP64 CR_ASEQX(7) +#define CR_ASEQXM1 CR_ASEQX(9) +#define CR_ASEQXM2 CR_ASEQX(10) +#define CR_ASEQXM4 CR_ASEQX(11) +#define CR_ASEQXM8 CR_ASEQX(12) +#define CR_ASEQXM16 CR_ASEQX(13) +#define CR_ASEQXM32 CR_ASEQX(14) +#define CR_ASEQXM64 CR_ASEQX(15) +#define CR_PSIZEBYTE BIT(8) +#define CR_PSIZEHALF (2 << 8) +#define CR_PSIZEWORD (3 << 8) +#define CR_PORTCPU (0 << 6) +#define CR_PORTIO BIT(6) +#define CR_PORTVXI (2 << 6) +#define CR_PORTMXI (3 << 6) +#define CR_AMDEVICE BIT(0) + +#define CHSR_INT 0x80000000 +#define CHSR_DONE 0x02000000 +#define CHSR_LINKC 0x00080000 + +#define MITE_MCR 0x50c +#define MCRPON 0 + +#define MITE_MAR 0x510 + +#define MITE_DCR 0x514 +#define DCR_NORMAL BIT(29) +#define DCRPON 0 + +#define MITE_DAR 0x518 + +#define MITE_LKCR 0x51c + +#define MITE_LKAR 0x520 +#define MITE_LLKAR 0x524 +#define MITE_BAR 0x528 +#define MITE_BCR 0x52c +#define MITE_SAR 0x530 +#define MITE_WSCR 0x534 +#define MITE_WSER 0x538 +#define MITE_CHSR 0x53c +#define MITE_FCR 0x540 + +#define MITE_FIFO 0x80 +#define MITE_FIFOEND 0xff + +#define MITE_AMRAM 0x00 +#define MITE_AMDEVICE 0x01 +#define MITE_AMHOST_A32_SINGLE 0x09 +#define MITE_AMHOST_A24_SINGLE 0x39 +#define MITE_AMHOST_A16_SINGLE 0x29 +#define MITE_AMHOST_A32_BLOCK 0x0b +#define MITE_AMHOST_A32D64_BLOCK 0x08 +#define MITE_AMHOST_A24_BLOCK 0x3b + +enum mite_registers { + MITE_IODWBSR = 0xc0, //IO Device Window Base Size Register + MITE_CSIGR = 0x460, //chip signature + MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1 (used by 6602 boards) + MITE_IODWCR_1 = 0xf4 +}; + +enum MITE_IODWBSR_bits { + WENAB = 0x80, // window enable + WENAB_6602 = 0x8c // window enable for 6602 boards +}; + +#endif + diff --git a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c new file mode 100644 index 0000000000000000000000000000000000000000..e49a952fa0d83829bcec2e98e12f2131d7003db5 --- /dev/null +++ b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c @@ -0,0 +1,1874 @@ +// SPDX-License-Identifier: GPL-2.0 + +/*************************************************************************** + * National Instruments boards using tnt4882 or compatible chips (at-gpib, etc). + * copyright : (C) 2001, 2002 by Frank Mori Hess + ***************************************************************************/ + +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/isapnp.h> + +#include "nec7210.h" +#include "gpibP.h" +#include "mite.h" +#include "tnt4882_registers.h" + +static const int ISAPNP_VENDOR_ID_NI = ISAPNP_VENDOR('N', 'I', 'C'); +static const int ISAPNP_ID_NI_ATGPIB_TNT = 0xc601; +enum { + PCI_DEVICE_ID_NI_GPIB = 0xc801, + PCI_DEVICE_ID_NI_GPIB_PLUS = 0xc811, + PCI_DEVICE_ID_NI_GPIB_PLUS2 = 0x71ad, + PCI_DEVICE_ID_NI_PXIGPIB = 0xc821, + PCI_DEVICE_ID_NI_PMCGPIB = 0xc831, + PCI_DEVICE_ID_NI_PCIEGPIB = 0x70cf, + PCI_DEVICE_ID_NI_PCIE2GPIB = 0x710e, +// Measurement Computing PCI-488 same design as PCI-GPIB with TNT5004 + PCI_DEVICE_ID_MC_PCI488 = 0x7259, + PCI_DEVICE_ID_CEC_NI_GPIB = 0x7258 +}; + +// struct which defines private_data for tnt4882 devices +struct tnt4882_priv { + struct nec7210_priv nec7210_priv; + struct mite_struct *mite; + struct pnp_dev *pnp_dev; + unsigned int irq; + unsigned short imr0_bits; + unsigned short imr3_bits; + unsigned short auxg_bits; // bits written to auxiliary register G + void (*io_writeb)(unsigned int value, void *address); + void (*io_writew)(unsigned int value, void *address); + unsigned int (*io_readb)(void *address); + unsigned int (*io_readw)(void *address); +}; + +// interface functions +static int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read); +static int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, + int *end, size_t *bytes_read); +static int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +static int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, size_t *bytes_written); +static int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length, + size_t *bytes_written); +static int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer, + size_t length, size_t *bytes_written); +static int tnt4882_take_control(gpib_board_t *board, int synchronous); +static int tnt4882_go_to_standby(gpib_board_t *board); +static void tnt4882_request_system_control(gpib_board_t *board, int request_control); +static void tnt4882_interface_clear(gpib_board_t *board, int assert); +static void tnt4882_remote_enable(gpib_board_t *board, int enable); +static int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int + compare_8_bits); +static void tnt4882_disable_eos(gpib_board_t *board); +static unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask); +static int tnt4882_primary_address(gpib_board_t *board, unsigned int address); +static int tnt4882_secondary_address(gpib_board_t *board, unsigned int address, + int enable); +static int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result); +static void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config); +static void tnt4882_parallel_poll_response(gpib_board_t *board, int ist); +static void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status); +static uint8_t tnt4882_serial_poll_status(gpib_board_t *board); +static int tnt4882_line_status(const gpib_board_t *board); +static unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec); +static void tnt4882_return_to_local(gpib_board_t *board); + +// interrupt service routines +static irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board); +static irqreturn_t tnt4882_interrupt(int irq, void *arg); + +// utility functions +static int tnt4882_allocate_private(gpib_board_t *board); +static void tnt4882_free_private(gpib_board_t *board); +static void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board); +static void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board); + +// register offset for nec7210 compatible registers +static const int atgpib_reg_offset = 2; + +// number of ioports used +static const int atgpib_iosize = 32; + +/* paged io */ +static inline unsigned int tnt_paged_readb(struct tnt4882_priv *priv, unsigned long offset) +{ + priv->io_writeb(AUX_PAGEIN, priv->nec7210_priv.iobase + AUXMR * priv->nec7210_priv.offset); + udelay(1); + return priv->io_readb(priv->nec7210_priv.iobase + offset); +} + +static inline void tnt_paged_writeb(struct tnt4882_priv *priv, unsigned int value, + unsigned long offset) +{ + priv->io_writeb(AUX_PAGEIN, priv->nec7210_priv.iobase + AUXMR * priv->nec7210_priv.offset); + udelay(1); + priv->io_writeb(value, priv->nec7210_priv.iobase + offset); +} + +/* readb/writeb wrappers */ +static inline unsigned short tnt_readb(struct tnt4882_priv *priv, unsigned long offset) +{ + void *address = priv->nec7210_priv.iobase + offset; + unsigned long flags; + unsigned short retval; + spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock; + + spin_lock_irqsave(register_lock, flags); + switch (offset) { + case CSR: + case SASR: + case ISR0: + case BSR: + switch (priv->nec7210_priv.type) { + case TNT4882: + case TNT5004: + retval = priv->io_readb(address); + break; + case NAT4882: + retval = tnt_paged_readb(priv, offset - tnt_pagein_offset); + break; + case NEC7210: + retval = 0; + break; + default: + pr_err("tnt4882: bug! unsupported ni_chipset\n"); + retval = 0; + break; + } + break; + default: + retval = priv->io_readb(address); + break; + } + spin_unlock_irqrestore(register_lock, flags); + return retval; +} + +static inline void tnt_writeb(struct tnt4882_priv *priv, unsigned short value, unsigned long offset) +{ + void *address = priv->nec7210_priv.iobase + offset; + unsigned long flags; + spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock; + + spin_lock_irqsave(register_lock, flags); + switch (offset) { + case KEYREG: + case IMR0: + case BCR: + switch (priv->nec7210_priv.type) { + case TNT4882: + case TNT5004: + priv->io_writeb(value, address); + break; + case NAT4882: + tnt_paged_writeb(priv, value, offset - tnt_pagein_offset); + break; + case NEC7210: + break; + default: + pr_err("tnt4882: bug! unsupported ni_chipset\n"); + break; + } + break; + default: + priv->io_writeb(value, address); + break; + } + spin_unlock_irqrestore(register_lock, flags); +} + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIB driver for National Instruments boards using tnt4882 or compatible chips"); + +int tnt4882_line_status(const gpib_board_t *board) +{ + int status = ValidALL; + int bcsr_bits; + struct tnt4882_priv *tnt_priv; + + tnt_priv = board->private_data; + + bcsr_bits = tnt_readb(tnt_priv, BSR); + + if (bcsr_bits & BCSR_REN_BIT) + status |= BusREN; + if (bcsr_bits & BCSR_IFC_BIT) + status |= BusIFC; + if (bcsr_bits & BCSR_SRQ_BIT) + status |= BusSRQ; + if (bcsr_bits & BCSR_EOI_BIT) + status |= BusEOI; + if (bcsr_bits & BCSR_NRFD_BIT) + status |= BusNRFD; + if (bcsr_bits & BCSR_NDAC_BIT) + status |= BusNDAC; + if (bcsr_bits & BCSR_DAV_BIT) + status |= BusDAV; + if (bcsr_bits & BCSR_ATN_BIT) + status |= BusATN; + + return status; +} + +unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + unsigned int retval; + + retval = nec7210_t1_delay(board, nec_priv, nano_sec); + if (nec_priv->type == NEC7210) + return retval; + + if (nano_sec <= 350) { + tnt_writeb(tnt_priv, MSTD, KEYREG); + retval = 350; + } else { + tnt_writeb(tnt_priv, 0, KEYREG); + } + if (nano_sec > 500 && nano_sec <= 1100) { + write_byte(nec_priv, AUXRI | USTD, AUXMR); + retval = 1100; + } else { + write_byte(nec_priv, AUXRI, AUXMR); + } + return retval; +} + +static int fifo_word_available(struct tnt4882_priv *tnt_priv) +{ + int status2; + int retval; + + status2 = tnt_readb(tnt_priv, STS2); + retval = (status2 & AEFN) && (status2 & BEFN); + + return retval; +} + +static int fifo_byte_available(struct tnt4882_priv *tnt_priv) +{ + int status2; + int retval; + + status2 = tnt_readb(tnt_priv, STS2); + retval = (status2 & AEFN) || (status2 & BEFN); + + return retval; +} + +static int fifo_xfer_done(struct tnt4882_priv *tnt_priv) +{ + int status1; + int retval; + + status1 = tnt_readb(tnt_priv, STS1); + retval = status1 & (S_DONE | S_HALT); + + return retval; +} + +static int drain_fifo_words(struct tnt4882_priv *tnt_priv, uint8_t *buffer, int num_bytes) +{ + int count = 0; + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + + while (fifo_word_available(tnt_priv) && count + 2 <= num_bytes) { + short word; + + word = tnt_priv->io_readw(nec_priv->iobase + FIFOB); + buffer[count++] = word & 0xff; + buffer[count++] = (word >> 8) & 0xff; + } + return count; +} + +static void tnt4882_release_holdoff(gpib_board_t *board, struct tnt4882_priv *tnt_priv) +{ + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + unsigned short sasr_bits; + + sasr_bits = tnt_readb(tnt_priv, SASR); + + /*tnt4882 not in one-chip mode won't always release holdoff unless we + * are in the right mode when release handshake command is given + */ + if (sasr_bits & AEHS_BIT) /* holding off due to holdoff on end mode*/ { + nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); + write_byte(nec_priv, AUX_FH, AUXMR); + } else if (sasr_bits & ANHS1_BIT) { /* held off due to holdoff on all data mode*/ + nec7210_set_handshake_mode(board, nec_priv, HR_HLDA); + write_byte(nec_priv, AUX_FH, AUXMR); + nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); + } else { /* held off due to holdoff immediately command */ + nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); + write_byte(nec_priv, AUX_FH, AUXMR); + } +} + +int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, + size_t *bytes_read) +{ + size_t count = 0; + ssize_t retval = 0; + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + unsigned int bits; + s32 hw_count; + unsigned long flags; + + *bytes_read = 0; + // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race + clear_bit(DEV_CLEAR_BN, &nec_priv->state); + clear_bit(ADR_CHANGE_BN, &nec_priv->state); + + nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, HR_ENDIE); + if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004) + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); + else + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + tnt_writeb(tnt_priv, nec_priv->auxa_bits | HR_HLDA, CCR); + bits = TNT_B_16BIT | TNT_IN | TNT_CCEN; + tnt_writeb(tnt_priv, bits, CFG); + tnt_writeb(tnt_priv, RESET_FIFO, CMDR); + udelay(1); + // load 2's complement of count into hardware counters + hw_count = -length; + tnt_writeb(tnt_priv, hw_count & 0xff, CNT0); + tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1); + tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2); + tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3); + + tnt4882_release_holdoff(board, tnt_priv); + + tnt_writeb(tnt_priv, GO, CMDR); + udelay(1); + + spin_lock_irqsave(&board->spinlock, flags); + tnt_priv->imr3_bits |= HR_DONE | HR_NEF; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + spin_unlock_irqrestore(&board->spinlock, flags); + + while (count + 2 <= length && + test_bit(RECEIVED_END_BN, &nec_priv->state) == 0 && + fifo_xfer_done(tnt_priv) == 0) { + // wait until a word is ready + if (wait_event_interruptible(board->wait, + fifo_word_available(tnt_priv) || + fifo_xfer_done(tnt_priv) || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(ADR_CHANGE_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_err("tnt4882: read interrupted\n"); + retval = -ERESTARTSYS; + break; + } + if (test_bit(TIMO_NUM, &board->status)) { + //pr_info("tnt4882: minor %i read timed out\n", board->minor); + retval = -ETIMEDOUT; + break; + } + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { + pr_err("tnt4882: device clear interrupted read\n"); + retval = -EINTR; + break; + } + if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) { + pr_err("tnt4882: address change interrupted read\n"); + retval = -EINTR; + break; + } + + spin_lock_irqsave(&board->spinlock, flags); + count += drain_fifo_words(tnt_priv, &buffer[count], length - count); + tnt_priv->imr3_bits |= HR_NEF; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + spin_unlock_irqrestore(&board->spinlock, flags); + + if (need_resched()) + schedule(); + } + // wait for last byte + if (count < length) { + spin_lock_irqsave(&board->spinlock, flags); + tnt_priv->imr3_bits |= HR_DONE | HR_NEF; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + spin_unlock_irqrestore(&board->spinlock, flags); + + if (wait_event_interruptible(board->wait, + fifo_xfer_done(tnt_priv) || + test_bit(RECEIVED_END_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(ADR_CHANGE_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + pr_err("tnt4882: read interrupted\n"); + retval = -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) + //pr_info("tnt4882: read timed out\n"); + retval = -ETIMEDOUT; + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { + pr_err("tnt4882: device clear interrupted read\n"); + retval = -EINTR; + } + if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) { + pr_err("tnt4882: address change interrupted read\n"); + retval = -EINTR; + } + count += drain_fifo_words(tnt_priv, &buffer[count], length - count); + if (fifo_byte_available(tnt_priv) && count < length) + buffer[count++] = tnt_readb(tnt_priv, FIFOB); + } + if (count < length) + tnt_writeb(tnt_priv, STOP, CMDR); + udelay(1); + + nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, 0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); + /* force handling of any pending interrupts (seems to be needed + * to keep interrupts from getting hosed, plus for syncing + * with RECEIVED_END below) + */ + tnt4882_internal_interrupt(board); + /* RECEIVED_END should be in sync now */ + if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) + *end = 1; + if (retval < 0) { + // force immediate holdoff + write_byte(nec_priv, AUX_HLDI, AUXMR); + + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + } + *bytes_read = count; + + return retval; +} + +static int fifo_space_available(struct tnt4882_priv *tnt_priv) +{ + int status2; + int retval; + + status2 = tnt_readb(tnt_priv, STS2); + retval = (status2 & AFFN) && (status2 & BFFN); + + return retval; +} + +static unsigned int tnt_transfer_count(struct tnt4882_priv *tnt_priv) +{ + unsigned int count = 0; + + count |= tnt_readb(tnt_priv, CNT0) & 0xff; + count |= (tnt_readb(tnt_priv, CNT1) << 8) & 0xff00; + count |= (tnt_readb(tnt_priv, CNT2) << 16) & 0xff0000; + count |= (tnt_readb(tnt_priv, CNT3) << 24) & 0xff000000; + // return two's complement + return -count; +}; + +static int write_wait(gpib_board_t *board, struct tnt4882_priv *tnt_priv, + int wait_for_done, int send_commands) +{ + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + + if (wait_event_interruptible(board->wait, + (!wait_for_done && fifo_space_available(tnt_priv)) || + fifo_xfer_done(tnt_priv) || + test_bit(BUS_ERROR_BN, &nec_priv->state) || + test_bit(DEV_CLEAR_BN, &nec_priv->state) || + test_bit(TIMO_NUM, &board->status))) { + dev_dbg(board->gpib_dev, "gpib write interrupted\n"); + return -ERESTARTSYS; + } + if (test_bit(TIMO_NUM, &board->status)) { + pr_info("tnt4882: write timed out\n"); + return -ETIMEDOUT; + } + if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) { + pr_err("tnt4882: write bus error\n"); + return (send_commands) ? -ENOTCONN : -ECOMM; + } + if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { + pr_err("tnt4882: device clear interrupted write\n"); + return -EINTR; + } + return 0; +} + +static int generic_write(gpib_board_t *board, uint8_t *buffer, size_t length, + int send_eoi, int send_commands, size_t *bytes_written) +{ + size_t count = 0; + ssize_t retval = 0; + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + unsigned int bits; + s32 hw_count; + unsigned long flags; + + *bytes_written = 0; + // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race + clear_bit(DEV_CLEAR_BN, &nec_priv->state); + + nec7210_set_reg_bits(nec_priv, IMR1, HR_ERRIE, HR_ERRIE); + + if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004) + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); + else + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); + + tnt_writeb(tnt_priv, RESET_FIFO, CMDR); + udelay(1); + + bits = TNT_B_16BIT; + if (send_eoi) { + bits |= TNT_CCEN; + if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004) + tnt_writeb(tnt_priv, AUX_SEOI, CCR); + } + if (send_commands) + bits |= TNT_COMMAND; + tnt_writeb(tnt_priv, bits, CFG); + + // load 2's complement of count into hardware counters + hw_count = -length; + tnt_writeb(tnt_priv, hw_count & 0xff, CNT0); + tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1); + tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2); + tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3); + + tnt_writeb(tnt_priv, GO, CMDR); + udelay(1); + + spin_lock_irqsave(&board->spinlock, flags); + tnt_priv->imr3_bits |= HR_DONE; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + spin_unlock_irqrestore(&board->spinlock, flags); + + while (count < length) { + // wait until byte is ready to be sent + retval = write_wait(board, tnt_priv, 0, send_commands); + if (retval < 0) + break; + if (fifo_xfer_done(tnt_priv)) + break; + spin_lock_irqsave(&board->spinlock, flags); + while (fifo_space_available(tnt_priv) && count < length) { + u16 word; + + word = buffer[count++] & 0xff; + if (count < length) + word |= (buffer[count++] << 8) & 0xff00; + tnt_priv->io_writew(word, nec_priv->iobase + FIFOB); + } +// avoid unnecessary HR_NFF interrupts +// tnt_priv->imr3_bits |= HR_NFF; +// tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + spin_unlock_irqrestore(&board->spinlock, flags); + + if (need_resched()) + schedule(); + } + // wait last byte has been sent + if (retval == 0) + retval = write_wait(board, tnt_priv, 1, send_commands); + + tnt_writeb(tnt_priv, STOP, CMDR); + udelay(1); + + nec7210_set_reg_bits(nec_priv, IMR1, HR_ERR, 0x0); + nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0x0); + /* force handling of any interrupts that happened + * while they were masked (this appears to be needed) + */ + tnt4882_internal_interrupt(board); + *bytes_written = length - tnt_transfer_count(tnt_priv); + return retval; +} + +int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + return generic_write(board, buffer, length, send_eoi, 0, bytes_written); +} + +int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written) +{ + return generic_write(board, buffer, length, 0, 1, bytes_written); +} + +irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board) +{ + struct tnt4882_priv *priv = board->private_data; + int isr0_bits, isr3_bits, imr3_bits; + unsigned long flags; + + spin_lock_irqsave(&board->spinlock, flags); + + nec7210_interrupt(board, &priv->nec7210_priv); + + isr0_bits = tnt_readb(priv, ISR0); + isr3_bits = tnt_readb(priv, ISR3); + imr3_bits = priv->imr3_bits; + + if (isr0_bits & TNT_IFCI_BIT) + push_gpib_event(board, EventIFC); + //XXX don't need this wakeup, one below should do? +// wake_up_interruptible(&board->wait); + + if (isr3_bits & HR_NFF) + priv->imr3_bits &= ~HR_NFF; + if (isr3_bits & HR_NEF) + priv->imr3_bits &= ~HR_NEF; + if (isr3_bits & HR_DONE) + priv->imr3_bits &= ~HR_DONE; + if (isr3_bits & (HR_INTR | HR_TLCI)) { + dev_dbg(board->gpib_dev, "tnt4882: minor %i isr0 0x%x imr0 0x%x isr3 0x%x imr3 0x%x\n", + board->minor, isr0_bits, priv->imr0_bits, isr3_bits, imr3_bits); + tnt_writeb(priv, priv->imr3_bits, IMR3); + wake_up_interruptible(&board->wait); + } + spin_unlock_irqrestore(&board->spinlock, flags); + return IRQ_HANDLED; +} + +irqreturn_t tnt4882_interrupt(int irq, void *arg) +{ + return tnt4882_internal_interrupt(arg); +} + +static int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config); +static int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config); + +static void ni_isa_detach(gpib_board_t *board); +static void ni_pci_detach(gpib_board_t *board); + +#ifdef GPIB_PCMCIA +static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); +static void ni_pcmcia_detach(gpib_board_t *board); +static int init_ni_gpib_cs(void); +static void __exit exit_ni_gpib_cs(void); +#endif + +// wrappers for interface functions +int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read) +{ + struct tnt4882_priv *priv = board->private_data; + struct nec7210_priv *nec_priv = &priv->nec7210_priv; + int retval; + int dummy; + + retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); + + if (retval < 0) { // force immediate holdoff + write_byte(nec_priv, AUX_HLDI, AUXMR); + + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + + nec7210_read_data_in(board, nec_priv, &dummy); + } + return retval; +} + +int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi, + size_t *bytes_written) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); +} + +int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer, + size_t length, size_t *bytes_written) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); +} + +int tnt4882_take_control(gpib_board_t *board, int synchronous) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_take_control(board, &priv->nec7210_priv, synchronous); +} + +int tnt4882_go_to_standby(gpib_board_t *board) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_go_to_standby(board, &priv->nec7210_priv); +} + +void tnt4882_request_system_control(gpib_board_t *board, int request_control) +{ + struct tnt4882_priv *priv = board->private_data; + + if (request_control) { + tnt_writeb(priv, SETSC, CMDR); + udelay(1); + } + nec7210_request_system_control(board, &priv->nec7210_priv, request_control); + if (!request_control) { + tnt_writeb(priv, CLRSC, CMDR); + udelay(1); + } +} + +void tnt4882_interface_clear(gpib_board_t *board, int assert) +{ + struct tnt4882_priv *priv = board->private_data; + + nec7210_interface_clear(board, &priv->nec7210_priv, assert); +} + +void tnt4882_remote_enable(gpib_board_t *board, int enable) +{ + struct tnt4882_priv *priv = board->private_data; + + nec7210_remote_enable(board, &priv->nec7210_priv, enable); +} + +int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); +} + +void tnt4882_disable_eos(gpib_board_t *board) +{ + struct tnt4882_priv *priv = board->private_data; + + nec7210_disable_eos(board, &priv->nec7210_priv); +} + +unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask) +{ + unsigned long flags; + u8 line_status; + unsigned int retval; + struct tnt4882_priv *priv = board->private_data; + + spin_lock_irqsave(&board->spinlock, flags); + board->status &= ~clear_mask; + retval = nec7210_update_status_nolock(board, &priv->nec7210_priv); + /* set / clear SRQ state since it is not cleared by interrupt */ + line_status = tnt_readb(priv, BSR); + if (line_status & BCSR_SRQ_BIT) + set_bit(SRQI_NUM, &board->status); + else + clear_bit(SRQI_NUM, &board->status); + spin_unlock_irqrestore(&board->spinlock, flags); + return board->status; +} + +int tnt4882_primary_address(gpib_board_t *board, unsigned int address) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_primary_address(board, &priv->nec7210_priv, address); +} + +int tnt4882_secondary_address(gpib_board_t *board, unsigned int address, int enable) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); +} + +int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result) + +{ + struct tnt4882_priv *tnt_priv = board->private_data; + + if (tnt_priv->nec7210_priv.type != NEC7210) { + tnt_priv->auxg_bits |= RPP2_BIT; + write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); + udelay(2); //FIXME use parallel poll timeout + *result = read_byte(&tnt_priv->nec7210_priv, CPTR); + tnt_priv->auxg_bits &= ~RPP2_BIT; + write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); + return 0; + } else { + return nec7210_parallel_poll(board, &tnt_priv->nec7210_priv, result); + } +} + +void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config) +{ + struct tnt4882_priv *priv = board->private_data; + + if (priv->nec7210_priv.type == TNT5004) { + /* configure locally */ + write_byte(&priv->nec7210_priv, AUXRI | 0x4, AUXMR); + if (config) + /* set response + clear sense */ + write_byte(&priv->nec7210_priv, PPR | config, AUXMR); + else + /* disable ppoll */ + write_byte(&priv->nec7210_priv, PPR | 0x10, AUXMR); + } else { + nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); + } +} + +void tnt4882_parallel_poll_response(gpib_board_t *board, int ist) +{ + struct tnt4882_priv *priv = board->private_data; + + nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); +} + +/* this is just used by the old nec7210 isa interfaces, the newer + * boards use tnt4882_serial_poll_response2 + */ +void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status) +{ + struct tnt4882_priv *priv = board->private_data; + + nec7210_serial_poll_response(board, &priv->nec7210_priv, status); +} + +static void tnt4882_serial_poll_response2(gpib_board_t *board, uint8_t status, + int new_reason_for_service) +{ + struct tnt4882_priv *priv = board->private_data; + unsigned long flags; + const int MSS = status & request_service_bit; + const int reqt = MSS && new_reason_for_service; + const int reqf = MSS == 0; + + spin_lock_irqsave(&board->spinlock, flags); + if (reqt) { + priv->nec7210_priv.srq_pending = 1; + clear_bit(SPOLL_NUM, &board->status); + } else { + if (reqf) + priv->nec7210_priv.srq_pending = 0; + } + if (reqt) + /* It may seem like a race to issue reqt before updating + * the status byte, but it is not. The chip does not + * issue the reqt until the SPMR is written to at + * a later time. + */ + write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR); + else if (reqf) + write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR); + /* We need to always zero bit 6 of the status byte before writing it to + * the SPMR to insure we are using + * serial poll mode SP1, and not accidentally triggering mode SP3. + */ + write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR); + spin_unlock_irqrestore(&board->spinlock, flags); +} + +uint8_t tnt4882_serial_poll_status(gpib_board_t *board) +{ + struct tnt4882_priv *priv = board->private_data; + + return nec7210_serial_poll_status(board, &priv->nec7210_priv); +} + +void tnt4882_return_to_local(gpib_board_t *board) +{ + struct tnt4882_priv *priv = board->private_data; + + nec7210_return_to_local(board, &priv->nec7210_priv); +} + +gpib_interface_t ni_pci_interface = { +name: "ni_pci", +attach : ni_pci_attach, +detach : ni_pci_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response2 : tnt4882_serial_poll_response2, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_pci_accel_interface = { +name: "ni_pci_accel", +attach : ni_pci_attach, +detach : ni_pci_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response2 : tnt4882_serial_poll_response2, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_isa_interface = { +name: "ni_isa", +attach : ni_tnt_isa_attach, +detach : ni_isa_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response2 : tnt4882_serial_poll_response2, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_nat4882_isa_interface = { +name: "ni_nat4882_isa", +attach : ni_nat4882_isa_attach, +detach : ni_isa_detach, +read : tnt4882_read, +write : tnt4882_write, +command : tnt4882_command_unaccel, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response2 : tnt4882_serial_poll_response2, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_nec_isa_interface = { +name: "ni_nec_isa", +attach : ni_nec_isa_attach, +detach : ni_isa_detach, +read : tnt4882_read, +write : tnt4882_write, +command : tnt4882_command_unaccel, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response : tnt4882_serial_poll_response, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_isa_accel_interface = { +name: "ni_isa_accel", +attach : ni_tnt_isa_attach, +detach : ni_isa_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response2 : tnt4882_serial_poll_response2, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_nat4882_isa_accel_interface = { +name: "ni_nat4882_isa_accel", +attach : ni_nat4882_isa_attach, +detach : ni_isa_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command_unaccel, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response2 : tnt4882_serial_poll_response2, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_nec_isa_accel_interface = { +name: "ni_nec_isa_accel", +attach : ni_nec_isa_attach, +detach : ni_isa_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command_unaccel, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : NULL, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response : tnt4882_serial_poll_response, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +#ifdef GPIB_PCMCIA +gpib_interface_t ni_pcmcia_interface = { +name: "ni_pcmcia", +attach : ni_pcmcia_attach, +detach : ni_pcmcia_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response : tnt4882_serial_poll_response, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; + +gpib_interface_t ni_pcmcia_accel_interface = { +name: "ni_pcmcia_accel", +attach : ni_pcmcia_attach, +detach : ni_pcmcia_detach, +read : tnt4882_accel_read, +write : tnt4882_accel_write, +command : tnt4882_command, +take_control : tnt4882_take_control, +go_to_standby : tnt4882_go_to_standby, +request_system_control : tnt4882_request_system_control, +interface_clear : tnt4882_interface_clear, +remote_enable : tnt4882_remote_enable, +enable_eos : tnt4882_enable_eos, +disable_eos : tnt4882_disable_eos, +parallel_poll : tnt4882_parallel_poll, +parallel_poll_configure : tnt4882_parallel_poll_configure, +parallel_poll_response : tnt4882_parallel_poll_response, +local_parallel_poll_mode : NULL, // XXX +line_status : tnt4882_line_status, +update_status : tnt4882_update_status, +primary_address : tnt4882_primary_address, +secondary_address : tnt4882_secondary_address, +serial_poll_response : tnt4882_serial_poll_response, +serial_poll_status : tnt4882_serial_poll_status, +t1_delay : tnt4882_t1_delay, +return_to_local : tnt4882_return_to_local, +}; +#endif + +void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board) +{ + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + + tnt_priv->imr0_bits = 0; + tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); + tnt_priv->imr3_bits = 0; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + tnt_readb(tnt_priv, IMR0); + tnt_readb(tnt_priv, IMR3); + nec7210_board_reset(nec_priv, board); +} + +int tnt4882_allocate_private(gpib_board_t *board) +{ + struct tnt4882_priv *tnt_priv; + + board->private_data = kmalloc(sizeof(struct tnt4882_priv), GFP_KERNEL); + if (!board->private_data) + return -1; + tnt_priv = board->private_data; + memset(tnt_priv, 0, sizeof(struct tnt4882_priv)); + init_nec7210_private(&tnt_priv->nec7210_priv); + return 0; +} + +void tnt4882_free_private(gpib_board_t *board) +{ + kfree(board->private_data); + board->private_data = NULL; +} + +void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board) +{ + struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; + + /* Turbo488 software reset */ + tnt_writeb(tnt_priv, SOFT_RESET, CMDR); + udelay(1); + + // turn off one-chip mode + tnt_writeb(tnt_priv, NODMA, HSSEL); + tnt_writeb(tnt_priv, 0, ACCWR); + // make sure we are in 7210 mode + tnt_writeb(tnt_priv, AUX_7210, AUXCR); + udelay(1); + // registers might be swapped, so write it to the swapped address too + tnt_writeb(tnt_priv, AUX_7210, SWAPPED_AUXCR); + udelay(1); + // turn on one-chip mode + if (nec_priv->type == TNT4882 || nec_priv->type == TNT5004) + tnt_writeb(tnt_priv, NODMA | TNT_ONE_CHIP_BIT, HSSEL); + else + tnt_writeb(tnt_priv, NODMA, HSSEL); + + nec7210_board_reset(nec_priv, board); + // read-clear isr0 + tnt_readb(tnt_priv, ISR0); + + // enable passing of nat4882 interrupts + tnt_priv->imr3_bits = HR_TLCI; + tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); + + // enable interrupt + tnt_writeb(tnt_priv, 0x1, INTRT); + + // force immediate holdoff + write_byte(&tnt_priv->nec7210_priv, AUX_HLDI, AUXMR); + + set_bit(RFD_HOLDOFF_BN, &nec_priv->state); + + tnt_priv->auxg_bits = AUXRG | NTNL_BIT; + write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); + + nec7210_board_online(nec_priv, board); + // enable interface clear interrupt for event queue + tnt_priv->imr0_bits = TNT_IMR0_ALWAYS_BITS | TNT_ATNI_BIT | TNT_IFCIE_BIT; + tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); +} + +int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct tnt4882_priv *tnt_priv; + struct nec7210_priv *nec_priv; + int isr_flags = IRQF_SHARED; + int retval; + struct mite_struct *mite; + + board->status = 0; + + if (tnt4882_allocate_private(board)) + return -ENOMEM; + tnt_priv = board->private_data; + tnt_priv->io_writeb = writeb_wrapper; + tnt_priv->io_readb = readb_wrapper; + tnt_priv->io_writew = writew_wrapper; + tnt_priv->io_readw = readw_wrapper; + nec_priv = &tnt_priv->nec7210_priv; + nec_priv->type = TNT4882; + nec_priv->read_byte = nec7210_locking_iomem_read_byte; + nec_priv->write_byte = nec7210_locking_iomem_write_byte; + nec_priv->offset = atgpib_reg_offset; + + if (!mite_devices) { + pr_err("no National Instruments PCI boards found\n"); + return -1; + } + + for (mite = mite_devices; mite; mite = mite->next) { + short found_board; + + if (mite->used) + continue; + if (config->pci_bus >= 0 && config->pci_bus != mite->pcidev->bus->number) + continue; + if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(mite->pcidev->devfn)) + continue; + switch (mite_device_id(mite)) { + case PCI_DEVICE_ID_NI_GPIB: + case PCI_DEVICE_ID_NI_GPIB_PLUS: + case PCI_DEVICE_ID_NI_GPIB_PLUS2: + case PCI_DEVICE_ID_NI_PXIGPIB: + case PCI_DEVICE_ID_NI_PMCGPIB: + case PCI_DEVICE_ID_NI_PCIEGPIB: + case PCI_DEVICE_ID_NI_PCIE2GPIB: +// support for Measurement Computing PCI-488 + case PCI_DEVICE_ID_MC_PCI488: + case PCI_DEVICE_ID_CEC_NI_GPIB: + found_board = 1; + break; + default: + found_board = 0; + break; + } + if (found_board) + break; + } + if (!mite) { + pr_err("no NI PCI-GPIB boards found\n"); + return -1; + } + tnt_priv->mite = mite; + retval = mite_setup(tnt_priv->mite); + if (retval < 0) { + pr_err("tnt4882: error setting up mite.\n"); + return retval; + } + + nec_priv->iobase = tnt_priv->mite->daq_io_addr; + + // get irq + if (request_irq(mite_irq(tnt_priv->mite), tnt4882_interrupt, isr_flags, + "ni-pci-gpib", board)) { + pr_err("gpib: can't request IRQ %d\n", mite_irq(tnt_priv->mite)); + return -1; + } + tnt_priv->irq = mite_irq(tnt_priv->mite); + pr_info("tnt4882: irq %i\n", tnt_priv->irq); + + // TNT5004 detection + switch (tnt_readb(tnt_priv, CSR) & 0xf0) { + case 0x30: + nec_priv->type = TNT4882; + pr_info("tnt4882: TNT4882 chipset detected\n"); + break; + case 0x40: + nec_priv->type = TNT5004; + pr_info("tnt4882: TNT5004 chipset detected\n"); + break; + } + tnt4882_init(tnt_priv, board); + + return 0; +} + +void ni_pci_detach(gpib_board_t *board) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (tnt_priv) { + nec_priv = &tnt_priv->nec7210_priv; + + if (nec_priv->iobase) + tnt4882_board_reset(tnt_priv, board); + if (tnt_priv->irq) + free_irq(tnt_priv->irq, board); + if (tnt_priv->mite) + mite_unsetup(tnt_priv->mite); + } + tnt4882_free_private(board); +} + +static int ni_isapnp_find(struct pnp_dev **dev) +{ + *dev = pnp_find_dev(NULL, ISAPNP_VENDOR_ID_NI, + ISAPNP_FUNCTION(ISAPNP_ID_NI_ATGPIB_TNT), NULL); + if (!*dev || !(*dev)->card) { + pr_err("tnt4882: failed to find isapnp board\n"); + return -ENODEV; + } + if (pnp_device_attach(*dev) < 0) { + pr_err("tnt4882: atgpib/tnt board already active, skipping\n"); + return -EBUSY; + } + if (pnp_activate_dev(*dev) < 0) { + pnp_device_detach(*dev); + pr_err("tnt4882: failed to activate() atgpib/tnt, aborting\n"); + return -EAGAIN; + } + if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { + pnp_device_detach(*dev); + pr_err("tnt4882: invalid port or irq for atgpib/tnt, aborting\n"); + return -ENOMEM; + } + return 0; +} + +static int ni_isa_attach_common(gpib_board_t *board, const gpib_board_config_t *config, + enum nec7210_chipset chipset) +{ + struct tnt4882_priv *tnt_priv; + struct nec7210_priv *nec_priv; + int isr_flags = 0; + void *iobase; + int irq; + + board->status = 0; + + if (tnt4882_allocate_private(board)) + return -ENOMEM; + tnt_priv = board->private_data; + tnt_priv->io_writeb = outb_wrapper; + tnt_priv->io_readb = inb_wrapper; + tnt_priv->io_writew = outw_wrapper; + tnt_priv->io_readw = inw_wrapper; + nec_priv = &tnt_priv->nec7210_priv; + nec_priv->type = chipset; + nec_priv->read_byte = nec7210_locking_ioport_read_byte; + nec_priv->write_byte = nec7210_locking_ioport_write_byte; + nec_priv->offset = atgpib_reg_offset; + + // look for plug-n-play board + if (config->ibbase == 0) { + struct pnp_dev *dev; + int retval; + + retval = ni_isapnp_find(&dev); + if (retval < 0) + return retval; + tnt_priv->pnp_dev = dev; + iobase = (void *)(pnp_port_start(dev, 0)); + irq = pnp_irq(dev, 0); + } else { + iobase = config->ibbase; + irq = config->ibirq; + } + // allocate ioports + if (!request_region((unsigned long)(iobase), atgpib_iosize, "atgpib")) { + pr_err("tnt4882: failed to allocate ioports\n"); + return -1; + } + nec_priv->iobase = iobase; + + // get irq + if (request_irq(irq, tnt4882_interrupt, isr_flags, "atgpib", board)) { + pr_err("gpib: can't request IRQ %d\n", irq); + return -1; + } + tnt_priv->irq = irq; + + tnt4882_init(tnt_priv, board); + + return 0; +} + +int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + return ni_isa_attach_common(board, config, TNT4882); +} + +int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + return ni_isa_attach_common(board, config, NAT4882); +} + +int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + return ni_isa_attach_common(board, config, NEC7210); +} + +void ni_isa_detach(gpib_board_t *board) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv; + + if (tnt_priv) { + nec_priv = &tnt_priv->nec7210_priv; + if (nec_priv->iobase) + tnt4882_board_reset(tnt_priv, board); + if (tnt_priv->irq) + free_irq(tnt_priv->irq, board); + if (nec_priv->iobase) + release_region((unsigned long)(nec_priv->iobase), atgpib_iosize); + if (tnt_priv->pnp_dev) + pnp_device_detach(tnt_priv->pnp_dev); + } + tnt4882_free_private(board); +} + +static int tnt4882_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + return 0; +} + +static const struct pci_device_id tnt4882_pci_table[] = { + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS2)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PXIGPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PMCGPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIEGPIB)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIE2GPIB)}, + // support for Measurement Computing PCI-488 + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_MC_PCI488)}, + {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_CEC_NI_GPIB)}, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, tnt4882_pci_table); + +static struct pci_driver tnt4882_pci_driver = { + .name = "tnt4882", + .id_table = tnt4882_pci_table, + .probe = &tnt4882_pci_probe +}; + +static const struct pnp_device_id tnt4882_pnp_table[] = { + {.id = "NICC601"}, + {.id = ""} +}; +MODULE_DEVICE_TABLE(pnp, tnt4882_pnp_table); + +static int __init tnt4882_init_module(void) +{ + int result; + + result = pci_register_driver(&tnt4882_pci_driver); + if (result) { + pr_err("tnt4882: pci_driver_register failed!\n"); + return result; + } + + gpib_register_driver(&ni_isa_interface, THIS_MODULE); + gpib_register_driver(&ni_isa_accel_interface, THIS_MODULE); + gpib_register_driver(&ni_nat4882_isa_interface, THIS_MODULE); + gpib_register_driver(&ni_nat4882_isa_accel_interface, THIS_MODULE); + gpib_register_driver(&ni_nec_isa_interface, THIS_MODULE); + gpib_register_driver(&ni_nec_isa_accel_interface, THIS_MODULE); + gpib_register_driver(&ni_pci_interface, THIS_MODULE); + gpib_register_driver(&ni_pci_accel_interface, THIS_MODULE); +#ifdef GPIB_PCMCIA + gpib_register_driver(&ni_pcmcia_interface, THIS_MODULE); + gpib_register_driver(&ni_pcmcia_accel_interface, THIS_MODULE); + if (init_ni_gpib_cs() < 0) + return -1; +#endif + + mite_init(); + mite_list_devices(); + + return 0; +} + +static void __exit tnt4882_exit_module(void) +{ + gpib_unregister_driver(&ni_isa_interface); + gpib_unregister_driver(&ni_isa_accel_interface); + gpib_unregister_driver(&ni_nat4882_isa_interface); + gpib_unregister_driver(&ni_nat4882_isa_accel_interface); + gpib_unregister_driver(&ni_nec_isa_interface); + gpib_unregister_driver(&ni_nec_isa_accel_interface); + gpib_unregister_driver(&ni_pci_interface); + gpib_unregister_driver(&ni_pci_accel_interface); +#ifdef GPIB_PCMCIA + gpib_unregister_driver(&ni_pcmcia_interface); + gpib_unregister_driver(&ni_pcmcia_accel_interface); + exit_ni_gpib_cs(); +#endif + + mite_cleanup(); + + pci_unregister_driver(&tnt4882_pci_driver); +} + +#ifdef GPIB_PCMCIA + +#include <linux/kernel.h> +#include <linux/moduleparam.h> +#include <linux/ptrace.h> +#include <linux/timer.h> +#include <linux/ioport.h> +#include <linux/io.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/cisreg.h> +#include <pcmcia/ds.h> + +/* + * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + * you do not define PCMCIA_DEBUG at all, all the debug code will be + * left out. If you compile with PCMCIA_DEBUG=0, the debug code will + * be present but disabled -- but it can then be enabled for specific + * modules at load time with a 'pc_debug=#' option to insmod. + */ +#define PCMCIA_DEBUG 1 +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +module_param(pc_debug, int, 0); +#define DEBUG(n, args...) \ + do {if (pc_debug > (n)) \ + pr_debug(args); } \ + while (0) +#else +#define DEBUG(args...) +#endif + +static int ni_gpib_config(struct pcmcia_device *link); +static void ni_gpib_release(struct pcmcia_device *link); +static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config); +static void ni_pcmcia_detach(gpib_board_t *board); + +/* + * A linked list of "instances" of the dummy device. Each actual + * PCMCIA card corresponds to one device instance, and is described + * by one dev_link_t structure (defined in ds.h). + * + * You may not want to use a linked list for this -- for example, the + * memory card driver uses an array of dev_link_t pointers, where minor + * device numbers are used to derive the corresponding array index. + * + * I think this dev_list is obsolete but the pointer is needed to keep + * the module instance for the ni_pcmcia_attach function. + */ + +static struct pcmcia_device *curr_dev; + +struct local_info_t { + struct pcmcia_device *p_dev; + gpib_board_t *dev; + int stop; + struct bus_operations *bus; +}; + +/* + * ni_gpib_probe() creates an "instance" of the driver, allocating + * local data structures for one device. The device is registered + * with Card Services. + */ + +static int ni_gpib_probe(struct pcmcia_device *link) +{ + struct local_info_t *info; + //struct gpib_board_t *dev; + + DEBUG(0, "%s(0x%p)\n", __func__, link); + + /* Allocate space for private device-specific data */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->p_dev = link; + link->priv = info; + + /* + * General socket configuration defaults can go here. In this + * client, we assume very little, and rely on the CIS for almost + * everything. In most clients, many details (i.e., number, sizes, + * and attributes of IO windows) are fixed by the nature of the + * device, and can be hard-wired here. + */ + link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + + /* Register with Card Services */ + curr_dev = link; + return ni_gpib_config(link); +} + +/* + * This deletes a driver "instance". The device is de-registered + * with Card Services. If it has been released, all local data + * structures are freed. Otherwise, the structures will be freed + * when the device is released. + */ +static void ni_gpib_remove(struct pcmcia_device *link) +{ + struct local_info_t *info = link->priv; + //struct gpib_board_t *dev = info->dev; + + DEBUG(0, "%s(%p)\n", __func__, link); + + if (info->dev) + ni_pcmcia_detach(info->dev); + ni_gpib_release(link); + + //free_netdev(dev); + kfree(info); +} + +static int ni_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) +{ + int retval; + + retval = pcmcia_request_io(link); + if (retval != 0) + return retval; + + return 0; +} + +/* + * ni_gpib_config() is scheduled to run after a CARD_INSERTION event + * is received, to configure the PCMCIA socket, and to make the + * device available to the system. + */ +static int ni_gpib_config(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //gpib_board_t *dev = info->dev; + int last_ret; + + DEBUG(0, "%s(0x%p)\n", __func__, link); + + last_ret = pcmcia_loop_config(link, &ni_gpib_config_iteration, NULL); + if (last_ret) { + dev_warn(&link->dev, "no configuration found\n"); + ni_gpib_release(link); + return last_ret; + } + + last_ret = pcmcia_enable_device(link); + if (last_ret) { + ni_gpib_release(link); + return last_ret; + } + return 0; +} /* ni_gpib_config */ + +/* + * After a card is removed, ni_gpib_release() will unregister the + * device, and release the PCMCIA configuration. If the device is + * still open, this will be postponed until it is closed. + */ +static void ni_gpib_release(struct pcmcia_device *link) +{ + DEBUG(0, "%s(0x%p)\n", __func__, link); + pcmcia_disable_device(link); +} /* ni_gpib_release */ + +static int ni_gpib_suspend(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //struct gpib_board_t *dev = info->dev; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + if (link->open) + pr_err("Device still open ???\n"); + //netif_device_detach(dev); + + return 0; +} + +static int ni_gpib_resume(struct pcmcia_device *link) +{ + //struct local_info_t *info = link->priv; + //struct gpib_board_t *dev = info->dev; + DEBUG(0, "%s(0x%p)\n", __func__, link); + + /*if (link->open) { + * ni_gpib_probe(dev); / really? + * printk("Gpib resumed ???\n"); + * //netif_device_attach(dev); + *} + */ + return ni_gpib_config(link); +} + +static struct pcmcia_device_id ni_pcmcia_ids[] = { + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4882), + PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0c71), // NI PCMCIA-GPIB+ + PCMCIA_DEVICE_NULL +}; + +MODULE_DEVICE_TABLE(pcmcia, ni_pcmcia_ids); + +static struct pcmcia_driver ni_gpib_cs_driver = { + .name = "ni_gpib_cs", + .owner = THIS_MODULE, + .drv = { .name = "ni_gpib_cs", }, + .id_table = ni_pcmcia_ids, + .probe = ni_gpib_probe, + .remove = ni_gpib_remove, + .suspend = ni_gpib_suspend, + .resume = ni_gpib_resume, +}; + +int __init init_ni_gpib_cs(void) +{ + return pcmcia_register_driver(&ni_gpib_cs_driver); +} + +void __exit exit_ni_gpib_cs(void) +{ + DEBUG(0, "ni_gpib_cs: unloading\n"); + pcmcia_unregister_driver(&ni_gpib_cs_driver); +} + +static const int pcmcia_gpib_iosize = 32; + +int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config) +{ + struct local_info_t *info; + struct tnt4882_priv *tnt_priv; + struct nec7210_priv *nec_priv; + int isr_flags = IRQF_SHARED; + + DEBUG(0, "%s(0x%p)\n", __func__, board); + + if (!curr_dev) { + pr_err("gpib: no NI PCMCIA board found\n"); + return -1; + } + + info = curr_dev->priv; + info->dev = board; + + board->status = 0; + + if (tnt4882_allocate_private(board)) + return -ENOMEM; + tnt_priv = board->private_data; + tnt_priv->io_writeb = outb_wrapper; + tnt_priv->io_readb = inb_wrapper; + tnt_priv->io_writew = outw_wrapper; + tnt_priv->io_readw = inw_wrapper; + nec_priv = &tnt_priv->nec7210_priv; + nec_priv->type = TNT4882; + nec_priv->read_byte = nec7210_locking_ioport_read_byte; + nec_priv->write_byte = nec7210_locking_ioport_write_byte; + nec_priv->offset = atgpib_reg_offset; + + DEBUG(0, "ioport1 window attributes: 0x%lx\n", curr_dev->resource[0]->flags); + if (request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), + "tnt4882") == 0) { + pr_err("gpib: ioports starting at 0x%lx are already in use\n", + (unsigned long)curr_dev->resource[0]->start); + return -EIO; + } + + nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start; + + // get irq + if (request_irq(curr_dev->irq, tnt4882_interrupt, isr_flags, "tnt4882", board)) { + pr_err("gpib: can't request IRQ %d\n", curr_dev->irq); + return -1; + } + tnt_priv->irq = curr_dev->irq; + + tnt4882_init(tnt_priv, board); + + return 0; +} + +void ni_pcmcia_detach(gpib_board_t *board) +{ + struct tnt4882_priv *tnt_priv = board->private_data; + struct nec7210_priv *nec_priv; + + DEBUG(0, "%s(0x%p)\n", __func__, board); + + if (tnt_priv) { + nec_priv = &tnt_priv->nec7210_priv; + if (tnt_priv->irq) + free_irq(tnt_priv->irq, board); + if (nec_priv->iobase) { + tnt4882_board_reset(tnt_priv, board); + release_region((unsigned long)nec_priv->iobase, pcmcia_gpib_iosize); + } + } + tnt4882_free_private(board); +} + +#endif // GPIB_PCMCIA + +module_init(tnt4882_init_module); +module_exit(tnt4882_exit_module); diff --git a/drivers/staging/gpib/uapi/gpib_ioctl.h b/drivers/staging/gpib/uapi/gpib_ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..6202865278ea7c9bf858d79b2bf2d84e8a662499 --- /dev/null +++ b/drivers/staging/gpib/uapi/gpib_ioctl.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _GPIB_IOCTL_H +#define _GPIB_IOCTL_H + +#include <asm/ioctl.h> +#include <linux/types.h> + +#define GPIB_CODE 160 + +typedef struct { + char name[100]; +} board_type_ioctl_t; + +/* argument for read/write/command ioctls */ +typedef struct { + uint64_t buffer_ptr; + unsigned int requested_transfer_count; + unsigned int completed_transfer_count; + int end; /* end flag return for reads, end io suppression request for cmd*/ + int handle; +} read_write_ioctl_t; + +typedef struct { + unsigned int handle; + unsigned int pad; + int sad; + unsigned is_board : 1; +} open_dev_ioctl_t; + +typedef struct { + unsigned int handle; +} close_dev_ioctl_t; + +typedef struct { + unsigned int pad; + int sad; + uint8_t status_byte; +} serial_poll_ioctl_t; + +typedef struct { + int eos; + int eos_flags; +} eos_ioctl_t; + +typedef struct { + int handle; + int wait_mask; + int clear_mask; + int set_mask; + int ibsta; + int pad; + int sad; + unsigned int usec_timeout; +} wait_ioctl_t; + +typedef struct { + uint64_t init_data_ptr; + int init_data_length; + int online; +} online_ioctl_t; + +typedef struct { + unsigned int num_bytes; + unsigned int pad; + int sad; +} spoll_bytes_ioctl_t; + +typedef struct { + unsigned int pad; + int sad; + int parallel_poll_configuration; + int autopolling; + int is_system_controller; + unsigned int t1_delay; + unsigned ist : 1; + unsigned no_7_bit_eos : 1; +} board_info_ioctl_t; + +typedef struct { + int pci_bus; + int pci_slot; +} select_pci_ioctl_t; + +typedef struct { + uint8_t config; + unsigned set_ist : 1; + unsigned clear_ist : 1; +} ppoll_config_ioctl_t; + +typedef struct { + unsigned int handle; + unsigned int pad; +} pad_ioctl_t; + +typedef struct { + unsigned int handle; + int sad; +} sad_ioctl_t; + +// select a piece of hardware to attach by its sysfs device path +typedef struct { + char device_path[0x1000]; +} select_device_path_ioctl_t; + +typedef short event_ioctl_t; +typedef int rsc_ioctl_t; +typedef unsigned int t1_delay_ioctl_t; +typedef short autospoll_ioctl_t; +typedef short local_ppoll_mode_ioctl_t; + +// update status byte and request service +typedef struct { + uint8_t status_byte; + int new_reason_for_service; +} request_service2_t; + +/* Standard functions. */ +enum gpib_ioctl { + IBRD = _IOWR(GPIB_CODE, 100, read_write_ioctl_t), + IBWRT = _IOWR(GPIB_CODE, 101, read_write_ioctl_t), + IBCMD = _IOWR(GPIB_CODE, 102, read_write_ioctl_t), + IBOPENDEV = _IOWR(GPIB_CODE, 3, open_dev_ioctl_t), + IBCLOSEDEV = _IOW(GPIB_CODE, 4, close_dev_ioctl_t), + IBWAIT = _IOWR(GPIB_CODE, 5, wait_ioctl_t), + IBRPP = _IOWR(GPIB_CODE, 6, uint8_t), + + IBSIC = _IOW(GPIB_CODE, 9, unsigned int), + IBSRE = _IOW(GPIB_CODE, 10, int), + IBGTS = _IO(GPIB_CODE, 11), + IBCAC = _IOW(GPIB_CODE, 12, int), + IBLINES = _IOR(GPIB_CODE, 14, short), + IBPAD = _IOW(GPIB_CODE, 15, pad_ioctl_t), + IBSAD = _IOW(GPIB_CODE, 16, sad_ioctl_t), + IBTMO = _IOW(GPIB_CODE, 17, unsigned int), + IBRSP = _IOWR(GPIB_CODE, 18, serial_poll_ioctl_t), + IBEOS = _IOW(GPIB_CODE, 19, eos_ioctl_t), + IBRSV = _IOW(GPIB_CODE, 20, uint8_t), + CFCBASE = _IOW(GPIB_CODE, 21, uint64_t), + CFCIRQ = _IOW(GPIB_CODE, 22, unsigned int), + CFCDMA = _IOW(GPIB_CODE, 23, unsigned int), + CFCBOARDTYPE = _IOW(GPIB_CODE, 24, board_type_ioctl_t), + + IBMUTEX = _IOW(GPIB_CODE, 26, int), + IBSPOLL_BYTES = _IOWR(GPIB_CODE, 27, spoll_bytes_ioctl_t), + IBPPC = _IOW(GPIB_CODE, 28, ppoll_config_ioctl_t), + IBBOARD_INFO = _IOR(GPIB_CODE, 29, board_info_ioctl_t), + + IBQUERY_BOARD_RSV = _IOR(GPIB_CODE, 31, int), + IBSELECT_PCI = _IOWR(GPIB_CODE, 32, select_pci_ioctl_t), + IBEVENT = _IOR(GPIB_CODE, 33, event_ioctl_t), + IBRSC = _IOW(GPIB_CODE, 34, rsc_ioctl_t), + IB_T1_DELAY = _IOW(GPIB_CODE, 35, t1_delay_ioctl_t), + IBLOC = _IO(GPIB_CODE, 36), + + IBAUTOSPOLL = _IOW(GPIB_CODE, 38, autospoll_ioctl_t), + IBONL = _IOW(GPIB_CODE, 39, online_ioctl_t), + IBPP2_SET = _IOW(GPIB_CODE, 40, local_ppoll_mode_ioctl_t), + IBPP2_GET = _IOR(GPIB_CODE, 41, local_ppoll_mode_ioctl_t), + IBSELECT_DEVICE_PATH = _IOW(GPIB_CODE, 43, select_device_path_ioctl_t), + // 44 was IBSELECT_SERIAL_NUMBER + IBRSV2 = _IOW(GPIB_CODE, 45, request_service2_t) +}; + +#endif /* _GPIB_IOCTL_H */ diff --git a/drivers/staging/gpib/uapi/gpib_user.h b/drivers/staging/gpib/uapi/gpib_user.h new file mode 100644 index 0000000000000000000000000000000000000000..0896a55a758feeae61da2047b001e482b530041b --- /dev/null +++ b/drivers/staging/gpib/uapi/gpib_user.h @@ -0,0 +1,363 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/*************************************************************************** + * copyright : (C) 2002 by Frank Mori Hess + ***************************************************************************/ + +#ifndef _GPIB_USER_H +#define _GPIB_USER_H + +#define GPIB_MAX_NUM_BOARDS 16 +#define GPIB_MAX_NUM_DESCRIPTORS 0x1000 + +enum ibsta_bit_numbers { + DCAS_NUM = 0, + DTAS_NUM = 1, + LACS_NUM = 2, + TACS_NUM = 3, + ATN_NUM = 4, + CIC_NUM = 5, + REM_NUM = 6, + LOK_NUM = 7, + CMPL_NUM = 8, + EVENT_NUM = 9, + SPOLL_NUM = 10, + RQS_NUM = 11, + SRQI_NUM = 12, + END_NUM = 13, + TIMO_NUM = 14, + ERR_NUM = 15 +}; + +/* IBSTA status bits (returned by all functions) */ +enum ibsta_bits { + DCAS = (1 << DCAS_NUM), /* device clear state */ + DTAS = (1 << DTAS_NUM), /* device trigger state */ + LACS = (1 << LACS_NUM), /* GPIB interface is addressed as Listener */ + TACS = (1 << TACS_NUM), /* GPIB interface is addressed as Talker */ + ATN = (1 << ATN_NUM), /* Attention is asserted */ + CIC = (1 << CIC_NUM), /* GPIB interface is Controller-in-Charge */ + REM = (1 << REM_NUM), /* remote state */ + LOK = (1 << LOK_NUM), /* lockout state */ + CMPL = (1 << CMPL_NUM), /* I/O is complete */ + EVENT = (1 << EVENT_NUM), /* DCAS, DTAS, or IFC has occurred */ + SPOLL = (1 << SPOLL_NUM), /* board serial polled by busmaster */ + RQS = (1 << RQS_NUM), /* Device requesting service */ + SRQI = (1 << SRQI_NUM), /* SRQ is asserted */ + END = (1 << END_NUM), /* EOI or EOS encountered */ + TIMO = (1 << TIMO_NUM), /* Time limit on I/O or wait function exceeded */ + ERR = (1 << ERR_NUM), /* Function call terminated on error */ + + device_status_mask = ERR | TIMO | END | CMPL | RQS, + board_status_mask = ERR | TIMO | END | CMPL | SPOLL | + EVENT | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS | SRQI, +}; + +/* IBERR error codes */ +enum iberr_code { + EDVR = 0, /* system error */ + ECIC = 1, /* not CIC */ + ENOL = 2, /* no listeners */ + EADR = 3, /* CIC and not addressed before I/O */ + EARG = 4, /* bad argument to function call */ + ESAC = 5, /* not SAC */ + EABO = 6, /* I/O operation was aborted */ + ENEB = 7, /* non-existent board (GPIB interface offline) */ + EDMA = 8, /* DMA hardware error detected */ + EOIP = 10, /* new I/O attempted with old I/O in progress */ + ECAP = 11, /* no capability for intended opeation */ + EFSO = 12, /* file system operation error */ + EBUS = 14, /* bus error */ + ESTB = 15, /* lost serial poll bytes */ + ESRQ = 16, /* SRQ stuck on */ + ETAB = 20 /* Table Overflow */ +}; + +/* Timeout values and meanings */ +enum gpib_timeout { + TNONE = 0, /* Infinite timeout (disabled) */ + T10us = 1, /* Timeout of 10 usec (ideal) */ + T30us = 2, /* Timeout of 30 usec (ideal) */ + T100us = 3, /* Timeout of 100 usec (ideal) */ + T300us = 4, /* Timeout of 300 usec (ideal) */ + T1ms = 5, /* Timeout of 1 msec (ideal) */ + T3ms = 6, /* Timeout of 3 msec (ideal) */ + T10ms = 7, /* Timeout of 10 msec (ideal) */ + T30ms = 8, /* Timeout of 30 msec (ideal) */ + T100ms = 9, /* Timeout of 100 msec (ideal) */ + T300ms = 10, /* Timeout of 300 msec (ideal) */ + T1s = 11, /* Timeout of 1 sec (ideal) */ + T3s = 12, /* Timeout of 3 sec (ideal) */ + T10s = 13, /* Timeout of 10 sec (ideal) */ + T30s = 14, /* Timeout of 30 sec (ideal) */ + T100s = 15, /* Timeout of 100 sec (ideal) */ + T300s = 16, /* Timeout of 300 sec (ideal) */ + T1000s = 17 /* Timeout of 1000 sec (maximum) */ +}; + +/* End-of-string (EOS) modes for use with ibeos */ + +enum eos_flags { + EOS_MASK = 0x1c00, + REOS = 0x0400, /* Terminate reads on EOS */ + XEOS = 0x800, /* assert EOI when EOS char is sent */ + BIN = 0x1000 /* Do 8-bit compare on EOS */ +}; + +/* GPIB Bus Control Lines bit vector */ +enum bus_control_line { + ValidDAV = 0x01, + ValidNDAC = 0x02, + ValidNRFD = 0x04, + ValidIFC = 0x08, + ValidREN = 0x10, + ValidSRQ = 0x20, + ValidATN = 0x40, + ValidEOI = 0x80, + ValidALL = 0xff, + BusDAV = 0x0100, /* DAV line status bit */ + BusNDAC = 0x0200, /* NDAC line status bit */ + BusNRFD = 0x0400, /* NRFD line status bit */ + BusIFC = 0x0800, /* IFC line status bit */ + BusREN = 0x1000, /* REN line status bit */ + BusSRQ = 0x2000, /* SRQ line status bit */ + BusATN = 0x4000, /* ATN line status bit */ + BusEOI = 0x8000 /* EOI line status bit */ +}; + +enum old_bus_control_line { + BUS_DAV = 0x0100, /* DAV line status bit */ + BUS_NDAC = 0x0200, /* NDAC line status bit */ + BUS_NRFD = 0x0400, /* NRFD line status bit */ + BUS_IFC = 0x0800, /* IFC line status bit */ + BUS_REN = 0x1000, /* REN line status bit */ + BUS_SRQ = 0x2000, /* SRQ line status bit */ + BUS_ATN = 0x4000, /* ATN line status bit */ + BUS_EOI = 0x8000 /* EOI line status bit */ +}; + +/* Possible GPIB command messages */ + +enum cmd_byte { + GTL = 0x1, /* go to local */ + SDC = 0x4, /* selected device clear */ + PPConfig = 0x5, +#ifndef PPC + PPC = PPConfig, /* parallel poll configure */ +#endif + GET = 0x8, /* group execute trigger */ + TCT = 0x9, /* take control */ + LLO = 0x11, /* local lockout */ + DCL = 0x14, /* device clear */ + PPU = 0x15, /* parallel poll unconfigure */ + SPE = 0x18, /* serial poll enable */ + SPD = 0x19, /* serial poll disable */ + CFE = 0x1f, /* configure enable */ + LAD = 0x20, /* value to be 'ored' in to obtain listen address */ + UNL = 0x3F, /* unlisten */ + TAD = 0x40, /* value to be 'ored' in to obtain talk address */ + UNT = 0x5F, /* untalk */ + SAD = 0x60, /* my secondary address (base) */ + PPE = 0x60, /* parallel poll enable (base) */ + PPD = 0x70 /* parallel poll disable */ +}; + +enum ppe_bits { + PPC_DISABLE = 0x10, + PPC_SENSE = 0x8, /* parallel poll sense bit */ + PPC_DIO_MASK = 0x7 +}; + +/* confine address to range 0 to 30. */ +static inline unsigned int gpib_address_restrict(unsigned int addr) +{ + addr &= 0x1f; + if (addr == 0x1f) + addr = 0; + return addr; +} + +static inline uint8_t MLA(unsigned int addr) +{ + return gpib_address_restrict(addr) | LAD; +} + +static inline uint8_t MTA(unsigned int addr) +{ + return gpib_address_restrict(addr) | TAD; +} + +static inline uint8_t MSA(unsigned int addr) +{ + return gpib_address_restrict(addr) | SAD; +} + +static inline uint8_t PPE_byte(unsigned int dio_line, int sense) +{ + uint8_t cmd; + + cmd = PPE; + if (sense) + cmd |= PPC_SENSE; + cmd |= (dio_line - 1) & 0x7; + return cmd; +} + +static inline uint8_t CFGn(unsigned int meters) +{ + return 0x6 | (meters & 0xf); +} + +/* mask of bits that actually matter in a command byte */ +enum { + gpib_command_mask = 0x7f, +}; + +static inline int is_PPE(uint8_t command) +{ + return (command & 0x70) == 0x60; +} + +static inline int is_PPD(uint8_t command) +{ + return (command & 0x70) == 0x70; +} + +static inline int in_addressed_command_group(uint8_t command) +{ + return (command & 0x70) == 0x0; +} + +static inline int in_universal_command_group(uint8_t command) +{ + return (command & 0x70) == 0x10; +} + +static inline int in_listen_address_group(uint8_t command) +{ + return (command & 0x60) == 0x20; +} + +static inline int in_talk_address_group(uint8_t command) +{ + return (command & 0x60) == 0x40; +} + +static inline int in_primary_command_group(uint8_t command) +{ + return in_addressed_command_group(command) || + in_universal_command_group(command) || + in_listen_address_group(command) || + in_talk_address_group(command); +} + +static inline int gpib_address_equal(unsigned int pad1, int sad1, unsigned int pad2, int sad2) +{ + if (pad1 == pad2) { + if (sad1 == sad2) + return 1; + if (sad1 < 0 && sad2 < 0) + return 1; + } + + return 0; +} + +enum ibask_option { + IbaPAD = 0x1, + IbaSAD = 0x2, + IbaTMO = 0x3, + IbaEOT = 0x4, + IbaPPC = 0x5, /* board only */ + IbaREADDR = 0x6, /* device only */ + IbaAUTOPOLL = 0x7, /* board only */ + IbaCICPROT = 0x8, /* board only */ + IbaIRQ = 0x9, /* board only */ + IbaSC = 0xa, /* board only */ + IbaSRE = 0xb, /* board only */ + IbaEOSrd = 0xc, + IbaEOSwrt = 0xd, + IbaEOScmp = 0xe, + IbaEOSchar = 0xf, + IbaPP2 = 0x10, /* board only */ + IbaTIMING = 0x11, /* board only */ + IbaDMA = 0x12, /* board only */ + IbaReadAdjust = 0x13, + IbaWriteAdjust = 0x14, + IbaEventQueue = 0x15, /* board only */ + IbaSPollBit = 0x16, /* board only */ + IbaSpollBit = 0x16, /* board only */ + IbaSendLLO = 0x17, /* board only */ + IbaSPollTime = 0x18, /* device only */ + IbaPPollTime = 0x19, /* board only */ + IbaEndBitIsNormal = 0x1a, + IbaUnAddr = 0x1b, /* device only */ + IbaHSCableLength = 0x1f, /* board only */ + IbaIst = 0x20, /* board only */ + IbaRsv = 0x21, /* board only */ + IbaBNA = 0x200, /* device only */ + /* linux-gpib extensions */ + Iba7BitEOS = 0x1000 /* board only. Returns 1 if board supports 7 bit eos compares*/ +}; + +enum ibconfig_option { + IbcPAD = 0x1, + IbcSAD = 0x2, + IbcTMO = 0x3, + IbcEOT = 0x4, + IbcPPC = 0x5, /* board only */ + IbcREADDR = 0x6, /* device only */ + IbcAUTOPOLL = 0x7, /* board only */ + IbcCICPROT = 0x8, /* board only */ + IbcIRQ = 0x9, /* board only */ + IbcSC = 0xa, /* board only */ + IbcSRE = 0xb, /* board only */ + IbcEOSrd = 0xc, + IbcEOSwrt = 0xd, + IbcEOScmp = 0xe, + IbcEOSchar = 0xf, + IbcPP2 = 0x10, /* board only */ + IbcTIMING = 0x11, /* board only */ + IbcDMA = 0x12, /* board only */ + IbcReadAdjust = 0x13, + IbcWriteAdjust = 0x14, + IbcEventQueue = 0x15, /* board only */ + IbcSPollBit = 0x16, /* board only */ + IbcSpollBit = 0x16, /* board only */ + IbcSendLLO = 0x17, /* board only */ + IbcSPollTime = 0x18, /* device only */ + IbcPPollTime = 0x19, /* board only */ + IbcEndBitIsNormal = 0x1a, + IbcUnAddr = 0x1b, /* device only */ + IbcHSCableLength = 0x1f, /* board only */ + IbcIst = 0x20, /* board only */ + IbcRsv = 0x21, /* board only */ + IbcBNA = 0x200 /* device only */ +}; + +enum t1_delays { + T1_DELAY_2000ns = 1, + T1_DELAY_500ns = 2, + T1_DELAY_350ns = 3 +}; + +enum { + request_service_bit = 0x40, +}; + +enum gpib_events { + EventNone = 0, + EventDevTrg = 1, + EventDevClr = 2, + EventIFC = 3 +}; + +enum gpib_stb { + IbStbRQS = 0x40, /* IEEE 488.1 & 2 */ + IbStbESB = 0x20, /* IEEE 488.2 only */ + IbStbMAV = 0x10 /* IEEE 488.2 only */ +}; + +#endif /* _GPIB_USER_H */ + +/* Check for errors */ diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index aa6f266b62a1417408e11b68f2f624b4c40bec7d..90ab32638d3f59570da774e95d59db1257cde37e 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match); static struct platform_driver arche_apb_ctrl_device_driver = { .probe = arche_apb_ctrl_probe, - .remove_new = arche_apb_ctrl_remove, + .remove = arche_apb_ctrl_remove, .shutdown = arche_apb_ctrl_shutdown, .driver = { .name = "arche-apb-ctrl", diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index b33977ccd5271064a1b588df6e529e1684c2d190..d48464390f58e23af3d1c2c83d7e3dd8c3a75132 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -623,7 +623,7 @@ MODULE_DEVICE_TABLE(of, arche_platform_of_match); static struct platform_driver arche_platform_device_driver = { .probe = arche_platform_probe, - .remove_new = arche_platform_remove, + .remove = arche_platform_remove, .shutdown = arche_platform_shutdown, .driver = { .name = "arche-platform-ctrl", diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 9b26e148d40fba89398ef02a2517fdedd539130b..16bcf7fc8158659284dff900d33befa3b65fe7be 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -42,11 +42,6 @@ struct gb_gpio_controller { struct mutex irq_lock; }; -static inline struct gb_gpio_controller *gpio_chip_to_gb_gpio_controller(struct gpio_chip *chip) -{ - return container_of(chip, struct gb_gpio_controller, chip); -} - static struct gpio_chip *irq_data_to_gpio_chip(struct irq_data *d) { return d->domain->host_data; @@ -278,7 +273,7 @@ static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc, static void gb_gpio_irq_mask(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; line->masked = true; @@ -288,7 +283,7 @@ static void gb_gpio_irq_mask(struct irq_data *d) static void gb_gpio_irq_unmask(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; line->masked = false; @@ -298,7 +293,7 @@ static void gb_gpio_irq_unmask(struct irq_data *d) static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; struct device *dev = &ggc->gbphy_dev->dev; u8 irq_type; @@ -336,7 +331,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type) static void gb_gpio_irq_bus_lock(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); mutex_lock(&ggc->irq_lock); } @@ -344,7 +339,7 @@ static void gb_gpio_irq_bus_lock(struct irq_data *d) static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d) { struct gpio_chip *chip = irq_data_to_gpio_chip(d); - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); struct gb_gpio_line *line = &ggc->lines[d->hwirq]; if (line->irq_type_pending) { @@ -407,21 +402,21 @@ static int gb_gpio_request_handler(struct gb_operation *op) static int gb_gpio_request(struct gpio_chip *chip, unsigned int offset) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); return gb_gpio_activate_operation(ggc, (u8)offset); } static void gb_gpio_free(struct gpio_chip *chip, unsigned int offset) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); gb_gpio_deactivate_operation(ggc, (u8)offset); } static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); u8 which; int ret; @@ -435,7 +430,7 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); return gb_gpio_direction_in_operation(ggc, (u8)offset); } @@ -443,14 +438,14 @@ static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); return gb_gpio_direction_out_operation(ggc, (u8)offset, !!value); } static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); u8 which; int ret; @@ -464,7 +459,7 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset) static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); gb_gpio_set_value_operation(ggc, (u8)offset, !!value); } @@ -472,7 +467,7 @@ static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) static int gb_gpio_set_config(struct gpio_chip *chip, unsigned int offset, unsigned long config) { - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); + struct gb_gpio_controller *ggc = gpiochip_get_data(chip); u32 debounce; if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) @@ -579,7 +574,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_line_free; - ret = gpiochip_add_data(gpio, NULL); + ret = gpiochip_add_data(gpio, ggc); if (ret) { dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret); goto exit_line_free; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index cdf4ebb93b104e85296fa770a2d9692114b3d022..8eab94cb06faf64dbf171edb7c924cbc00fb3c02 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -596,11 +596,13 @@ static int get_serial_info(struct tty_struct *tty, struct gb_tty *gb_tty = tty->driver_data; ss->line = gb_tty->minor; + mutex_lock(&gb_tty->port.mutex); ss->close_delay = jiffies_to_msecs(gb_tty->port.close_delay) / 10; ss->closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : jiffies_to_msecs(gb_tty->port.closing_wait) / 10; + mutex_unlock(&gb_tty->port.mutex); return 0; } diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO deleted file mode 100644 index 0fa6a5500bdb10c59d4e09c0326be3e73d5e7b22..0000000000000000000000000000000000000000 --- a/drivers/staging/iio/TODO +++ /dev/null @@ -1,5 +0,0 @@ -2020-02-25 - - -Contact: Jonathan Cameron <jic23@kernel.org>. -Mailing list: linux-iio@vger.kernel.org diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c index 712f916f0935f5be7d4284cf2698828ef89a7e64..71e6e278a4b3cc6c8118f884d556ac47e2f8c9dc 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c +++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c @@ -629,7 +629,7 @@ MODULE_DEVICE_TABLE(of, atmel_isc_of_match); static struct platform_driver atmel_isc_driver = { .probe = atmel_isc_probe, - .remove_new = atmel_isc_remove, + .remove = atmel_isc_remove, .driver = { .name = "atmel-sama5d2-isc", .pm = &atmel_isc_dev_pm_ops, diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c index 9485167d5b7d7385431df579afaa879531680baa..1f74c2dd044cfb9e7df926524171ac758d9b53b2 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c +++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c @@ -592,7 +592,7 @@ MODULE_DEVICE_TABLE(of, microchip_xisc_of_match); static struct platform_driver microchip_xisc_driver = { .probe = microchip_xisc_probe, - .remove_new = microchip_xisc_remove, + .remove = microchip_xisc_remove, .driver = { .name = "microchip-sama7g5-xisc", .pm = µchip_xisc_dev_pm_ops, diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 785aac88192212bcb31d6145522f5ebb2b356feb..3edbc57be2caa76d0f1236fc4337992095962475 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -2076,7 +2076,7 @@ MODULE_DEVICE_TABLE(platform, imx_csi_ids); static struct platform_driver imx_csi_driver = { .probe = imx_csi_probe, - .remove_new = imx_csi_remove, + .remove = imx_csi_remove, .id_table = imx_csi_ids, .driver = { .name = "imx-ipuv3-csi", diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index be54dca11465dc4eb0112fc44556596e05a17d83..a08389b99d14acceb50ba854f0c579fc646ac808 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -129,7 +129,7 @@ MODULE_DEVICE_TABLE(of, imx_media_dt_ids); static struct platform_driver imx_media_pdrv = { .probe = imx_media_probe, - .remove_new = imx_media_remove, + .remove = imx_media_remove, .driver = { .name = "imx-media", .of_match_table = imx_media_dt_ids, diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index 0d8b420616235dd32d155de4ce489cd5acc63752..dd8c7b3233bccfc34b59e0f0ff813b36752e1526 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -836,7 +836,7 @@ static struct platform_driver csi2_driver = { .of_match_table = csi2_dt_ids, }, .probe = csi2_probe, - .remove_new = csi2_remove, + .remove = csi2_remove, }; module_platform_driver(csi2_driver); diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c index 52185090129ba5a5c5f3d7747f7d00268375aa33..6d34a482492e8838cf9dbb104315b87abf3f3e3b 100644 --- a/drivers/staging/media/meson/vdec/vdec.c +++ b/drivers/staging/media/meson/vdec/vdec.c @@ -1117,7 +1117,7 @@ static void vdec_remove(struct platform_device *pdev) static struct platform_driver meson_vdec_driver = { .probe = vdec_probe, - .remove_new = vdec_remove, + .remove = vdec_remove, .driver = { .name = "meson-vdec", .of_match_table = vdec_dt_match, diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index f468af64bbef1c7e9019352508f95f5e2d2a083a..f9bef5173bf25c0cd6b09d2b253d36aa78d7b0c4 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -1101,7 +1101,7 @@ static const struct dev_pm_ops rkvdec_pm_ops = { static struct platform_driver rkvdec_driver = { .probe = rkvdec_probe, - .remove_new = rkvdec_remove, + .remove = rkvdec_remove, .driver = { .name = "rkvdec", .of_match_table = of_rkvdec_match, diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c index b6d34145bc191e8f2e39713553c28ce0c6ca2d9f..259aaad010d2f02b620ce7ac98517c75134566bb 100644 --- a/drivers/staging/media/starfive/camss/stf-camss.c +++ b/drivers/staging/media/starfive/camss/stf-camss.c @@ -422,7 +422,7 @@ static const struct dev_pm_ops stfcamss_pm_ops = { static struct platform_driver stfcamss_driver = { .probe = stfcamss_probe, - .remove_new = stfcamss_remove, + .remove = stfcamss_remove, .driver = { .name = "starfive-camss", .pm = &stfcamss_pm_ops, diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index f52df683604525fd17b82087ef7f867f2d9155a2..52a9588462ce5898705cc351fa461f3c49600ad2 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -705,7 +705,7 @@ static const struct dev_pm_ops cedrus_dev_pm_ops = { static struct platform_driver cedrus_driver = { .probe = cedrus_probe, - .remove_new = cedrus_remove, + .remove = cedrus_remove, .driver = { .name = CEDRUS_NAME, .of_match_table = cedrus_dt_match, diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c index 58f8ae92320d676058d170cc0871df70b2571559..6877f2beee8c8c069a0aa1aeeafd052acc713164 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c @@ -536,7 +536,7 @@ MODULE_DEVICE_TABLE(of, sun6i_isp_of_match); static struct platform_driver sun6i_isp_platform_driver = { .probe = sun6i_isp_probe, - .remove_new = sun6i_isp_remove, + .remove = sun6i_isp_remove, .driver = { .name = SUN6I_ISP_NAME, .of_match_table = sun6i_isp_of_match, diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 255cccd0c5fda8e47455142451f56d27bcd7a608..604185c00a1a39e34357e3beefa75aa87b0a1189 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -858,5 +858,5 @@ struct platform_driver tegra_csi_driver = { .pm = &tegra_csi_pm_ops, }, .probe = tegra_csi_probe, - .remove_new = tegra_csi_remove, + .remove = tegra_csi_remove, }; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index ad481b35e618a0b0e85af7276d84342440b82e64..c9276ff76157fa2d17e05df271c6ebea4b4455ed 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1977,5 +1977,5 @@ struct platform_driver tegra_vi_driver = { .pm = &tegra_vi_pm_ops, }, .probe = tegra_vi_probe, - .remove_new = tegra_vi_remove, + .remove = tegra_vi_remove, }; diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c index 8504b9ea9cea2ce27164c689116663a820608706..5ec717f3afd503b1ef7e3690d3f028531c1afa9f 100644 --- a/drivers/staging/media/tegra-video/vip.c +++ b/drivers/staging/media/tegra-video/vip.c @@ -281,5 +281,5 @@ struct platform_driver tegra_vip_driver = { .of_match_table = tegra_vip_of_id_table, }, .probe = tegra_vip_probe, - .remove_new = tegra_vip_remove, + .remove = tegra_vip_remove, }; diff --git a/drivers/staging/most/TODO b/drivers/staging/most/TODO index 4fa11a9d2cf741fcf49ee9e74f8b635e9990549d..a6448a05ed4612082a2e391d5022d12bda0783cf 100644 --- a/drivers/staging/most/TODO +++ b/drivers/staging/most/TODO @@ -1,8 +1 @@ * Get through code review with Greg Kroah-Hartman - -Contact: -To: -Christian Gromm <christian.gromm@microchip.com> -Cc: -Michael Fabry <Michael.Fabry@microchip.com> -Christian Gromm <chris@engineersdelight.de> diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index ed6a9cc8854129ea9526eb6f37f7cc6d8edce140..dad2abe6c0c90e0af0902d2022a8438370d4c5aa 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -1090,7 +1090,7 @@ MODULE_DEVICE_TABLE(of, dim2_of_match); static struct platform_driver dim2_driver = { .probe = dim2_probe, - .remove_new = dim2_remove, + .remove = dim2_remove, .driver = { .name = "hdm_dim2", .of_match_table = dim2_of_match, diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index ce869280a056b6fb88d61880b2c34a7785ad2b86..184b2dd11fc34a23be1d31107e73ddde7f0d1201 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -352,8 +352,8 @@ static void i2c_remove(struct i2c_client *client) } static const struct i2c_device_id i2c_id[] = { - { "most_i2c", 0 }, - { }, /* Terminating entry */ + { "most_i2c" }, + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(i2c, i2c_id); diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 977f8fc29e631f1a391da08531a51a98c4a0e443..263774e6a78cae913ebd74af5d16ed0dc6ee86ad 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -952,7 +952,7 @@ MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match); static struct platform_driver nvec_device_driver = { .probe = tegra_nvec_probe, - .remove_new = tegra_nvec_remove, + .remove = tegra_nvec_remove, .driver = { .name = "nvec", .pm = &nvec_pm_ops, diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c index d0259c80f8105e6529262329e5ad0ce4405e512f..d2b91318f1516f2e9f8edbe4f68731595999f4c5 100644 --- a/drivers/staging/nvec/nvec_kbd.c +++ b/drivers/staging/nvec/nvec_kbd.c @@ -175,7 +175,7 @@ static void nvec_kbd_remove(struct platform_device *pdev) static struct platform_driver nvec_kbd_driver = { .probe = nvec_kbd_probe, - .remove_new = nvec_kbd_remove, + .remove = nvec_kbd_remove, .driver = { .name = "nvec-kbd", }, diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c index 9943b1fff1905d4cfc5ebf6274ecd65598f7680a..e0e67a3eb7222b38a45aa61fd23db0336d5b21a0 100644 --- a/drivers/staging/nvec/nvec_power.c +++ b/drivers/staging/nvec/nvec_power.c @@ -433,7 +433,7 @@ static void nvec_power_remove(struct platform_device *pdev) static struct platform_driver nvec_power_driver = { .probe = nvec_power_probe, - .remove_new = nvec_power_remove, + .remove = nvec_power_remove, .driver = { .name = "nvec-power", } diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index f34016c4a26b6ecafdf68bb28989e8852d1bd925..575233fa1677eaab75b28448f3a15f9839527b12 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -175,7 +175,7 @@ static SIMPLE_DEV_PM_OPS(nvec_mouse_pm_ops, nvec_mouse_suspend, static struct platform_driver nvec_mouse_driver = { .probe = nvec_mouse_probe, - .remove_new = nvec_mouse_remove, + .remove = nvec_mouse_remove, .driver = { .name = "nvec-mouse", .pm = &nvec_mouse_pm_ops, diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index bbf33b88bb7c2afe59321c5862e42102ab15a52a..261f8dbdc3827360bdff4565d511b47883a6ef84 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -40,8 +40,8 @@ #define GET_SKBUFF_QOS(skb) 0 #endif -static void cvm_oct_tx_do_cleanup(unsigned long arg); -static DECLARE_TASKLET_OLD(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup); +static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean); +static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup); /* Maximum number of SKBs to try to free per xmit packet. */ #define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2) @@ -670,7 +670,7 @@ void cvm_oct_tx_shutdown_dev(struct net_device *dev) } } -static void cvm_oct_tx_do_cleanup(unsigned long arg) +static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean) { int port; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index a5e99cc78a454f5666b6bb3632e701e794db781e..eadb74fc14c8d9d88731c2b500ef38d27fa56cfb 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -977,7 +977,7 @@ MODULE_DEVICE_TABLE(of, cvm_oct_match); static struct platform_driver cvm_oct_driver = { .probe = cvm_oct_probe, - .remove_new = cvm_oct_remove, + .remove = cvm_oct_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = cvm_oct_match, diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig deleted file mode 100644 index d0ba34cc32f7a8f9861cd97e2dbc27358a9767ec..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config FB_OLPC_DCON - tristate "One Laptop Per Child Display CONtroller support" - depends on OLPC && FB && BROKEN - depends on I2C - depends on GPIO_CS5535 && ACPI - select BACKLIGHT_CLASS_DEVICE - help - In order to support very low power operation, the XO laptop uses a - secondary Display CONtroller, or DCON. This secondary controller - is present in the video pipeline between the primary display - controller (integrate into the processor or chipset) and the LCD - panel. It allows the main processor/display controller to be - completely powered off while still retaining an image on the display. - This controller is only available on OLPC platforms. Unless you have - one of these platforms, you will want to say 'N'. - diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile deleted file mode 100644 index 734b2ce26066f34fd005b053aac2513ef5bb1933..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -olpc-dcon-objs += olpc_dcon.o olpc_dcon_xo_1.o olpc_dcon_xo_1_5.o -obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o - - diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO deleted file mode 100644 index 7c263358b44a96bd8160b65baf0186e3ad450dfa..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/TODO +++ /dev/null @@ -1,15 +0,0 @@ -TODO: - - complete rewrite: - 1. The underlying fbdev drivers need to be converted into drm kernel - modesetting drivers. - 2. The dcon low-power display mode can then be integrated using the - drm damage tracking and self-refresh helpers. - This bolted-on self-refresh support that digs around in fbdev - internals, but isn't properly integrated, is not the correct solution. - - see if vx855 gpio API can be made similar enough to cs5535 so we can - share more code - -Please send patches to Greg Kroah-Hartman <greg@kroah.com> and -copy: - Daniel Drake <dsd@laptop.org> - Jens Frederich <jfrederich@gmail.com> diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c deleted file mode 100644 index 4cb904a5f8f40258a2f03b39109366c5ebf50298..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ /dev/null @@ -1,807 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Mainly by David Woodhouse, somewhat modified by Jordan Crouse - * - * Copyright © 2006-2007 Red Hat, Inc. - * Copyright © 2006-2007 Advanced Micro Devices, Inc. - * Copyright © 2009 VIA Technology, Inc. - * Copyright (c) 2010-2011 Andres Salomon <dilinger@queued.net> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/fb.h> -#include <linux/console.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/backlight.h> -#include <linux/device.h> -#include <linux/uaccess.h> -#include <linux/ctype.h> -#include <linux/panic_notifier.h> -#include <linux/reboot.h> -#include <linux/olpc-ec.h> -#include <asm/tsc.h> -#include <asm/olpc.h> - -#include "olpc_dcon.h" - -/* Module definitions */ - -static ushort resumeline = 898; -module_param(resumeline, ushort, 0444); - -static struct dcon_platform_data *pdata; - -/* I2C structures */ - -/* Platform devices */ -static struct platform_device *dcon_device; - -static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END }; - -static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val) -{ - return i2c_smbus_write_word_data(dcon->client, reg, val); -} - -static s32 dcon_read(struct dcon_priv *dcon, u8 reg) -{ - return i2c_smbus_read_word_data(dcon->client, reg); -} - -/* ===== API functions - these are called by a variety of users ==== */ - -static int dcon_hw_init(struct dcon_priv *dcon, int is_init) -{ - u16 ver; - int rc = 0; - - ver = dcon_read(dcon, DCON_REG_ID); - if ((ver >> 8) != 0xDC) { - pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver); - rc = -ENXIO; - goto err; - } - - if (is_init) { - pr_info("Discovered DCON version %x\n", ver & 0xFF); - rc = pdata->init(dcon); - if (rc != 0) { - pr_err("Unable to init.\n"); - goto err; - } - } - - if (ver < 0xdc02) { - dev_err(&dcon->client->dev, - "DCON v1 is unsupported, giving up..\n"); - rc = -ENODEV; - goto err; - } - - /* SDRAM setup/hold time */ - dcon_write(dcon, 0x3a, 0xc040); - dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */ - dcon_write(dcon, DCON_REG_MEM_OPT_A, - MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN); - dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET); - - /* Colour swizzle, AA, no passthrough, backlight */ - if (is_init) { - dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE | - MODE_CSWIZZLE | MODE_COL_AA; - } - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - - /* Set the scanline to interrupt on during resume */ - dcon_write(dcon, DCON_REG_SCAN_INT, resumeline); - -err: - return rc; -} - -/* - * The smbus doesn't always come back due to what is believed to be - * hardware (power rail) bugs. For older models where this is known to - * occur, our solution is to attempt to wait for the bus to stabilize; - * if it doesn't happen, cut power to the dcon, repower it, and wait - * for the bus to stabilize. Rinse, repeat until we have a working - * smbus. For newer models, we simply BUG(); we want to know if this - * still happens despite the power fixes that have been made! - */ -static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down) -{ - unsigned long timeout; - u8 pm; - int x; - -power_up: - if (is_powered_down) { - pm = 1; - x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - if (x) { - pr_warn("unable to force dcon to power up: %d!\n", x); - return x; - } - usleep_range(10000, 11000); /* we'll be conservative */ - } - - pdata->bus_stabilize_wiggle(); - - for (x = -1, timeout = 50; timeout && x < 0; timeout--) { - usleep_range(1000, 1100); - x = dcon_read(dcon, DCON_REG_ID); - } - if (x < 0) { - pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n"); - BUG_ON(olpc_board_at_least(olpc_board(0xc2))); - pm = 0; - olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - msleep(100); - is_powered_down = 1; - goto power_up; /* argh, stupid hardware.. */ - } - - if (is_powered_down) - return dcon_hw_init(dcon, 0); - return 0; -} - -static void dcon_set_backlight(struct dcon_priv *dcon, u8 level) -{ - dcon->bl_val = level; - dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val); - - /* Purposely turn off the backlight when we go to level 0 */ - if (dcon->bl_val == 0) { - dcon->disp_mode &= ~MODE_BL_ENABLE; - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - } else if (!(dcon->disp_mode & MODE_BL_ENABLE)) { - dcon->disp_mode |= MODE_BL_ENABLE; - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - } -} - -/* Set the output type to either color or mono */ -static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono) -{ - if (dcon->mono == enable_mono) - return 0; - - dcon->mono = enable_mono; - - if (enable_mono) { - dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA); - dcon->disp_mode |= MODE_MONO_LUMA; - } else { - dcon->disp_mode &= ~(MODE_MONO_LUMA); - dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA; - } - - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - return 0; -} - -/* For now, this will be really stupid - we need to address how - * DCONLOAD works in a sleep and account for it accordingly - */ - -static void dcon_sleep(struct dcon_priv *dcon, bool sleep) -{ - int x; - - /* Turn off the backlight and put the DCON to sleep */ - - if (dcon->asleep == sleep) - return; - - if (!olpc_board_at_least(olpc_board(0xc2))) - return; - - if (sleep) { - u8 pm = 0; - - x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - if (x) - pr_warn("unable to force dcon to power down: %d!\n", x); - else - dcon->asleep = sleep; - } else { - /* Only re-enable the backlight if the backlight value is set */ - if (dcon->bl_val != 0) - dcon->disp_mode |= MODE_BL_ENABLE; - x = dcon_bus_stabilize(dcon, 1); - if (x) - pr_warn("unable to reinit dcon hardware: %d!\n", x); - else - dcon->asleep = sleep; - - /* Restore backlight */ - dcon_set_backlight(dcon, dcon->bl_val); - } - - /* We should turn off some stuff in the framebuffer - but what? */ -} - -/* the DCON seems to get confused if we change DCONLOAD too - * frequently -- i.e., approximately faster than frame time. - * normally we don't change it this fast, so in general we won't - * delay here. - */ -static void dcon_load_holdoff(struct dcon_priv *dcon) -{ - ktime_t delta_t, now; - - while (1) { - now = ktime_get(); - delta_t = ktime_sub(now, dcon->load_time); - if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20) - break; - mdelay(4); - } -} - -static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank) -{ - int err; - - console_lock(); - lock_fb_info(dcon->fbinfo); - - dcon->ignore_fb_events = true; - err = fb_blank(dcon->fbinfo, - blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); - dcon->ignore_fb_events = false; - unlock_fb_info(dcon->fbinfo); - console_unlock(); - - if (err) { - dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n", - blank ? "" : "un"); - return false; - } - return true; -} - -/* Set the source of the display (CPU or DCON) */ -static void dcon_source_switch(struct work_struct *work) -{ - struct dcon_priv *dcon = container_of(work, struct dcon_priv, - switch_source); - int source = dcon->pending_src; - - if (dcon->curr_src == source) - return; - - dcon_load_holdoff(dcon); - - dcon->switched = false; - - switch (source) { - case DCON_SOURCE_CPU: - pr_info("%s to CPU\n", __func__); - /* Enable the scanline interrupt bit */ - if (dcon_write(dcon, DCON_REG_MODE, - dcon->disp_mode | MODE_SCAN_INT)) - pr_err("couldn't enable scanline interrupt!\n"); - else - /* Wait up to one second for the scanline interrupt */ - wait_event_timeout(dcon->waitq, dcon->switched, HZ); - - if (!dcon->switched) - pr_err("Timeout entering CPU mode; expect a screen glitch.\n"); - - /* Turn off the scanline interrupt */ - if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode)) - pr_err("couldn't disable scanline interrupt!\n"); - - /* - * Ideally we'd like to disable interrupts here so that the - * fb unblanking and DCON turn on happen at a known time value; - * however, we can't do that right now with fb_blank - * messing with semaphores. - * - * For now, we just hope.. - */ - if (!dcon_blank_fb(dcon, false)) { - pr_err("Failed to enter CPU mode\n"); - dcon->pending_src = DCON_SOURCE_DCON; - return; - } - - /* And turn off the DCON */ - pdata->set_dconload(1); - dcon->load_time = ktime_get(); - - pr_info("The CPU has control\n"); - break; - case DCON_SOURCE_DCON: - { - ktime_t delta_t; - - pr_info("%s to DCON\n", __func__); - - /* Clear DCONLOAD - this implies that the DCON is in control */ - pdata->set_dconload(0); - dcon->load_time = ktime_get(); - - wait_event_timeout(dcon->waitq, dcon->switched, HZ / 2); - - if (!dcon->switched) { - pr_err("Timeout entering DCON mode; expect a screen glitch.\n"); - } else { - /* sometimes the DCON doesn't follow its own rules, - * and doesn't wait for two vsync pulses before - * ack'ing the frame load with an IRQ. the result - * is that the display shows the *previously* - * loaded frame. we can detect this by looking at - * the time between asserting DCONLOAD and the IRQ -- - * if it's less than 20msec, then the DCON couldn't - * have seen two VSYNC pulses. in that case we - * deassert and reassert, and hope for the best. - * see http://dev.laptop.org/ticket/9664 - */ - delta_t = ktime_sub(dcon->irq_time, dcon->load_time); - if (dcon->switched && ktime_to_ns(delta_t) - < NSEC_PER_MSEC * 20) { - pr_err("missed loading, retrying\n"); - pdata->set_dconload(1); - mdelay(41); - pdata->set_dconload(0); - dcon->load_time = ktime_get(); - mdelay(41); - } - } - - dcon_blank_fb(dcon, true); - pr_info("The DCON has control\n"); - break; - } - default: - BUG(); - } - - dcon->curr_src = source; -} - -static void dcon_set_source(struct dcon_priv *dcon, int arg) -{ - if (dcon->pending_src == arg) - return; - - dcon->pending_src = arg; - - if (dcon->curr_src != arg) - schedule_work(&dcon->switch_source); -} - -static void dcon_set_source_sync(struct dcon_priv *dcon, int arg) -{ - dcon_set_source(dcon, arg); - flush_work(&dcon->switch_source); -} - -static ssize_t dcon_mode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%4.4X\n", dcon->disp_mode); -} - -static ssize_t dcon_sleep_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->asleep); -} - -static ssize_t dcon_freeze_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0); -} - -static ssize_t dcon_mono_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->mono); -} - -static ssize_t dcon_resumeline_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", resumeline); -} - -static ssize_t dcon_mono_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long enable_mono; - int rc; - - rc = kstrtoul(buf, 10, &enable_mono); - if (rc) - return rc; - - dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false); - - return count; -} - -static ssize_t dcon_freeze_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - unsigned long output; - int ret; - - ret = kstrtoul(buf, 10, &output); - if (ret) - return ret; - - switch (output) { - case 0: - dcon_set_source(dcon, DCON_SOURCE_CPU); - break; - case 1: - dcon_set_source_sync(dcon, DCON_SOURCE_DCON); - break; - case 2: /* normally unused */ - dcon_set_source(dcon, DCON_SOURCE_DCON); - break; - default: - return -EINVAL; - } - - return count; -} - -static ssize_t dcon_resumeline_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned short rl; - int rc; - - rc = kstrtou16(buf, 10, &rl); - if (rc) - return rc; - - resumeline = rl; - dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline); - - return count; -} - -static ssize_t dcon_sleep_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long output; - int ret; - - ret = kstrtoul(buf, 10, &output); - if (ret) - return ret; - - dcon_sleep(dev_get_drvdata(dev), output ? true : false); - return count; -} - -static struct device_attribute dcon_device_files[] = { - __ATTR(mode, 0444, dcon_mode_show, NULL), - __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store), - __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store), - __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store), - __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store), -}; - -static int dcon_bl_update(struct backlight_device *dev) -{ - struct dcon_priv *dcon = bl_get_data(dev); - u8 level = backlight_get_brightness(dev) & 0x0F; - - if (level != dcon->bl_val) - dcon_set_backlight(dcon, level); - - /* power down the DCON when the screen is blanked */ - if (!dcon->ignore_fb_events) - dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK)); - - return 0; -} - -static int dcon_bl_get(struct backlight_device *dev) -{ - struct dcon_priv *dcon = bl_get_data(dev); - - return dcon->bl_val; -} - -static const struct backlight_ops dcon_bl_ops = { - .update_status = dcon_bl_update, - .get_brightness = dcon_bl_get, -}; - -static struct backlight_properties dcon_bl_props = { - .max_brightness = 15, - .type = BACKLIGHT_RAW, - .power = BACKLIGHT_POWER_ON, -}; - -static int dcon_reboot_notify(struct notifier_block *nb, - unsigned long foo, void *bar) -{ - struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb); - - if (!dcon || !dcon->client) - return NOTIFY_DONE; - - /* Turn off the DCON. Entirely. */ - dcon_write(dcon, DCON_REG_MODE, 0x39); - dcon_write(dcon, DCON_REG_MODE, 0x32); - return NOTIFY_DONE; -} - -static int unfreeze_on_panic(struct notifier_block *nb, - unsigned long e, void *p) -{ - pdata->set_dconload(1); - return NOTIFY_DONE; -} - -static struct notifier_block dcon_panic_nb = { - .notifier_call = unfreeze_on_panic, -}; - -static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - strscpy(info->type, "olpc_dcon", I2C_NAME_SIZE); - - return 0; -} - -static int dcon_probe(struct i2c_client *client) -{ - struct dcon_priv *dcon; - int rc, i, j; - - if (!pdata) - return -ENXIO; - - dcon = kzalloc(sizeof(*dcon), GFP_KERNEL); - if (!dcon) - return -ENOMEM; - - dcon->client = client; - init_waitqueue_head(&dcon->waitq); - INIT_WORK(&dcon->switch_source, dcon_source_switch); - dcon->reboot_nb.notifier_call = dcon_reboot_notify; - dcon->reboot_nb.priority = -1; - - i2c_set_clientdata(client, dcon); - - if (num_registered_fb < 1) { - dev_err(&client->dev, "DCON driver requires a registered fb\n"); - rc = -EIO; - goto einit; - } - dcon->fbinfo = registered_fb[0]; - - rc = dcon_hw_init(dcon, 1); - if (rc) - goto einit; - - /* Add the DCON device */ - - dcon_device = platform_device_alloc("dcon", -1); - - if (!dcon_device) { - pr_err("Unable to create the DCON device\n"); - rc = -ENOMEM; - goto eirq; - } - rc = platform_device_add(dcon_device); - platform_set_drvdata(dcon_device, dcon); - - if (rc) { - pr_err("Unable to add the DCON device\n"); - goto edev; - } - - for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) { - rc = device_create_file(&dcon_device->dev, - &dcon_device_files[i]); - if (rc) { - dev_err(&dcon_device->dev, "Cannot create sysfs file\n"); - goto ecreate; - } - } - - dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F; - - /* Add the backlight device for the DCON */ - dcon_bl_props.brightness = dcon->bl_val; - dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev, - dcon, &dcon_bl_ops, - &dcon_bl_props); - if (IS_ERR(dcon->bl_dev)) { - dev_err(&client->dev, "cannot register backlight dev (%ld)\n", - PTR_ERR(dcon->bl_dev)); - dcon->bl_dev = NULL; - } - - register_reboot_notifier(&dcon->reboot_nb); - atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb); - - return 0; - - ecreate: - for (j = 0; j < i; j++) - device_remove_file(&dcon_device->dev, &dcon_device_files[j]); - platform_device_del(dcon_device); - edev: - platform_device_put(dcon_device); - dcon_device = NULL; - eirq: - free_irq(DCON_IRQ, dcon); - einit: - kfree(dcon); - return rc; -} - -static void dcon_remove(struct i2c_client *client) -{ - struct dcon_priv *dcon = i2c_get_clientdata(client); - - unregister_reboot_notifier(&dcon->reboot_nb); - atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb); - - free_irq(DCON_IRQ, dcon); - - backlight_device_unregister(dcon->bl_dev); - - if (dcon_device) - platform_device_unregister(dcon_device); - cancel_work_sync(&dcon->switch_source); - - kfree(dcon); -} - -#ifdef CONFIG_PM -static int dcon_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dcon_priv *dcon = i2c_get_clientdata(client); - - if (!dcon->asleep) { - /* Set up the DCON to have the source */ - dcon_set_source_sync(dcon, DCON_SOURCE_DCON); - } - - return 0; -} - -static int dcon_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dcon_priv *dcon = i2c_get_clientdata(client); - - if (!dcon->asleep) { - dcon_bus_stabilize(dcon, 0); - dcon_set_source(dcon, DCON_SOURCE_CPU); - } - - return 0; -} - -#else - -#define dcon_suspend NULL -#define dcon_resume NULL - -#endif /* CONFIG_PM */ - -irqreturn_t dcon_interrupt(int irq, void *id) -{ - struct dcon_priv *dcon = id; - u8 status; - - if (pdata->read_status(&status)) - return IRQ_NONE; - - switch (status & 3) { - case 3: - pr_debug("DCONLOAD_MISSED interrupt\n"); - break; - - case 2: /* switch to DCON mode */ - case 1: /* switch to CPU mode */ - dcon->switched = true; - dcon->irq_time = ktime_get(); - wake_up(&dcon->waitq); - break; - - case 0: - /* workaround resume case: the DCON (on 1.5) doesn't - * ever assert status 0x01 when switching to CPU mode - * during resume. this is because DCONLOAD is de-asserted - * _immediately_ upon exiting S3, so the actual release - * of the DCON happened long before this point. - * see http://dev.laptop.org/ticket/9869 - */ - if (dcon->curr_src != dcon->pending_src && !dcon->switched) { - dcon->switched = true; - dcon->irq_time = ktime_get(); - wake_up(&dcon->waitq); - pr_debug("switching w/ status 0/0\n"); - } else { - pr_debug("scanline interrupt w/CPU\n"); - } - } - - return IRQ_HANDLED; -} - -static const struct dev_pm_ops dcon_pm_ops = { - .suspend = dcon_suspend, - .resume = dcon_resume, -}; - -static const struct i2c_device_id dcon_idtable[] = { - { "olpc_dcon", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, dcon_idtable); - -static struct i2c_driver dcon_driver = { - .driver = { - .name = "olpc_dcon", - .pm = &dcon_pm_ops, - }, - .class = I2C_CLASS_HWMON, - .id_table = dcon_idtable, - .probe = dcon_probe, - .remove = dcon_remove, - .detect = dcon_detect, - .address_list = normal_i2c, -}; - -static int __init olpc_dcon_init(void) -{ - /* XO-1.5 */ - if (olpc_board_at_least(olpc_board(0xd0))) - pdata = &dcon_pdata_xo_1_5; - else - pdata = &dcon_pdata_xo_1; - - return i2c_add_driver(&dcon_driver); -} - -static void __exit olpc_dcon_exit(void) -{ - i2c_del_driver(&dcon_driver); -} - -module_init(olpc_dcon_init); -module_exit(olpc_dcon_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h deleted file mode 100644 index 41bd1360b56e479837256851e976001c2ab7dc2a..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef OLPC_DCON_H_ -#define OLPC_DCON_H_ - -#include <linux/notifier.h> -#include <linux/workqueue.h> - -/* DCON registers */ - -#define DCON_REG_ID 0 -#define DCON_REG_MODE 1 - -#define MODE_PASSTHRU BIT(0) -#define MODE_SLEEP BIT(1) -#define MODE_SLEEP_AUTO BIT(2) -#define MODE_BL_ENABLE BIT(3) -#define MODE_BLANK BIT(4) -#define MODE_CSWIZZLE BIT(5) -#define MODE_COL_AA BIT(6) -#define MODE_MONO_LUMA BIT(7) -#define MODE_SCAN_INT BIT(8) -#define MODE_CLOCKDIV BIT(9) -#define MODE_DEBUG BIT(14) -#define MODE_SELFTEST BIT(15) - -#define DCON_REG_HRES 0x2 -#define DCON_REG_HTOTAL 0x3 -#define DCON_REG_HSYNC_WIDTH 0x4 -#define DCON_REG_VRES 0x5 -#define DCON_REG_VTOTAL 0x6 -#define DCON_REG_VSYNC_WIDTH 0x7 -#define DCON_REG_TIMEOUT 0x8 -#define DCON_REG_SCAN_INT 0x9 -#define DCON_REG_BRIGHT 0xa -#define DCON_REG_MEM_OPT_A 0x41 -#define DCON_REG_MEM_OPT_B 0x42 - -/* Load Delay Locked Loop (DLL) settings for clock delay */ -#define MEM_DLL_CLOCK_DELAY BIT(0) -/* Memory controller power down function */ -#define MEM_POWER_DOWN BIT(8) -/* Memory controller software reset */ -#define MEM_SOFT_RESET BIT(0) - -/* Status values */ - -#define DCONSTAT_SCANINT 0 -#define DCONSTAT_SCANINT_DCON 1 -#define DCONSTAT_DISPLAYLOAD 2 -#define DCONSTAT_MISSED 3 - -/* Source values */ - -#define DCON_SOURCE_DCON 0 -#define DCON_SOURCE_CPU 1 - -/* Interrupt */ -#define DCON_IRQ 6 - -struct dcon_priv { - struct i2c_client *client; - struct fb_info *fbinfo; - struct backlight_device *bl_dev; - - wait_queue_head_t waitq; - struct work_struct switch_source; - struct notifier_block reboot_nb; - - /* Shadow register for the DCON_REG_MODE register */ - u8 disp_mode; - - /* The current backlight value - this saves us some smbus traffic */ - u8 bl_val; - - /* Current source, initialized at probe time */ - int curr_src; - - /* Desired source */ - int pending_src; - - /* Variables used during switches */ - bool switched; - ktime_t irq_time; - ktime_t load_time; - - /* Current output type; true == mono, false == color */ - bool mono; - bool asleep; - /* This get set while controlling fb blank state from the driver */ - bool ignore_fb_events; -}; - -struct dcon_platform_data { - int (*init)(struct dcon_priv *dcon); - void (*bus_stabilize_wiggle)(void); - void (*set_dconload)(int load); - int (*read_status)(u8 *status); -}; - -struct dcon_gpio { - const char *name; - unsigned long flags; -}; - -#include <linux/interrupt.h> - -irqreturn_t dcon_interrupt(int irq, void *id); - -extern struct dcon_platform_data dcon_pdata_xo_1; -extern struct dcon_platform_data dcon_pdata_xo_1_5; - -#endif diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c deleted file mode 100644 index 02c059897784d18fba755a61ec8e79b2438e544b..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ /dev/null @@ -1,201 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Mainly by David Woodhouse, somewhat modified by Jordan Crouse - * - * Copyright © 2006-2007 Red Hat, Inc. - * Copyright © 2006-2007 Advanced Micro Devices, Inc. - * Copyright © 2009 VIA Technology, Inc. - * Copyright (c) 2010 Andres Salomon <dilinger@queued.net> - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/cs5535.h> -#include <linux/gpio/consumer.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <asm/olpc.h> - -#include "olpc_dcon.h" - -enum dcon_gpios { - OLPC_DCON_STAT0, - OLPC_DCON_STAT1, - OLPC_DCON_IRQ, - OLPC_DCON_LOAD, - OLPC_DCON_BLANK, -}; - -static const struct dcon_gpio gpios_asis[] = { - [OLPC_DCON_STAT0] = { .name = "dcon_stat0", .flags = GPIOD_ASIS }, - [OLPC_DCON_STAT1] = { .name = "dcon_stat1", .flags = GPIOD_ASIS }, - [OLPC_DCON_IRQ] = { .name = "dcon_irq", .flags = GPIOD_ASIS }, - [OLPC_DCON_LOAD] = { .name = "dcon_load", .flags = GPIOD_ASIS }, - [OLPC_DCON_BLANK] = { .name = "dcon_blank", .flags = GPIOD_ASIS }, -}; - -static struct gpio_desc *gpios[5]; - -static int dcon_init_xo_1(struct dcon_priv *dcon) -{ - unsigned char lob; - int ret, i; - const struct dcon_gpio *pin = &gpios_asis[0]; - - for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) { - gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name, - pin[i].flags); - if (IS_ERR(gpios[i])) { - ret = PTR_ERR(gpios[i]); - pr_err("failed to request %s GPIO: %d\n", pin[i].name, - ret); - return ret; - } - } - - /* Turn off the event enable for GPIO7 just to be safe */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); - - /* - * Determine the current state by reading the GPIO bit; earlier - * stages of the boot process have established the state. - * - * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here; - * this is because OFW will disable input for the pin and set a value.. - * READ_BACK will only contain a valid value if input is enabled and - * then a value is set. So, future readings of the pin can use - * READ_BACK, but the first one cannot. Awesome, huh? - */ - dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL) - ? DCON_SOURCE_CPU - : DCON_SOURCE_DCON; - dcon->pending_src = dcon->curr_src; - - /* Set the directions for the GPIO pins */ - gpiod_direction_input(gpios[OLPC_DCON_STAT0]); - gpiod_direction_input(gpios[OLPC_DCON_STAT1]); - gpiod_direction_input(gpios[OLPC_DCON_IRQ]); - gpiod_direction_input(gpios[OLPC_DCON_BLANK]); - gpiod_direction_output(gpios[OLPC_DCON_LOAD], - dcon->curr_src == DCON_SOURCE_CPU); - - /* Set up the interrupt mappings */ - - /* Set the IRQ to pair 2 */ - cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0); - - /* Enable group 2 to trigger the DCON interrupt */ - cs5535_gpio_set_irq(2, DCON_IRQ); - - /* Select edge level for interrupt (in PIC) */ - lob = inb(0x4d0); - lob &= ~(1 << DCON_IRQ); - outb(lob, 0x4d0); - - /* Register the interrupt handler */ - if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) { - pr_err("failed to request DCON's irq\n"); - return -EIO; - } - - /* Clear INV_EN for GPIO7 (DCONIRQ) */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT); - - /* Enable filter for GPIO12 (DCONBLANK) */ - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER); - - /* Disable filter for GPIO7 */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER); - - /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT); - cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT); - - /* Add GPIO12 to the Filter Event Pair #7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL); - - /* Turn off negative Edge Enable for GPIO12 */ - cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN); - - /* Enable negative Edge Enable for GPIO7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN); - - /* Zero the filter amount for Filter Event Pair #7 */ - cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT); - - /* Clear the negative edge status for GPIO7 and GPIO12 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS); - - /* FIXME: Clear the positive status as well, just to be sure */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS); - - /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE); - - return 0; -} - -static void dcon_wiggle_xo_1(void) -{ - int x; - - /* - * According to HiMax, when powering the DCON up we should hold - * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON - * state machine to reset to a (sane) initial state. Mitch Bradley - * did some testing and discovered that holding for 16 SMB_CLK cycles - * worked a lot more reliably, so that's what we do here. - * - * According to the cs5536 spec, to set GPIO14 to SMB_CLK we must - * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and - * GPIO15. - */ - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); - - for (x = 0; x < 16; x++) { - udelay(5); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - udelay(5); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - } - udelay(5); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); -} - -static void dcon_set_dconload_1(int val) -{ - gpiod_set_value(gpios[OLPC_DCON_LOAD], val); -} - -static int dcon_read_status_xo_1(u8 *status) -{ - *status = gpiod_get_value(gpios[OLPC_DCON_STAT0]); - *status |= gpiod_get_value(gpios[OLPC_DCON_STAT1]) << 1; - - /* Clear the negative edge status for GPIO7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); - - return 0; -} - -struct dcon_platform_data dcon_pdata_xo_1 = { - .init = dcon_init_xo_1, - .bus_stabilize_wiggle = dcon_wiggle_xo_1, - .set_dconload = dcon_set_dconload_1, - .read_status = dcon_read_status_xo_1, -}; diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c deleted file mode 100644 index 52cdcd2a89d6f39bbc344eda483c5ecb8316476d..0000000000000000000000000000000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2009,2010 One Laptop per Child - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/acpi.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/gpio/consumer.h> -#include <linux/gpio/machine.h> -#include <asm/olpc.h> - -/* TODO: this eventually belongs in linux/vx855.h */ -#define NR_VX855_GPI 14 -#define NR_VX855_GPO 13 -#define NR_VX855_GPIO 15 - -#define VX855_GPI(n) (n) -#define VX855_GPO(n) (NR_VX855_GPI + (n)) -#define VX855_GPIO(n) (NR_VX855_GPI + NR_VX855_GPO + (n)) - -#include "olpc_dcon.h" - -/* Hardware setup on the XO 1.5: - * DCONLOAD connects to VX855_GPIO1 (not SMBCK2) - * DCONBLANK connects to VX855_GPIO8 (not SSPICLK) unused in driver - * DCONSTAT0 connects to VX855_GPI10 (not SSPISDI) - * DCONSTAT1 connects to VX855_GPI11 (not nSSPISS) - * DCONIRQ connects to VX855_GPIO12 - * DCONSMBDATA connects to VX855 graphics CRTSPD - * DCONSMBCLK connects to VX855 graphics CRTSPCLK - */ - -#define VX855_GENL_PURPOSE_OUTPUT 0x44c /* PMIO_Rx4c-4f */ -#define VX855_GPI_STATUS_CHG 0x450 /* PMIO_Rx50 */ -#define VX855_GPI_SCI_SMI 0x452 /* PMIO_Rx52 */ -#define BIT_GPIO12 0x40 - -#define PREFIX "OLPC DCON:" - -enum dcon_gpios { - OLPC_DCON_STAT0, - OLPC_DCON_STAT1, - OLPC_DCON_LOAD, -}; - -struct gpiod_lookup_table gpios_table = { - .dev_id = NULL, - .table = { - GPIO_LOOKUP("VX855 South Bridge", VX855_GPIO(1), "dcon_load", - GPIO_ACTIVE_LOW), - GPIO_LOOKUP("VX855 South Bridge", VX855_GPI(10), "dcon_stat0", - GPIO_ACTIVE_LOW), - GPIO_LOOKUP("VX855 South Bridge", VX855_GPI(11), "dcon_stat1", - GPIO_ACTIVE_LOW), - { }, - }, -}; - -static const struct dcon_gpio gpios_asis[] = { - [OLPC_DCON_STAT0] = { .name = "dcon_stat0", .flags = GPIOD_ASIS }, - [OLPC_DCON_STAT1] = { .name = "dcon_stat1", .flags = GPIOD_ASIS }, - [OLPC_DCON_LOAD] = { .name = "dcon_load", .flags = GPIOD_ASIS }, -}; - -static struct gpio_desc *gpios[3]; - -static void dcon_clear_irq(void) -{ - /* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */ - outb(BIT_GPIO12, VX855_GPI_STATUS_CHG); -} - -static int dcon_was_irq(void) -{ - u8 tmp; - - /* irq status will appear in PMIO_Rx50[6] on gpio12 */ - tmp = inb(VX855_GPI_STATUS_CHG); - - return !!(tmp & BIT_GPIO12); -} - -static int dcon_init_xo_1_5(struct dcon_priv *dcon) -{ - unsigned int irq; - const struct dcon_gpio *pin = &gpios_asis[0]; - int i; - int ret; - - /* Add GPIO look up table */ - gpios_table.dev_id = dev_name(&dcon->client->dev); - gpiod_add_lookup_table(&gpios_table); - - /* Get GPIO descriptor */ - for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) { - gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name, - pin[i].flags); - if (IS_ERR(gpios[i])) { - ret = PTR_ERR(gpios[i]); - pr_err("failed to request %s GPIO: %d\n", pin[i].name, - ret); - return ret; - } - } - - dcon_clear_irq(); - - /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */ - outb(inb(VX855_GPI_SCI_SMI) | BIT_GPIO12, VX855_GPI_SCI_SMI); - - /* Determine the current state of DCONLOAD, likely set by firmware */ - /* GPIO1 */ - dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ? - DCON_SOURCE_CPU : DCON_SOURCE_DCON; - dcon->pending_src = dcon->curr_src; - - /* we're sharing the IRQ with ACPI */ - irq = acpi_gbl_FADT.sci_interrupt; - if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) { - pr_err("DCON (IRQ%d) allocation failed\n", irq); - return 1; - } - - return 0; -} - -static void set_i2c_line(int sda, int scl) -{ - unsigned char tmp; - unsigned int port = 0x26; - - /* FIXME: This directly accesses the CRT GPIO controller !!! */ - outb(port, 0x3c4); - tmp = inb(0x3c5); - - if (scl) - tmp |= 0x20; - else - tmp &= ~0x20; - - if (sda) - tmp |= 0x10; - else - tmp &= ~0x10; - - tmp |= 0x01; - - outb(port, 0x3c4); - outb(tmp, 0x3c5); -} - -static void dcon_wiggle_xo_1_5(void) -{ - int x; - - /* - * According to HiMax, when powering the DCON up we should hold - * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON - * state machine to reset to a (sane) initial state. Mitch Bradley - * did some testing and discovered that holding for 16 SMB_CLK cycles - * worked a lot more reliably, so that's what we do here. - */ - set_i2c_line(1, 1); - - for (x = 0; x < 16; x++) { - udelay(5); - set_i2c_line(1, 0); - udelay(5); - set_i2c_line(1, 1); - } - udelay(5); - - /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */ - outb(inb(VX855_GPI_SCI_SMI) | BIT_GPIO12, VX855_GPI_SCI_SMI); -} - -static void dcon_set_dconload_xo_1_5(int val) -{ - gpiod_set_value(gpios[OLPC_DCON_LOAD], val); -} - -static int dcon_read_status_xo_1_5(u8 *status) -{ - if (!dcon_was_irq()) - return -1; - - /* i believe this is the same as "inb(0x44b) & 3" */ - *status = gpiod_get_value(gpios[OLPC_DCON_STAT0]); - *status |= gpiod_get_value(gpios[OLPC_DCON_STAT1]) << 1; - - dcon_clear_irq(); - - return 0; -} - -struct dcon_platform_data dcon_pdata_xo_1_5 = { - .init = dcon_init_xo_1_5, - .bus_stabilize_wiggle = dcon_wiggle_xo_1_5, - .set_dconload = dcon_set_dconload_xo_1_5, - .read_status = dcon_read_status_xo_1_5, -}; diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig deleted file mode 100644 index 8de26425225b380ed62cb224676a0b00445a8439..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config R8712U - tristate "RealTek RTL8712U (RTL8192SU) Wireless LAN NIC driver" - depends on WLAN && USB && CFG80211 - select WIRELESS_EXT - select WEXT_PRIV - select FW_LOADER - help - This option adds the Realtek RTL8712 USB device such as the - D-Link DWA-130. - - If built as a module, it will be called r8712u. - -config R8712_TX_AGGR - bool "Realtek RTL8712U Transmit Aggregation code" - depends on R8712U && BROKEN - help - This option provides transmit aggregation for the Realtek - RTL8712 USB device. - - diff --git a/drivers/staging/rtl8712/Makefile b/drivers/staging/rtl8712/Makefile deleted file mode 100644 index 3ae216b6621b1c95d8aed2e51ebda955fcbead7f..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -r8712u-y := \ - rtl871x_cmd.o \ - rtl8712_cmd.o \ - rtl871x_security.o \ - rtl871x_eeprom.o \ - rtl8712_efuse.o \ - hal_init.o \ - usb_halinit.o \ - usb_ops.o \ - usb_ops_linux.o \ - rtl871x_io.o \ - rtl8712_io.o \ - rtl871x_ioctl_linux.o \ - rtl871x_ioctl_rtl.o \ - rtl871x_ioctl_set.o \ - rtl8712_led.o \ - rtl871x_mlme.o \ - ieee80211.o \ - rtl871x_mp_ioctl.o \ - rtl871x_mp.o \ - mlme_linux.o \ - recv_linux.o \ - xmit_linux.o \ - usb_intf.o \ - os_intfs.o \ - rtl871x_pwrctrl.o \ - rtl8712_recv.o \ - rtl871x_recv.o \ - rtl871x_sta_mgt.o \ - rtl871x_xmit.o \ - rtl8712_xmit.o - -obj-$(CONFIG_R8712U) := r8712u.o - diff --git a/drivers/staging/rtl8712/TODO b/drivers/staging/rtl8712/TODO deleted file mode 100644 index 5aed36efa7cbf4be1ce7c8ff592b6c0eca74c4ac..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/TODO +++ /dev/null @@ -1,12 +0,0 @@ -TODO: -- merge Realtek's bugfixes and new features into the driver -- switch to use MAC80211 -- checkpatch.pl fixes - only a few remain - -A replacement for this driver with MAC80211 support is available -at https://github.com/chunkeey/rtl8192su - -Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, -Larry Finger <Larry.Finger@lwfinger.net>, -Florian Schilhabel <florian.c.schilhabel@googlemail.com> and -Linux Driver Project Developer List <driverdev-devel@linuxdriverproject.org>. diff --git a/drivers/staging/rtl8712/basic_types.h b/drivers/staging/rtl8712/basic_types.h deleted file mode 100644 index aecded87dd4c8733742c433f4111b009f9f82c27..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/basic_types.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __BASIC_TYPES_H__ -#define __BASIC_TYPES_H__ - -#include <linux/types.h> - -#define sint signed int - -/* Should we extend this to be host_addr_t and target_addr_t for case: - * host : x86_64 - * target : mips64 - */ -#define addr_t unsigned long - -#endif /*__BASIC_TYPES_H__*/ - diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h deleted file mode 100644 index 76ac798642bd2b01e36a170061d7f7a7914d6ddb..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/drv_types.h +++ /dev/null @@ -1,175 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -/* --------------------------------------------------------------------- - * - * For type defines and data structure defines - * - * --------------------------------------------------------------------- - */ -#ifndef __DRV_TYPES_H__ -#define __DRV_TYPES_H__ - -struct _adapter; - -#include "osdep_service.h" -#include "wlan_bssdef.h" -#include "rtl8712_spec.h" -#include "rtl8712_hal.h" -#include <linux/mutex.h> -#include <linux/completion.h> - -enum _NIC_VERSION { - RTL8711_NIC, - RTL8712_NIC, - RTL8713_NIC, - RTL8716_NIC -}; - -struct qos_priv { - /* bit mask option: u-apsd, s-apsd, ts, block ack... */ - unsigned int qos_option; -}; - -#include "rtl871x_ht.h" -#include "rtl871x_cmd.h" -#include "rtl871x_xmit.h" -#include "rtl871x_recv.h" -#include "rtl871x_security.h" -#include "rtl871x_pwrctrl.h" -#include "rtl871x_io.h" -#include "rtl871x_eeprom.h" -#include "sta_info.h" -#include "rtl871x_mlme.h" -#include "rtl871x_mp.h" -#include "rtl871x_debug.h" -#include "rtl871x_rf.h" -#include "rtl871x_event.h" -#include "rtl871x_led.h" - -#define SPEC_DEV_ID_DISABLE_HT BIT(1) - -struct specific_device_id { - u32 flags; - u16 idVendor; - u16 idProduct; - -}; - -struct registry_priv { - u8 chip_version; - u8 rfintfs; - u8 lbkmode; - u8 hci; - u8 network_mode; /*infra, ad-hoc, auto*/ - struct ndis_802_11_ssid ssid; - u8 channel;/* ad-hoc support requirement */ - u8 wireless_mode;/* A, B, G, auto */ - u8 vrtl_carrier_sense; /*Enable, Disable, Auto*/ - u8 vcs_type;/*RTS/CTS, CTS-to-self*/ - u16 rts_thresh; - u16 frag_thresh; - u8 preamble;/*long, short, auto*/ - u8 scan_mode;/*active, passive*/ - u8 adhoc_tx_pwr; - u8 soft_ap; - u8 smart_ps; - u8 power_mgnt; - u8 radio_enable; - u8 long_retry_lmt; - u8 short_retry_lmt; - u16 busy_thresh; - u8 ack_policy; - u8 mp_mode; - u8 software_encrypt; - u8 software_decrypt; - /* UAPSD */ - u8 wmm_enable; - u8 uapsd_enable; - u8 uapsd_max_sp; - u8 uapsd_acbk_en; - u8 uapsd_acbe_en; - u8 uapsd_acvi_en; - u8 uapsd_acvo_en; - - struct wlan_bssid_ex dev_network; - - u8 ht_enable; - u8 cbw40_enable; - u8 ampdu_enable;/*for tx*/ - u8 rf_config; - u8 low_power; - u8 wifi_test; -}; - -struct dvobj_priv { - struct _adapter *padapter; - u32 nr_endpoint; - u8 ishighspeed; - uint (*inirp_init)(struct _adapter *adapter); - uint (*inirp_deinit)(struct _adapter *adapter); - struct usb_device *pusbdev; -}; - -/** - * struct _adapter - the main adapter structure for this device. - * - * bup: True indicates that the interface is up. - */ -struct _adapter { - struct dvobj_priv dvobjpriv; - struct mlme_priv mlmepriv; - struct cmd_priv cmdpriv; - struct evt_priv evtpriv; - struct io_queue *pio_queue; - struct xmit_priv xmitpriv; - struct recv_priv recvpriv; - struct sta_priv stapriv; - struct security_priv securitypriv; - struct registry_priv registrypriv; - struct wlan_acl_pool acl_list; - struct pwrctrl_priv pwrctrlpriv; - struct eeprom_priv eeprompriv; - struct hal_priv halpriv; - struct led_priv ledpriv; - struct mp_priv mppriv; - bool driver_stopped; - bool surprise_removed; - bool suspended; - u8 eeprom_address_size; - u8 hw_init_completed; - struct task_struct *cmd_thread; - uint (*dvobj_init)(struct _adapter *adapter); - void (*dvobj_deinit)(struct _adapter *adapter); - struct net_device *pnetdev; - int bup; - struct net_device_stats stats; - struct iw_statistics iwstats; - int pid; /*process id from UI*/ - struct work_struct wk_filter_rx_ff0; - const struct firmware *fw; - struct usb_interface *pusb_intf; - struct mutex mutex_start; - struct completion rtl8712_fw_ready; - struct completion rx_filter_ready; -}; - -static inline u8 *myid(struct eeprom_priv *peepriv) -{ - return peepriv->mac_addr; -} - -u8 r8712_usb_hal_bus_init(struct _adapter *adapter); - -#endif /*__DRV_TYPES_H__*/ - diff --git a/drivers/staging/rtl8712/ethernet.h b/drivers/staging/rtl8712/ethernet.h deleted file mode 100644 index 4b9b8a97a0bc6c950a465591caa4e00c68fe6069..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/ethernet.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __INC_ETHERNET_H -#define __INC_ETHERNET_H - -#define ETHERNET_HEADER_SIZE 14 /*!< Ethernet Header Length*/ -#define LLC_HEADER_SIZE 6 /*!< LLC Header Length*/ - -#endif /* #ifndef __INC_ETHERNET_H */ - diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c deleted file mode 100644 index 1148075f0cd64c5045c6df8bf5a228031f8bfe98..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/hal_init.c +++ /dev/null @@ -1,401 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _HAL_INIT_C_ - -#include <linux/usb.h> -#include <linux/device.h> -#include <linux/usb/ch9.h> -#include <linux/firmware.h> -#include <linux/module.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "usb_osintf.h" - -#define FWBUFF_ALIGN_SZ 512 -#define MAX_DUMP_FWSZ (48 * 1024) - -static void rtl871x_load_fw_fail(struct _adapter *adapter) -{ - struct usb_device *udev = adapter->dvobjpriv.pusbdev; - struct device *dev = &udev->dev; - struct device *parent = dev->parent; - - complete(&adapter->rtl8712_fw_ready); - - dev_err(&udev->dev, "r8712u: Firmware request failed\n"); - - if (parent) - device_lock(parent); - - device_release_driver(dev); - - if (parent) - device_unlock(parent); -} - -static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) -{ - struct _adapter *adapter = context; - - if (!firmware) { - rtl871x_load_fw_fail(adapter); - return; - } - adapter->fw = firmware; - /* firmware available - start netdev */ - register_netdev(adapter->pnetdev); - complete(&adapter->rtl8712_fw_ready); -} - -static const char firmware_file[] = "rtlwifi/rtl8712u.bin"; - -int rtl871x_load_fw(struct _adapter *padapter) -{ - struct device *dev = &padapter->dvobjpriv.pusbdev->dev; - int rc; - - init_completion(&padapter->rtl8712_fw_ready); - dev_info(dev, "r8712u: Loading firmware from \"%s\"\n", firmware_file); - rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev, - GFP_KERNEL, padapter, rtl871x_load_fw_cb); - if (rc) - dev_err(dev, "r8712u: Firmware request error %d\n", rc); - return rc; -} -MODULE_FIRMWARE("rtlwifi/rtl8712u.bin"); - -static u32 rtl871x_open_fw(struct _adapter *adapter, const u8 **mappedfw) -{ - if (adapter->fw->size > 200000) { - dev_err(&adapter->pnetdev->dev, "r8712u: Bad fw->size of %zu\n", - adapter->fw->size); - return 0; - } - *mappedfw = adapter->fw->data; - return adapter->fw->size; -} - -static void fill_fwpriv(struct _adapter *adapter, struct fw_priv *fwpriv) -{ - struct dvobj_priv *dvobj = &adapter->dvobjpriv; - struct registry_priv *regpriv = &adapter->registrypriv; - - memset(fwpriv, 0, sizeof(struct fw_priv)); - /* todo: check if needs endian conversion */ - fwpriv->hci_sel = RTL8712_HCI_TYPE_72USB; - fwpriv->usb_ep_num = (u8)dvobj->nr_endpoint; - fwpriv->bw_40MHz_en = regpriv->cbw40_enable; - switch (regpriv->rf_config) { - case RTL8712_RF_1T1R: - fwpriv->rf_config = RTL8712_RFC_1T1R; - break; - case RTL8712_RF_2T2R: - fwpriv->rf_config = RTL8712_RFC_2T2R; - break; - case RTL8712_RF_1T2R: - default: - fwpriv->rf_config = RTL8712_RFC_1T2R; - } - fwpriv->mp_mode = (regpriv->mp_mode == 1); - /* 0:off 1:on 2:auto */ - fwpriv->vcs_type = regpriv->vrtl_carrier_sense; - fwpriv->vcs_mode = regpriv->vcs_type; /* 1:RTS/CTS 2:CTS to self */ - /* default enable turbo_mode */ - fwpriv->turbo_mode = (regpriv->wifi_test != 1); - fwpriv->low_power_mode = regpriv->low_power; -} - -static void update_fwhdr(struct fw_hdr *pfwhdr, const u8 *pmappedfw) -{ - pfwhdr->signature = le16_to_cpu(*(__le16 *)pmappedfw); - pfwhdr->version = le16_to_cpu(*(__le16 *)(pmappedfw + 2)); - /* define the size of boot loader */ - pfwhdr->dmem_size = le32_to_cpu(*(__le32 *)(pmappedfw + 4)); - /* define the size of FW in IMEM */ - pfwhdr->img_IMEM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 8)); - /* define the size of FW in SRAM */ - pfwhdr->img_SRAM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 12)); - /* define the size of DMEM variable */ - pfwhdr->fw_priv_sz = le32_to_cpu(*(__le32 *)(pmappedfw + 16)); -} - -static u8 chk_fwhdr(struct fw_hdr *pfwhdr, u32 ulfilelength) -{ - u32 fwhdrsz, fw_sz; - - /* check signature */ - if ((pfwhdr->signature != 0x8712) && (pfwhdr->signature != 0x8192)) - return _FAIL; - /* check fw_priv_sze & sizeof(struct fw_priv) */ - if (pfwhdr->fw_priv_sz != sizeof(struct fw_priv)) - return _FAIL; - /* check fw_sz & image_fw_sz */ - fwhdrsz = offsetof(struct fw_hdr, fwpriv) + pfwhdr->fw_priv_sz; - fw_sz = fwhdrsz + pfwhdr->img_IMEM_size + pfwhdr->img_SRAM_size + - pfwhdr->dmem_size; - if (fw_sz != ulfilelength) - return _FAIL; - return _SUCCESS; -} - -static u8 rtl8712_dl_fw(struct _adapter *adapter) -{ - sint i; - u8 tmp8, tmp8_a; - u16 tmp16; - u32 maxlen = 0; /* for compare usage */ - uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */ - struct fw_hdr fwhdr; - u32 ulfilelength; /* FW file size */ - const u8 *mappedfw = NULL; - u8 *tmpchar = NULL, *payload, *ptr; - struct tx_desc *txdesc; - u32 txdscp_sz = sizeof(struct tx_desc); - u8 ret = _FAIL; - - ulfilelength = rtl871x_open_fw(adapter, &mappedfw); - if (mappedfw && (ulfilelength > 0)) { - update_fwhdr(&fwhdr, mappedfw); - if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL) - return ret; - fill_fwpriv(adapter, &fwhdr.fwpriv); - /* firmware check ok */ - maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ? - fwhdr.img_IMEM_size : fwhdr.img_SRAM_size; - maxlen += txdscp_sz; - tmpchar = kmalloc(maxlen + FWBUFF_ALIGN_SZ, GFP_KERNEL); - if (!tmpchar) - return ret; - - txdesc = (struct tx_desc *)(tmpchar + FWBUFF_ALIGN_SZ - - ((addr_t)(tmpchar) & (FWBUFF_ALIGN_SZ - 1))); - payload = (u8 *)(txdesc) + txdscp_sz; - ptr = (u8 *)mappedfw + offsetof(struct fw_hdr, fwpriv) + - fwhdr.fw_priv_sz; - /* Download FirmWare */ - /* 1. determine IMEM code size and Load IMEM Code Section */ - imem_sz = fwhdr.img_IMEM_size; - do { - memset(txdesc, 0, TXDESC_SIZE); - if (imem_sz > MAX_DUMP_FWSZ/*49152*/) { - dump_imem_sz = MAX_DUMP_FWSZ; - } else { - dump_imem_sz = imem_sz; - txdesc->txdw0 |= cpu_to_le32(BIT(28)); - } - txdesc->txdw0 |= cpu_to_le32(dump_imem_sz & - 0x0000ffff); - memcpy(payload, ptr, dump_imem_sz); - r8712_write_mem(adapter, RTL8712_DMA_VOQ, - dump_imem_sz + TXDESC_SIZE, - (u8 *)txdesc); - ptr += dump_imem_sz; - imem_sz -= dump_imem_sz; - } while (imem_sz > 0); - i = 10; - tmp16 = r8712_read16(adapter, TCR); - while (((tmp16 & _IMEM_CODE_DONE) == 0) && (i > 0)) { - usleep_range(10, 1000); - tmp16 = r8712_read16(adapter, TCR); - i--; - } - if (i == 0 || (tmp16 & _IMEM_CHK_RPT) == 0) - goto exit_fail; - - /* 2.Download EMEM code size and Load EMEM Code Section */ - emem_sz = fwhdr.img_SRAM_size; - do { - memset(txdesc, 0, TXDESC_SIZE); - if (emem_sz > MAX_DUMP_FWSZ) { /* max=48k */ - dump_emem_sz = MAX_DUMP_FWSZ; - } else { - dump_emem_sz = emem_sz; - txdesc->txdw0 |= cpu_to_le32(BIT(28)); - } - txdesc->txdw0 |= cpu_to_le32(dump_emem_sz & - 0x0000ffff); - memcpy(payload, ptr, dump_emem_sz); - r8712_write_mem(adapter, RTL8712_DMA_VOQ, - dump_emem_sz + TXDESC_SIZE, - (u8 *)txdesc); - ptr += dump_emem_sz; - emem_sz -= dump_emem_sz; - } while (emem_sz > 0); - i = 5; - tmp16 = r8712_read16(adapter, TCR); - while (((tmp16 & _EMEM_CODE_DONE) == 0) && (i > 0)) { - usleep_range(10, 1000); - tmp16 = r8712_read16(adapter, TCR); - i--; - } - if (i == 0 || (tmp16 & _EMEM_CHK_RPT) == 0) - goto exit_fail; - - /* 3.Enable CPU */ - tmp8 = r8712_read8(adapter, SYS_CLKR); - r8712_write8(adapter, SYS_CLKR, tmp8 | BIT(2)); - tmp8_a = r8712_read8(adapter, SYS_CLKR); - if (tmp8_a != (tmp8 | BIT(2))) - goto exit_fail; - - tmp8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, tmp8 | BIT(2)); - tmp8_a = r8712_read8(adapter, SYS_FUNC_EN + 1); - if (tmp8_a != (tmp8 | BIT(2))) - goto exit_fail; - - r8712_read32(adapter, TCR); - - /* 4.polling IMEM Ready */ - i = 100; - tmp16 = r8712_read16(adapter, TCR); - while (((tmp16 & _IMEM_RDY) == 0) && (i > 0)) { - msleep(20); - tmp16 = r8712_read16(adapter, TCR); - i--; - } - if (i == 0) { - r8712_write16(adapter, 0x10250348, 0xc000); - r8712_write16(adapter, 0x10250348, 0xc001); - r8712_write16(adapter, 0x10250348, 0x2000); - r8712_write16(adapter, 0x10250348, 0x2001); - r8712_write16(adapter, 0x10250348, 0x2002); - r8712_write16(adapter, 0x10250348, 0x2003); - goto exit_fail; - } - /* 5.Download DMEM code size and Load EMEM Code Section */ - memset(txdesc, 0, TXDESC_SIZE); - txdesc->txdw0 |= cpu_to_le32(fwhdr.fw_priv_sz & 0x0000ffff); - txdesc->txdw0 |= cpu_to_le32(BIT(28)); - memcpy(payload, &fwhdr.fwpriv, fwhdr.fw_priv_sz); - r8712_write_mem(adapter, RTL8712_DMA_VOQ, - fwhdr.fw_priv_sz + TXDESC_SIZE, (u8 *)txdesc); - - /* polling dmem code done */ - i = 100; - tmp16 = r8712_read16(adapter, TCR); - while (((tmp16 & _DMEM_CODE_DONE) == 0) && (i > 0)) { - msleep(20); - tmp16 = r8712_read16(adapter, TCR); - i--; - } - if (i == 0) - goto exit_fail; - - tmp8 = r8712_read8(adapter, 0x1025000A); - if (tmp8 & BIT(4)) /* When boot from EEPROM, - * & FW need more time to read EEPROM - */ - i = 60; - else /* boot from EFUSE */ - i = 30; - tmp16 = r8712_read16(adapter, TCR); - while (((tmp16 & _FWRDY) == 0) && (i > 0)) { - msleep(100); - tmp16 = r8712_read16(adapter, TCR); - i--; - } - if (i == 0) - goto exit_fail; - } else { - goto exit_fail; - } - ret = _SUCCESS; - -exit_fail: - kfree(tmpchar); - return ret; -} - -uint rtl8712_hal_init(struct _adapter *padapter) -{ - u32 val32; - int i; - - /* r8712 firmware download */ - if (rtl8712_dl_fw(padapter) != _SUCCESS) - return _FAIL; - - netdev_info(padapter->pnetdev, "1 RCR=0x%x\n", - r8712_read32(padapter, RCR)); - val32 = r8712_read32(padapter, RCR); - r8712_write32(padapter, RCR, (val32 | BIT(26))); /* Enable RX TCP - * Checksum offload - */ - netdev_info(padapter->pnetdev, "2 RCR=0x%x\n", - r8712_read32(padapter, RCR)); - val32 = r8712_read32(padapter, RCR); - r8712_write32(padapter, RCR, (val32 | BIT(25))); /* Append PHY status */ - val32 = r8712_read32(padapter, 0x10250040); - r8712_write32(padapter, 0x10250040, (val32 & 0x00FFFFFF)); - /* for usb rx aggregation */ - r8712_write8(padapter, 0x102500B5, r8712_read8(padapter, 0x102500B5) | - BIT(0)); /* page = 128bytes */ - r8712_write8(padapter, 0x102500BD, r8712_read8(padapter, 0x102500BD) | - BIT(7)); /* enable usb rx aggregation */ - r8712_write8(padapter, 0x102500D9, 1); /* TH=1 => means that invalidate - * usb rx aggregation - */ - r8712_write8(padapter, 0x1025FE5B, 0x04); /* 1.7ms/4 */ - /* Fix the RX FIFO issue(USB error) */ - r8712_write8(padapter, 0x1025fe5C, r8712_read8(padapter, 0x1025fe5C) - | BIT(7)); - for (i = 0; i < ETH_ALEN; i++) - padapter->eeprompriv.mac_addr[i] = r8712_read8(padapter, - MACID + i); - return _SUCCESS; -} - -uint rtl8712_hal_deinit(struct _adapter *padapter) -{ - r8712_write8(padapter, RF_CTRL, 0x00); - /* Turn off BB */ - msleep(20); - /* Turn off MAC */ - r8712_write8(padapter, SYS_CLKR + 1, 0x38); /* Switch Control Path */ - r8712_write8(padapter, SYS_FUNC_EN + 1, 0x70); - r8712_write8(padapter, PMC_FSM, 0x06); /* Enable Loader Data Keep */ - r8712_write8(padapter, SYS_ISO_CTRL, 0xF9); /* Isolation signals from - * CORE, PLL - */ - r8712_write8(padapter, SYS_ISO_CTRL + 1, 0xe8); /* Enable EFUSE 1.2V */ - r8712_write8(padapter, AFE_PLL_CTRL, 0x00); /* Disable AFE PLL. */ - r8712_write8(padapter, LDOA15_CTRL, 0x54); /* Disable A15V */ - r8712_write8(padapter, SYS_FUNC_EN + 1, 0x50); /* Disable E-Fuse 1.2V */ - r8712_write8(padapter, LDOV12D_CTRL, 0x24); /* Disable LDO12(for CE) */ - r8712_write8(padapter, AFE_MISC, 0x30); /* Disable AFE BG&MB */ - /* Option for Disable 1.6V LDO. */ - r8712_write8(padapter, SPS0_CTRL, 0x56); /* Disable 1.6V LDO */ - r8712_write8(padapter, SPS0_CTRL + 1, 0x43); /* Set SW PFM */ - return _SUCCESS; -} - -uint rtl871x_hal_init(struct _adapter *padapter) -{ - padapter->hw_init_completed = false; - if (!padapter->halpriv.hal_bus_init) - return _FAIL; - if (padapter->halpriv.hal_bus_init(padapter) != _SUCCESS) - return _FAIL; - if (rtl8712_hal_init(padapter) == _SUCCESS) { - padapter->hw_init_completed = true; - } else { - padapter->hw_init_completed = false; - return _FAIL; - } - return _SUCCESS; -} diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c deleted file mode 100644 index 7d8f1a29d18a909de4117f09cdbd0084f49dc997..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/ieee80211.c +++ /dev/null @@ -1,415 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * ieee80211.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _IEEE80211_C - -#include "drv_types.h" -#include "ieee80211.h" -#include "wifi.h" -#include "osdep_service.h" -#include "wlan_bssdef.h" - -static const u8 WPA_OUI_TYPE[] = {0x00, 0x50, 0xf2, 1}; -static const u8 WPA_CIPHER_SUITE_NONE[] = {0x00, 0x50, 0xf2, 0}; -static const u8 WPA_CIPHER_SUITE_WEP40[] = {0x00, 0x50, 0xf2, 1}; -static const u8 WPA_CIPHER_SUITE_TKIP[] = {0x00, 0x50, 0xf2, 2}; -static const u8 WPA_CIPHER_SUITE_CCMP[] = {0x00, 0x50, 0xf2, 4}; -static const u8 WPA_CIPHER_SUITE_WEP104[] = {0x00, 0x50, 0xf2, 5}; - -static const u8 RSN_CIPHER_SUITE_NONE[] = {0x00, 0x0f, 0xac, 0}; -static const u8 RSN_CIPHER_SUITE_WEP40[] = {0x00, 0x0f, 0xac, 1}; -static const u8 RSN_CIPHER_SUITE_TKIP[] = {0x00, 0x0f, 0xac, 2}; -static const u8 RSN_CIPHER_SUITE_CCMP[] = {0x00, 0x0f, 0xac, 4}; -static const u8 RSN_CIPHER_SUITE_WEP104[] = {0x00, 0x0f, 0xac, 5}; - -/*----------------------------------------------------------- - * for adhoc-master to generate ie and provide supported-rate to fw - *----------------------------------------------------------- - */ - -static u8 WIFI_CCKRATES[] = { - (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK) -}; - -static u8 WIFI_OFDMRATES[] = { - (IEEE80211_OFDM_RATE_6MB), - (IEEE80211_OFDM_RATE_9MB), - (IEEE80211_OFDM_RATE_12MB), - (IEEE80211_OFDM_RATE_18MB), - (IEEE80211_OFDM_RATE_24MB), - (IEEE80211_OFDM_RATE_36MB), - (IEEE80211_OFDM_RATE_48MB), - (IEEE80211_OFDM_RATE_54MB) -}; - -uint r8712_is_cckrates_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i] != 0) { - if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) || - (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22)) - return true; - i++; - } - return false; -} - -uint r8712_is_cckratesonly_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i] != 0) { - if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) && - (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22)) - return false; - i++; - } - return true; -} - -/* r8712_set_ie will update frame length */ -u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen) -{ - *pbuf = (u8)index; - *(pbuf + 1) = (u8)len; - if (len > 0) - memcpy((void *)(pbuf + 2), (void *)source, len); - *frlen = *frlen + (len + 2); - return pbuf + len + 2; -} - -/* --------------------------------------------------------------------------- - * index: the information element id index, limit is the limit for search - * --------------------------------------------------------------------------- - */ -u8 *r8712_get_ie(u8 *pbuf, sint index, uint *len, sint limit) -{ - sint tmp, i; - u8 *p; - - if (limit < 1) - return NULL; - p = pbuf; - i = 0; - *len = 0; - while (1) { - if (*p == index) { - *len = *(p + 1); - return p; - } - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); - if (i >= limit) - break; - } - return NULL; -} - -static void set_supported_rate(u8 *rates, uint mode) -{ - memset(rates, 0, NDIS_802_11_LENGTH_RATES_EX); - switch (mode) { - case WIRELESS_11B: - memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - break; - case WIRELESS_11G: - case WIRELESS_11A: - memcpy(rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); - break; - case WIRELESS_11BG: - memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, - IEEE80211_NUM_OFDM_RATESLEN); - break; - } -} - -static uint r8712_get_rateset_len(u8 *rateset) -{ - uint i = 0; - - while (1) { - if ((rateset[i]) == 0) - break; - if (i > 12) - break; - i++; - } - return i; -} - -int r8712_generate_ie(struct registry_priv *registrypriv) -{ - int rate_len; - uint sz = 0; - struct wlan_bssid_ex *dev_network = ®istrypriv->dev_network; - u8 *ie = dev_network->IEs; - u16 beacon_period = (u16)dev_network->Configuration.BeaconPeriod; - - /*timestamp will be inserted by hardware*/ - sz += 8; - ie += sz; - /*beacon interval : 2bytes*/ - *(__le16 *)ie = cpu_to_le16(beacon_period); - sz += 2; - ie += 2; - /*capability info*/ - *(u16 *)ie = 0; - *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS); - if (registrypriv->preamble == PREAMBLE_SHORT) - *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - if (dev_network->Privacy) - *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - sz += 2; - ie += 2; - /*SSID*/ - ie = r8712_set_ie(ie, WLAN_EID_SSID, dev_network->Ssid.SsidLength, - dev_network->Ssid.Ssid, &sz); - /*supported rates*/ - set_supported_rate(dev_network->rates, registrypriv->wireless_mode); - rate_len = r8712_get_rateset_len(dev_network->rates); - if (rate_len > 8) { - ie = r8712_set_ie(ie, WLAN_EID_SUPP_RATES, 8, - dev_network->rates, &sz); - ie = r8712_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), - (dev_network->rates + 8), &sz); - } else { - ie = r8712_set_ie(ie, WLAN_EID_SUPP_RATES, - rate_len, dev_network->rates, &sz); - } - /*DS parameter set*/ - ie = r8712_set_ie(ie, WLAN_EID_DS_PARAMS, 1, - (u8 *)&dev_network->Configuration.DSConfig, &sz); - /*IBSS Parameter Set*/ - ie = r8712_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2, - (u8 *)&dev_network->Configuration.ATIMWindow, &sz); - return sz; -} - -unsigned char *r8712_get_wpa_ie(unsigned char *ie, uint *wpa_ie_len, int limit) -{ - u32 len; - u16 val16; - unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; - u8 *buf = ie; - - while (1) { - buf = r8712_get_ie(buf, _WPA_IE_ID_, &len, limit); - if (buf) { - /*check if oui matches...*/ - if (memcmp((buf + 2), wpa_oui_type, - sizeof(wpa_oui_type))) - goto check_next_ie; - /*check version...*/ - memcpy((u8 *)&val16, (buf + 6), sizeof(val16)); - le16_to_cpus(&val16); - if (val16 != 0x0001) - goto check_next_ie; - *wpa_ie_len = *(buf + 1); - return buf; - } - *wpa_ie_len = 0; - return NULL; -check_next_ie: - limit = limit - (buf - ie) - 2 - len; - if (limit <= 0) - break; - buf += (2 + len); - } - *wpa_ie_len = 0; - return NULL; -} - -unsigned char *r8712_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, - int limit) -{ - return r8712_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit); -} - -static int r8712_get_wpa_cipher_suite(u8 *s) -{ - if (!memcmp(s, (void *)WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, (void *)WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, (void *)WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, (void *)WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, (void *)WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - return 0; -} - -static int r8712_get_wpa2_cipher_suite(u8 *s) -{ - if (!memcmp(s, (void *)RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN)) - return WPA_CIPHER_NONE; - if (!memcmp(s, (void *)RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP40; - if (!memcmp(s, (void *)RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN)) - return WPA_CIPHER_TKIP; - if (!memcmp(s, (void *)RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN)) - return WPA_CIPHER_CCMP; - if (!memcmp(s, (void *)RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN)) - return WPA_CIPHER_WEP104; - return 0; -} - -int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher) -{ - int i; - int left, count; - u8 *pos; - - if (wpa_ie_len <= 0) { - /* No WPA IE - fail silently */ - return -EINVAL; - } - if ((*wpa_ie != _WPA_IE_ID_) || - (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) || - (memcmp(wpa_ie + 2, (void *)WPA_OUI_TYPE, WPA_SELECTOR_LEN))) - return -EINVAL; - pos = wpa_ie; - pos += 8; - left = wpa_ie_len - 8; - /*group_cipher*/ - if (left >= WPA_SELECTOR_LEN) { - *group_cipher = r8712_get_wpa_cipher_suite(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - return -EINVAL; - } - /*pairwise_cipher*/ - if (left >= 2) { - count = le16_to_cpu(*(__le16 *)pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) - return -EINVAL; - for (i = 0; i < count; i++) { - *pairwise_cipher |= r8712_get_wpa_cipher_suite(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - return -EINVAL; - } - return 0; -} - -int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher) -{ - int i; - int left, count; - u8 *pos; - - if (rsn_ie_len <= 0) { - /* No RSN IE - fail silently */ - return -EINVAL; - } - if ((*rsn_ie != _WPA2_IE_ID_) || - (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2))) - return -EINVAL; - pos = rsn_ie; - pos += 4; - left = rsn_ie_len - 4; - /*group_cipher*/ - if (left >= RSN_SELECTOR_LEN) { - *group_cipher = r8712_get_wpa2_cipher_suite(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) { - return -EINVAL; - } - /*pairwise_cipher*/ - if (left >= 2) { - count = le16_to_cpu(*(__le16 *)pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) - return -EINVAL; - for (i = 0; i < count; i++) { - *pairwise_cipher |= r8712_get_wpa2_cipher_suite(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - return -EINVAL; - } - return 0; -} - -int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, - u8 *wpa_ie, u16 *wpa_len) -{ - u8 authmode; - u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; - uint cnt; - - /*Search required WPA or WPA2 IE and copy to sec_ie[ ]*/ - cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_; - while (cnt < in_len) { - authmode = in_ie[cnt]; - if ((authmode == _WPA_IE_ID_) && - (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) { - memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - *wpa_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /*get next */ - } else { - if (authmode == _WPA2_IE_ID_) { - memcpy(rsn_ie, &in_ie[cnt], - in_ie[cnt + 1] + 2); - *rsn_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /*get next*/ - } else { - cnt += in_ie[cnt + 1] + 2; /*get next*/ - } - } - } - return *rsn_len + *wpa_len; -} - -int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) -{ - int match; - uint cnt; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - cnt = 12; - match = false; - while (cnt < in_len) { - eid = in_ie[cnt]; - if ((eid == _WPA_IE_ID_) && - (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) { - memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - *wps_ielen = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; - match = true; - break; - } - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - return match; -} diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h deleted file mode 100644 index 65ceaca9b51ea725e1947f041179c53080d06460..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/ieee80211.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __IEEE80211_H -#define __IEEE80211_H - -#include <linux/ieee80211.h> - -#define IEEE_CMD_SET_WPA_PARAM 1 -#define IEEE_CMD_SET_WPA_IE 2 -#define IEEE_CMD_SET_ENCRYPTION 3 -#define IEEE_CMD_MLME 4 - -#define IEEE_PARAM_WPA_ENABLED 1 -#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 -#define IEEE_PARAM_DROP_UNENCRYPTED 3 -#define IEEE_PARAM_PRIVACY_INVOKED 4 -#define IEEE_PARAM_AUTH_ALGS 5 -#define IEEE_PARAM_IEEE_802_1X 6 -#define IEEE_PARAM_WPAX_SELECT 7 - -#define AUTH_ALG_OPEN_SYSTEM 0x1 -#define AUTH_ALG_SHARED_KEY 0x2 -#define AUTH_ALG_LEAP 0x00000004 - -#define IEEE_MLME_STA_DEAUTH 1 -#define IEEE_MLME_STA_DISASSOC 2 - -#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 -#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 -#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 -#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 - -#define IEEE_CRYPT_ALG_NAME_LEN 16 - -#define WPA_CIPHER_NONE BIT(0) -#define WPA_CIPHER_WEP40 BIT(1) -#define WPA_CIPHER_WEP104 BIT(2) -#define WPA_CIPHER_TKIP BIT(3) -#define WPA_CIPHER_CCMP BIT(4) - -#define WPA_SELECTOR_LEN 4 -#define RSN_HEADER_LEN 4 - -#define RSN_SELECTOR_LEN 4 - -enum NETWORK_TYPE { - WIRELESS_INVALID = 0, - WIRELESS_11B = 1, - WIRELESS_11G = 2, - WIRELESS_11BG = (WIRELESS_11B | WIRELESS_11G), - WIRELESS_11A = 4, - WIRELESS_11N = 8, - WIRELESS_11GN = (WIRELESS_11G | WIRELESS_11N), - WIRELESS_11BGN = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11N), -}; - -struct ieee_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[]; - } wpa_ie; - struct { - int command; - int reason_code; - } mlme; - struct { - u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[]; - } crypt; - } u; -}; - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* QoS,QOS */ -#define NORMAL_ACK 0 - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ -} __packed; - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_NUM_OFDM_RATESLEN 8 - -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define WEP_KEYS 4 - -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... - */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_WPA_IE_LEN 128 - -struct registry_priv; - -u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen); -u8 *r8712_get_ie(u8 *pbuf, sint index, uint *len, sint limit); -unsigned char *r8712_get_wpa_ie(unsigned char *pie, uint *rsn_ie_len, - int limit); -unsigned char *r8712_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, - int limit); -int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher); -int r8712_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher); -int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, - u8 *wpa_ie, u16 *wpa_len); -int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen); -int r8712_generate_ie(struct registry_priv *pregistrypriv); -uint r8712_is_cckrates_included(u8 *rate); -uint r8712_is_cckratesonly_included(u8 *rate); - -#endif /* IEEE80211_H */ - diff --git a/drivers/staging/rtl8712/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c deleted file mode 100644 index 436816d14cdf351c07b6fb8142f53ada95696d41..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/mlme_linux.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * mlme_linux.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _MLME_OSDEP_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "mlme_osdep.h" - -static void sitesurvey_ctrl_handler(struct timer_list *t) -{ - struct _adapter *adapter = - from_timer(adapter, t, - mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer); - - _r8712_sitesurvey_ctrl_handler(adapter); - mod_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer, - jiffies + msecs_to_jiffies(3000)); -} - -static void join_timeout_handler (struct timer_list *t) -{ - struct _adapter *adapter = - from_timer(adapter, t, mlmepriv.assoc_timer); - - _r8712_join_timeout_handler(adapter); -} - -static void _scan_timeout_handler (struct timer_list *t) -{ - struct _adapter *adapter = - from_timer(adapter, t, mlmepriv.scan_to_timer); - - r8712_scan_timeout_handler(adapter); -} - -static void dhcp_timeout_handler (struct timer_list *t) -{ - struct _adapter *adapter = - from_timer(adapter, t, mlmepriv.dhcp_timer); - - _r8712_dhcp_timeout_handler(adapter); -} - -static void wdg_timeout_handler (struct timer_list *t) -{ - struct _adapter *adapter = - from_timer(adapter, t, mlmepriv.wdg_timer); - - r8712_wdg_wk_cmd(adapter); - - mod_timer(&adapter->mlmepriv.wdg_timer, - jiffies + msecs_to_jiffies(2000)); -} - -void r8712_init_mlme_timer(struct _adapter *adapter) -{ - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - timer_setup(&mlmepriv->assoc_timer, join_timeout_handler, 0); - timer_setup(&mlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer, - sitesurvey_ctrl_handler, 0); - timer_setup(&mlmepriv->scan_to_timer, _scan_timeout_handler, 0); - timer_setup(&mlmepriv->dhcp_timer, dhcp_timeout_handler, 0); - timer_setup(&mlmepriv->wdg_timer, wdg_timeout_handler, 0); -} - -void r8712_os_indicate_connect(struct _adapter *adapter) -{ - r8712_indicate_wx_assoc_event(adapter); - netif_carrier_on(adapter->pnetdev); -} - -static struct RT_PMKID_LIST backup_PMKID_list[NUM_PMKID_CACHE]; -void r8712_os_indicate_disconnect(struct _adapter *adapter) -{ - u8 backup_PMKID_index = 0; - u8 backup_TKIP_countermeasure = 0x00; - - r8712_indicate_wx_disassoc_event(adapter); - netif_carrier_off(adapter->pnetdev); - if (adapter->securitypriv.AuthAlgrthm == 2) { /*/802.1x*/ - /* We have to backup the PMK information for WiFi PMK Caching - * test item. Backup the btkip_countermeasure information. - * When the countermeasure is trigger, the driver have to - * disconnect with AP for 60 seconds. - */ - - memcpy(&backup_PMKID_list[0], - &adapter->securitypriv.PMKIDList[0], - sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE); - backup_PMKID_index = adapter->securitypriv.PMKIDIndex; - backup_TKIP_countermeasure = - adapter->securitypriv.btkip_countermeasure; - memset((unsigned char *)&adapter->securitypriv, 0, - sizeof(struct security_priv)); - timer_setup(&adapter->securitypriv.tkip_timer, - r8712_use_tkipkey_handler, 0); - /* Restore the PMK information to securitypriv structure - * for the following connection. - */ - memcpy(&adapter->securitypriv.PMKIDList[0], - &backup_PMKID_list[0], - sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE); - adapter->securitypriv.PMKIDIndex = backup_PMKID_index; - adapter->securitypriv.btkip_countermeasure = - backup_TKIP_countermeasure; - } else { /*reset values in securitypriv*/ - struct security_priv *sec_priv = &adapter->securitypriv; - - sec_priv->AuthAlgrthm = 0; /*open system*/ - sec_priv->PrivacyAlgrthm = _NO_PRIVACY_; - sec_priv->PrivacyKeyIndex = 0; - sec_priv->XGrpPrivacy = _NO_PRIVACY_; - sec_priv->XGrpKeyid = 1; - sec_priv->ndisauthtype = Ndis802_11AuthModeOpen; - sec_priv->ndisencryptstatus = Ndis802_11WEPDisabled; - sec_priv->wps_phase = false; - } -} - -void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie) -{ - uint len; - u8 *buff, *p, i; - union iwreq_data wrqu; - - buff = NULL; - if (authmode == _WPA_IE_ID_) { - buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC); - if (!buff) - return; - p = buff; - p += sprintf(p, "ASSOCINFO(ReqIEs="); - len = sec_ie[1] + 2; - len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX; - for (i = 0; i < len; i++) - p += sprintf(p, "%02x", sec_ie[i]); - p += sprintf(p, ")"); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = p - buff; - wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ? - wrqu.data.length : IW_CUSTOM_MAX; - wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff); - kfree(buff); - } -} diff --git a/drivers/staging/rtl8712/mlme_osdep.h b/drivers/staging/rtl8712/mlme_osdep.h deleted file mode 100644 index a02c782588ddbfd0bfcd233948b5a2ccf6f84bcf..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/mlme_osdep.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __MLME_OSDEP_H_ -#define __MLME_OSDEP_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -void r8712_init_mlme_timer(struct _adapter *padapter); -void r8712_os_indicate_disconnect(struct _adapter *adapter); -void r8712_os_indicate_connect(struct _adapter *adapter); -void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie); -int r8712_recv_indicatepkts_in_order(struct _adapter *adapter, - struct recv_reorder_ctrl *precvreorder_ctrl, - int bforced); -void r8712_indicate_wx_assoc_event(struct _adapter *padapter); -void r8712_indicate_wx_disassoc_event(struct _adapter *padapter); - -#endif /*_MLME_OSDEP_H_*/ - diff --git a/drivers/staging/rtl8712/mp_custom_oid.h b/drivers/staging/rtl8712/mp_custom_oid.h deleted file mode 100644 index a9fac87fcabc59b9d02ebbb68903e62055d0ad1e..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/mp_custom_oid.h +++ /dev/null @@ -1,287 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __CUSTOM_OID_H -#define __CUSTOM_OID_H - -/* 0xFF818000 - 0xFF81802F RTL8180 Mass Production Kit - * 0xFF818500 - 0xFF81850F RTL8185 Setup Utility - * 0xFF818580 - 0xFF81858F RTL8185 Phy Status Utility - * - * by Owen for Production Kit - * For Production Kit with Agilent Equipments - * in order to make our custom oids hopefully somewhat unique - * we will use 0xFF (indicating implementation specific OID) - * 81(first byte of non zero Realtek unique identifier) - * 80 (second byte of non zero Realtek unique identifier) - * XX (the custom OID number - providing 255 possible custom oids) - */ -#define OID_RT_PRO_RESET_DUT 0xFF818000 -#define OID_RT_PRO_SET_DATA_RATE 0xFF818001 -#define OID_RT_PRO_START_TEST 0xFF818002 -#define OID_RT_PRO_STOP_TEST 0xFF818003 -#define OID_RT_PRO_SET_PREAMBLE 0xFF818004 -#define OID_RT_PRO_SET_SCRAMBLER 0xFF818005 -#define OID_RT_PRO_SET_FILTER_BB 0xFF818006 -#define OID_RT_PRO_SET_MANUAL_DIVERSITY_BB 0xFF818007 -#define OID_RT_PRO_SET_CHANNEL_DIRECT_CALL 0xFF818008 -#define OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL 0xFF818009 -#define OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL 0xFF81800A - -#define OID_RT_PRO_SET_TX_ANTENNA_BB 0xFF81800D -#define OID_RT_PRO_SET_ANTENNA_BB 0xFF81800E -#define OID_RT_PRO_SET_CR_SCRAMBLER 0xFF81800F -#define OID_RT_PRO_SET_CR_NEW_FILTER 0xFF818010 -#define OID_RT_PRO_SET_TX_POWER_CONTROL 0xFF818011 -#define OID_RT_PRO_SET_CR_TX_CONFIG 0xFF818012 -#define OID_RT_PRO_GET_TX_POWER_CONTROL 0xFF818013 -#define OID_RT_PRO_GET_CR_SIGNAL_QUALITY 0xFF818014 -#define OID_RT_PRO_SET_CR_SETPOINT 0xFF818015 -#define OID_RT_PRO_SET_INTEGRATOR 0xFF818016 -#define OID_RT_PRO_SET_SIGNAL_QUALITY 0xFF818017 -#define OID_RT_PRO_GET_INTEGRATOR 0xFF818018 -#define OID_RT_PRO_GET_SIGNAL_QUALITY 0xFF818019 -#define OID_RT_PRO_QUERY_EEPROM_TYPE 0xFF81801A -#define OID_RT_PRO_WRITE_MAC_ADDRESS 0xFF81801B -#define OID_RT_PRO_READ_MAC_ADDRESS 0xFF81801C -#define OID_RT_PRO_WRITE_CIS_DATA 0xFF81801D -#define OID_RT_PRO_READ_CIS_DATA 0xFF81801E -#define OID_RT_PRO_WRITE_POWER_CONTROL 0xFF81801F -#define OID_RT_PRO_READ_POWER_CONTROL 0xFF818020 -#define OID_RT_PRO_WRITE_EEPROM 0xFF818021 -#define OID_RT_PRO_READ_EEPROM 0xFF818022 -#define OID_RT_PRO_RESET_TX_PACKET_SENT 0xFF818023 -#define OID_RT_PRO_QUERY_TX_PACKET_SENT 0xFF818024 -#define OID_RT_PRO_RESET_RX_PACKET_RECEIVED 0xFF818025 -#define OID_RT_PRO_QUERY_RX_PACKET_RECEIVED 0xFF818026 -#define OID_RT_PRO_QUERY_RX_PACKET_CRC32_ERROR 0xFF818027 -#define OID_RT_PRO_QUERY_CURRENT_ADDRESS 0xFF818028 -#define OID_RT_PRO_QUERY_PERMANENT_ADDRESS 0xFF818029 -#define OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS 0xFF81802A -#define OID_RT_PRO_RECEIVE_PACKET 0xFF81802C -#define OID_RT_PRO_WRITE_EEPROM_BYTE 0xFF81802D -#define OID_RT_PRO_READ_EEPROM_BYTE 0xFF81802E -#define OID_RT_PRO_SET_MODULATION 0xFF81802F -#define OID_RT_DRIVER_OPTION 0xFF818080 -#define OID_RT_RF_OFF 0xFF818081 -#define OID_RT_AUTH_STATUS 0xFF818082 -#define OID_RT_PRO_SET_CONTINUOUS_TX 0xFF81800B -#define OID_RT_PRO_SET_SINGLE_CARRIER_TX 0xFF81800C -#define OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX 0xFF81802B -#define OID_RT_PRO_SET_SINGLE_TONE_TX 0xFF818043 -#define OID_RT_UTILITY_FALSE_ALARM_COUNTERS 0xFF818580 -#define OID_RT_UTILITY_SELECT_DEBUG_MODE 0xFF818581 -#define OID_RT_UTILITY_SELECT_SUBCARRIER_NUMBER 0xFF818582 -#define OID_RT_UTILITY_GET_RSSI_STATUS 0xFF818583 -#define OID_RT_UTILITY_GET_FRAME_DETECTION_STATUS 0xFF818584 -#define OID_RT_UTILITY_GET_AGC_AND_FREQUENCY_OFFSET_ESTIMATION_STATUS \ - 0xFF818585 -#define OID_RT_UTILITY_GET_CHANNEL_ESTIMATION_STATUS 0xFF818586 -#define OID_RT_WIRELESS_MODE 0xFF818500 -#define OID_RT_SUPPORTED_RATES 0xFF818501 -#define OID_RT_DESIRED_RATES 0xFF818502 -#define OID_RT_WIRELESS_MODE_STARTING_ADHOC 0xFF818503 -#define OID_RT_GET_CONNECT_STATE 0xFF030001 -#define OID_RT_RESCAN 0xFF030002 -#define OID_RT_SET_KEY_LENGTH 0xFF030003 -#define OID_RT_SET_DEFAULT_KEY_ID 0xFF030004 -#define OID_RT_SET_CHANNEL 0xFF010182 -#define OID_RT_SET_SNIFFER_MODE 0xFF010183 -#define OID_RT_GET_SIGNAL_QUALITY 0xFF010184 -#define OID_RT_GET_SMALL_PACKET_CRC 0xFF010185 -#define OID_RT_GET_MIDDLE_PACKET_CRC 0xFF010186 -#define OID_RT_GET_LARGE_PACKET_CRC 0xFF010187 -#define OID_RT_GET_TX_RETRY 0xFF010188 -#define OID_RT_GET_RX_RETRY 0xFF010189 -#define OID_RT_PRO_SET_FW_DIG_STATE 0xFF01018A -#define OID_RT_PRO_SET_FW_RA_STATE 0xFF01018B -#define OID_RT_GET_RX_TOTAL_PACKET 0xFF010190 -#define OID_RT_GET_TX_BEACON_OK 0xFF010191 -#define OID_RT_GET_TX_BEACON_ERR 0xFF010192 -#define OID_RT_GET_RX_ICV_ERR 0xFF010193 -#define OID_RT_SET_ENCRYPTION_ALGORITHM 0xFF010194 -#define OID_RT_SET_NO_AUTO_RESCAN 0xFF010195 -#define OID_RT_GET_PREAMBLE_MODE 0xFF010196 -#define OID_RT_GET_DRIVER_UP_DELTA_TIME 0xFF010197 -#define OID_RT_GET_AP_IP 0xFF010198 -#define OID_RT_GET_CHANNELPLAN 0xFF010199 -#define OID_RT_SET_PREAMBLE_MODE 0xFF01019A -#define OID_RT_SET_BCN_INTVL 0xFF01019B -#define OID_RT_GET_RF_VENDER 0xFF01019C -#define OID_RT_DEDICATE_PROBE 0xFF01019D -#define OID_RT_PRO_RX_FILTER_PATTERN 0xFF01019E -#define OID_RT_GET_DCST_CURRENT_THRESHOLD 0xFF01019F -#define OID_RT_GET_CCA_ERR 0xFF0101A0 -#define OID_RT_GET_CCA_UPGRADE_THRESHOLD 0xFF0101A1 -#define OID_RT_GET_CCA_FALLBACK_THRESHOLD 0xFF0101A2 -#define OID_RT_GET_CCA_UPGRADE_EVALUATE_TIMES 0xFF0101A3 -#define OID_RT_GET_CCA_FALLBACK_EVALUATE_TIMES 0xFF0101A4 -#define OID_RT_SET_RATE_ADAPTIVE 0xFF0101A5 -#define OID_RT_GET_DCST_EVALUATE_PERIOD 0xFF0101A5 -#define OID_RT_GET_DCST_TIME_UNIT_INDEX 0xFF0101A6 -#define OID_RT_GET_TOTAL_TX_BYTES 0xFF0101A7 -#define OID_RT_GET_TOTAL_RX_BYTES 0xFF0101A8 -#define OID_RT_CURRENT_TX_POWER_LEVEL 0xFF0101A9 -#define OID_RT_GET_ENC_KEY_MISMATCH_COUNT 0xFF0101AA -#define OID_RT_GET_ENC_KEY_MATCH_COUNT 0xFF0101AB -#define OID_RT_GET_CHANNEL 0xFF0101AC -#define OID_RT_SET_CHANNELPLAN 0xFF0101AD -#define OID_RT_GET_HARDWARE_RADIO_OFF 0xFF0101AE -#define OID_RT_CHANNELPLAN_BY_COUNTRY 0xFF0101AF -#define OID_RT_SCAN_AVAILABLE_BSSID 0xFF0101B0 -#define OID_RT_GET_HARDWARE_VERSION 0xFF0101B1 -#define OID_RT_GET_IS_ROAMING 0xFF0101B2 -#define OID_RT_GET_IS_PRIVACY 0xFF0101B3 -#define OID_RT_GET_KEY_MISMATCH 0xFF0101B4 -#define OID_RT_SET_RSSI_ROAM_TRAFFIC_TH 0xFF0101B5 -#define OID_RT_SET_RSSI_ROAM_SIGNAL_TH 0xFF0101B6 -#define OID_RT_RESET_LOG 0xFF0101B7 -#define OID_RT_GET_LOG 0xFF0101B8 -#define OID_RT_SET_INDICATE_HIDDEN_AP 0xFF0101B9 -#define OID_RT_GET_HEADER_FAIL 0xFF0101BA -#define OID_RT_SUPPORTED_WIRELESS_MODE 0xFF0101BB -#define OID_RT_GET_CHANNEL_LIST 0xFF0101BC -#define OID_RT_GET_SCAN_IN_PROGRESS 0xFF0101BD -#define OID_RT_GET_TX_INFO 0xFF0101BE -#define OID_RT_RF_READ_WRITE_OFFSET 0xFF0101BF -#define OID_RT_RF_READ_WRITE 0xFF0101C0 -#define OID_RT_FORCED_DATA_RATE 0xFF0101C1 -#define OID_RT_WIRELESS_MODE_FOR_SCAN_LIST 0xFF0101C2 -#define OID_RT_GET_BSS_WIRELESS_MODE 0xFF0101C3 -#define OID_RT_SCAN_WITH_MAGIC_PACKET 0xFF0101C4 -#define OID_RT_PRO_RX_FILTER 0xFF0111C0 -#define OID_CE_USB_WRITE_REGISTRY 0xFF0111C1 -#define OID_CE_USB_READ_REGISTRY 0xFF0111C2 -#define OID_RT_PRO_SET_INITIAL_GAIN 0xFF0111C3 -#define OID_RT_PRO_SET_BB_RF_STANDBY_MODE 0xFF0111C4 -#define OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE 0xFF0111C5 -#define OID_RT_PRO_SET_TX_CHARGE_PUMP 0xFF0111C6 -#define OID_RT_PRO_SET_RX_CHARGE_PUMP 0xFF0111C7 -#define OID_RT_PRO_RF_WRITE_REGISTRY 0xFF0111C8 -#define OID_RT_PRO_RF_READ_REGISTRY 0xFF0111C9 -#define OID_RT_PRO_QUERY_RF_TYPE 0xFF0111CA -#define OID_RT_AP_GET_ASSOCIATED_STATION_LIST 0xFF010300 -#define OID_RT_AP_GET_CURRENT_TIME_STAMP 0xFF010301 -#define OID_RT_AP_SWITCH_INTO_AP_MODE 0xFF010302 -#define OID_RT_AP_SET_DTIM_PERIOD 0xFF010303 -#define OID_RT_AP_SUPPORTED 0xFF010304 -#define OID_RT_AP_SET_PASSPHRASE 0xFF010305 -#define OID_RT_PRO8187_WI_POLL 0xFF818780 -#define OID_RT_PRO_WRITE_BB_REG 0xFF818781 -#define OID_RT_PRO_READ_BB_REG 0xFF818782 -#define OID_RT_PRO_WRITE_RF_REG 0xFF818783 -#define OID_RT_PRO_READ_RF_REG 0xFF818784 -#define OID_RT_MH_VENDER_ID 0xFFEDC100 -#define OID_RT_PRO8711_JOIN_BSS 0xFF871100 -#define OID_RT_PRO_READ_REGISTER 0xFF871101 -#define OID_RT_PRO_WRITE_REGISTER 0xFF871102 -#define OID_RT_PRO_BURST_READ_REGISTER 0xFF871103 -#define OID_RT_PRO_BURST_WRITE_REGISTER 0xFF871104 -#define OID_RT_PRO_WRITE_TXCMD 0xFF871105 -#define OID_RT_PRO_READ16_EEPROM 0xFF871106 -#define OID_RT_PRO_WRITE16_EEPROM 0xFF871107 -#define OID_RT_PRO_H2C_SET_COMMAND 0xFF871108 -#define OID_RT_PRO_H2C_QUERY_RESULT 0xFF871109 -#define OID_RT_PRO8711_WI_POLL 0xFF87110A -#define OID_RT_PRO8711_PKT_LOSS 0xFF87110B -#define OID_RT_RD_ATTRIB_MEM 0xFF87110C -#define OID_RT_WR_ATTRIB_MEM 0xFF87110D -/*Method 2 for H2C/C2H*/ -#define OID_RT_PRO_H2C_CMD_MODE 0xFF871110 -#define OID_RT_PRO_H2C_CMD_RSP_MODE 0xFF871111 -#define OID_RT_PRO_H2C_CMD_EVENT_MODE 0xFF871112 -#define OID_RT_PRO_WAIT_C2H_EVENT 0xFF871113 -#define OID_RT_PRO_RW_ACCESS_PROTOCOL_TEST 0xFF871114 -#define OID_RT_PRO_SCSI_ACCESS_TEST 0xFF871115 -#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_OUT 0xFF871116 -#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_IN 0xFF871117 -#define OID_RT_RRO_RX_PKT_VIA_IOCTRL 0xFF871118 -#define OID_RT_RRO_RX_PKTARRAY_VIA_IOCTRL 0xFF871119 -#define OID_RT_RPO_SET_PWRMGT_TEST 0xFF87111A -#define OID_RT_PRO_QRY_PWRMGT_TEST 0XFF87111B -#define OID_RT_RPO_ASYNC_RWIO_TEST 0xFF87111C -#define OID_RT_RPO_ASYNC_RWIO_POLL 0xFF87111D -#define OID_RT_PRO_SET_RF_INTFS 0xFF87111E -#define OID_RT_POLL_RX_STATUS 0xFF87111F -#define OID_RT_PRO_CFG_DEBUG_MESSAGE 0xFF871120 -#define OID_RT_PRO_SET_DATA_RATE_EX 0xFF871121 -#define OID_RT_PRO_SET_BASIC_RATE 0xFF871122 -#define OID_RT_PRO_READ_TSSI 0xFF871123 -#define OID_RT_PRO_SET_POWER_TRACKING 0xFF871124 -#define OID_RT_PRO_QRY_PWRSTATE 0xFF871150 -#define OID_RT_PRO_SET_PWRSTATE 0xFF871151 -/*Method 2 , using workitem */ -#define OID_RT_SET_READ_REG 0xFF871181 -#define OID_RT_SET_WRITE_REG 0xFF871182 -#define OID_RT_SET_BURST_READ_REG 0xFF871183 -#define OID_RT_SET_BURST_WRITE_REG 0xFF871184 -#define OID_RT_SET_WRITE_TXCMD 0xFF871185 -#define OID_RT_SET_READ16_EEPROM 0xFF871186 -#define OID_RT_SET_WRITE16_EEPROM 0xFF871187 -#define OID_RT_QRY_POLL_WKITEM 0xFF871188 - -/*For SDIO INTERFACE only*/ -#define OID_RT_PRO_SYNCPAGERW_SRAM 0xFF8711A0 -#define OID_RT_PRO_871X_DRV_EXT 0xFF8711A1 - -/*For USB INTERFACE only*/ -#define OID_RT_PRO_USB_VENDOR_REQ 0xFF8711B0 -#define OID_RT_PRO_SCSI_AUTO_TEST 0xFF8711B1 -#define OID_RT_PRO_USB_MAC_AC_FIFO_WRITE 0xFF8711B2 -#define OID_RT_PRO_USB_MAC_RX_FIFO_READ 0xFF8711B3 -#define OID_RT_PRO_USB_MAC_RX_FIFO_POLLING 0xFF8711B4 - -#define OID_RT_PRO_H2C_SET_RATE_TABLE 0xFF8711FB -#define OID_RT_PRO_H2C_GET_RATE_TABLE 0xFF8711FC -#define OID_RT_PRO_H2C_C2H_LBK_TEST 0xFF8711FE - -#define OID_RT_PRO_ENCRYPTION_CTRL 0xFF871200 -#define OID_RT_PRO_ADD_STA_INFO 0xFF871201 -#define OID_RT_PRO_DELE_STA_INFO 0xFF871202 -#define OID_RT_PRO_QUERY_DR_VARIABLE 0xFF871203 - -#define OID_RT_PRO_RX_PACKET_TYPE 0xFF871204 - -#define OID_RT_PRO_READ_EFUSE 0xFF871205 -#define OID_RT_PRO_WRITE_EFUSE 0xFF871206 -#define OID_RT_PRO_RW_EFUSE_PGPKT 0xFF871207 -#define OID_RT_GET_EFUSE_CURRENT_SIZE 0xFF871208 - -#define OID_RT_SET_BANDWIDTH 0xFF871209 -#define OID_RT_SET_CRYSTAL_CAP 0xFF87120A - -#define OID_RT_SET_RX_PACKET_TYPE 0xFF87120B - -#define OID_RT_GET_EFUSE_MAX_SIZE 0xFF87120C - -#define OID_RT_PRO_SET_TX_AGC_OFFSET 0xFF87120D - -#define OID_RT_PRO_SET_PKT_TEST_MODE 0xFF87120E - -#define OID_RT_PRO_FOR_EVM_TEST_SETTING 0xFF87120F - -#define OID_RT_PRO_GET_THERMAL_METER 0xFF871210 - -#define OID_RT_RESET_PHY_RX_PACKET_COUNT 0xFF871211 -#define OID_RT_GET_PHY_RX_PACKET_RECEIVED 0xFF871212 -#define OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR 0xFF871213 - -#define OID_RT_SET_POWER_DOWN 0xFF871214 - -#define OID_RT_GET_POWER_MODE 0xFF871215 - -#define OID_RT_PRO_EFUSE 0xFF871216 -#define OID_RT_PRO_EFUSE_MAP 0xFF871217 - -#endif /*#ifndef __CUSTOM_OID_H */ - diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c deleted file mode 100644 index 1b11f8b04e13f28fa12564bdff5b3b1cbbcc6cd4..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/os_intfs.c +++ /dev/null @@ -1,482 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * os_intfs.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _OS_INTFS_C_ - -#include <linux/module.h> -#include <linux/kthread.h> -#include <linux/firmware.h> -#include "osdep_service.h" -#include "drv_types.h" -#include "xmit_osdep.h" -#include "recv_osdep.h" -#include "rtl871x_ioctl.h" -#include "usb_osintf.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("rtl871x wireless lan driver"); -MODULE_AUTHOR("Larry Finger"); - -static char ifname[IFNAMSIZ] = "wlan%d"; - -/* module param defaults */ -static int chip_version = RTL8712_2ndCUT; -static int rfintfs = HWPI; -static int lbkmode = RTL8712_AIR_TRX; -static int hci = RTL8712_USB; -static int ampdu_enable = 1;/*for enable tx_ampdu*/ - -/* The video_mode variable is for video mode.*/ -/* It may be specify when inserting module with video_mode=1 parameter.*/ -static int video_mode = 1; /* enable video mode*/ - -/*Ndis802_11Infrastructure; infra, ad-hoc, auto*/ -static int network_mode = Ndis802_11IBSS; -static int channel = 1;/*ad-hoc support requirement*/ -static int wireless_mode = WIRELESS_11BG; -static int vrtl_carrier_sense = AUTO_VCS; -static int vcs_type = RTS_CTS; -static int frag_thresh = 2346; -static int preamble = PREAMBLE_LONG;/*long, short, auto*/ -static int scan_mode = 1;/*active, passive*/ -static int adhoc_tx_pwr = 1; -static int soft_ap; -static int smart_ps = 1; -static int power_mgnt = PS_MODE_ACTIVE; -static int radio_enable = 1; -static int long_retry_lmt = 7; -static int short_retry_lmt = 7; -static int busy_thresh = 40; -static int ack_policy = NORMAL_ACK; -static int mp_mode; -static int software_encrypt; -static int software_decrypt; - -static int wmm_enable;/* default is set to disable the wmm.*/ -static int uapsd_enable; -static int uapsd_max_sp = NO_LIMIT; -static int uapsd_acbk_en; -static int uapsd_acbe_en; -static int uapsd_acvi_en; -static int uapsd_acvo_en; - -static int ht_enable = 1; -static int cbw40_enable = 1; -static int rf_config = RTL8712_RF_1T2R; /* 1T2R*/ -static int low_power; -/* mac address to use instead of the one stored in Efuse */ -char *r8712_initmac; -static char *initmac; -/* if wifi_test = 1, driver will disable the turbo mode and pass it to - * firmware private. - */ -static int wifi_test; - -module_param_string(ifname, ifname, sizeof(ifname), 0644); -module_param(wifi_test, int, 0644); -module_param(initmac, charp, 0644); -module_param(video_mode, int, 0644); -module_param(chip_version, int, 0644); -module_param(rfintfs, int, 0644); -module_param(lbkmode, int, 0644); -module_param(hci, int, 0644); -module_param(network_mode, int, 0644); -module_param(channel, int, 0644); -module_param(mp_mode, int, 0644); -module_param(wmm_enable, int, 0644); -module_param(vrtl_carrier_sense, int, 0644); -module_param(vcs_type, int, 0644); -module_param(busy_thresh, int, 0644); -module_param(ht_enable, int, 0644); -module_param(cbw40_enable, int, 0644); -module_param(ampdu_enable, int, 0644); -module_param(rf_config, int, 0644); -module_param(power_mgnt, int, 0644); -module_param(low_power, int, 0644); - -MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default"); -MODULE_PARM_DESC(initmac, "MAC-Address, default: use FUSE"); - -static int netdev_open(struct net_device *pnetdev); -static int netdev_close(struct net_device *pnetdev); - -static void loadparam(struct _adapter *padapter, struct net_device *pnetdev) -{ - struct registry_priv *registry_par = &padapter->registrypriv; - - registry_par->chip_version = (u8)chip_version; - registry_par->rfintfs = (u8)rfintfs; - registry_par->lbkmode = (u8)lbkmode; - registry_par->hci = (u8)hci; - registry_par->network_mode = (u8)network_mode; - memcpy(registry_par->ssid.Ssid, "ANY", 3); - registry_par->ssid.SsidLength = 3; - registry_par->channel = (u8)channel; - registry_par->wireless_mode = (u8)wireless_mode; - registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense; - registry_par->vcs_type = (u8)vcs_type; - registry_par->frag_thresh = (u16)frag_thresh; - registry_par->preamble = (u8)preamble; - registry_par->scan_mode = (u8)scan_mode; - registry_par->adhoc_tx_pwr = (u8)adhoc_tx_pwr; - registry_par->soft_ap = (u8)soft_ap; - registry_par->smart_ps = (u8)smart_ps; - registry_par->power_mgnt = (u8)power_mgnt; - registry_par->radio_enable = (u8)radio_enable; - registry_par->long_retry_lmt = (u8)long_retry_lmt; - registry_par->short_retry_lmt = (u8)short_retry_lmt; - registry_par->busy_thresh = (u16)busy_thresh; - registry_par->ack_policy = (u8)ack_policy; - registry_par->mp_mode = (u8)mp_mode; - registry_par->software_encrypt = (u8)software_encrypt; - registry_par->software_decrypt = (u8)software_decrypt; - /*UAPSD*/ - registry_par->wmm_enable = (u8)wmm_enable; - registry_par->uapsd_enable = (u8)uapsd_enable; - registry_par->uapsd_max_sp = (u8)uapsd_max_sp; - registry_par->uapsd_acbk_en = (u8)uapsd_acbk_en; - registry_par->uapsd_acbe_en = (u8)uapsd_acbe_en; - registry_par->uapsd_acvi_en = (u8)uapsd_acvi_en; - registry_par->uapsd_acvo_en = (u8)uapsd_acvo_en; - registry_par->ht_enable = (u8)ht_enable; - registry_par->cbw40_enable = (u8)cbw40_enable; - registry_par->ampdu_enable = (u8)ampdu_enable; - registry_par->rf_config = (u8)rf_config; - registry_par->low_power = (u8)low_power; - registry_par->wifi_test = (u8)wifi_test; - r8712_initmac = initmac; -} - -static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p) -{ - struct _adapter *padapter = netdev_priv(pnetdev); - struct sockaddr *addr = p; - - if (!padapter->bup) - eth_hw_addr_set(pnetdev, addr->sa_data); - return 0; -} - -static struct net_device_stats *r871x_net_get_stats(struct net_device *pnetdev) -{ - struct _adapter *padapter = netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - - padapter->stats.tx_packets = pxmitpriv->tx_pkts; - padapter->stats.rx_packets = precvpriv->rx_pkts; - padapter->stats.tx_dropped = pxmitpriv->tx_drop; - padapter->stats.rx_dropped = precvpriv->rx_drop; - padapter->stats.tx_bytes = pxmitpriv->tx_bytes; - padapter->stats.rx_bytes = precvpriv->rx_bytes; - return &padapter->stats; -} - -static const struct net_device_ops rtl8712_netdev_ops = { - .ndo_open = netdev_open, - .ndo_stop = netdev_close, - .ndo_start_xmit = r8712_xmit_entry, - .ndo_set_mac_address = r871x_net_set_mac_address, - .ndo_get_stats = r871x_net_get_stats, - .ndo_do_ioctl = r871x_ioctl, -}; - -struct net_device *r8712_init_netdev(void) -{ - struct _adapter *padapter; - struct net_device *pnetdev; - - pnetdev = alloc_etherdev(sizeof(struct _adapter)); - if (!pnetdev) - return NULL; - if (dev_alloc_name(pnetdev, ifname) < 0) { - strscpy(ifname, "wlan%d", sizeof(ifname)); - dev_alloc_name(pnetdev, ifname); - } - padapter = netdev_priv(pnetdev); - padapter->pnetdev = pnetdev; - pr_info("r8712u: register rtl8712_netdev_ops to netdev_ops\n"); - pnetdev->netdev_ops = &rtl8712_netdev_ops; - pnetdev->watchdog_timeo = HZ; /* 1 second timeout */ - pnetdev->wireless_handlers = (struct iw_handler_def *) - &r871x_handlers_def; - loadparam(padapter, pnetdev); - netif_carrier_off(pnetdev); - padapter->pid = 0; /* Initial the PID value used for HW PBC.*/ - return pnetdev; -} - -static u32 start_drv_threads(struct _adapter *padapter) -{ - padapter->cmd_thread = kthread_run(r8712_cmd_thread, padapter, "%s", - padapter->pnetdev->name); - if (IS_ERR(padapter->cmd_thread)) - return _FAIL; - return _SUCCESS; -} - -void r8712_stop_drv_threads(struct _adapter *padapter) -{ - struct completion *completion = - &padapter->cmdpriv.terminate_cmdthread_comp; - - /*Below is to terminate r8712_cmd_thread & event_thread...*/ - complete(&padapter->cmdpriv.cmd_queue_comp); - if (padapter->cmd_thread) - wait_for_completion_interruptible(completion); - padapter->cmdpriv.cmd_seq = 1; -} - -static void start_drv_timers(struct _adapter *padapter) -{ - mod_timer(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer, - jiffies + msecs_to_jiffies(5000)); - mod_timer(&padapter->mlmepriv.wdg_timer, - jiffies + msecs_to_jiffies(2000)); -} - -void r8712_stop_drv_timers(struct _adapter *padapter) -{ - del_timer_sync(&padapter->mlmepriv.assoc_timer); - del_timer_sync(&padapter->securitypriv.tkip_timer); - del_timer_sync(&padapter->mlmepriv.scan_to_timer); - del_timer_sync(&padapter->mlmepriv.dhcp_timer); - del_timer_sync(&padapter->mlmepriv.wdg_timer); - del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer); -} - -static void init_default_value(struct _adapter *padapter) -{ - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - /*xmit_priv*/ - pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense; - pxmitpriv->vcs = pregistrypriv->vcs_type; - pxmitpriv->vcs_type = pregistrypriv->vcs_type; - pxmitpriv->rts_thresh = pregistrypriv->rts_thresh; - pxmitpriv->frag_len = pregistrypriv->frag_thresh; - /* mlme_priv */ - /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/ - pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */ - /*ht_priv*/ - { - int i; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - phtpriv->ampdu_enable = false;/*set to disabled*/ - for (i = 0; i < 16; i++) - phtpriv->baddbareq_issued[i] = false; - } - /*security_priv*/ - psecuritypriv->sw_encrypt = pregistrypriv->software_encrypt; - psecuritypriv->sw_decrypt = pregistrypriv->software_decrypt; - psecuritypriv->binstallGrpkey = _FAIL; - /*pwrctrl_priv*/ - /*registry_priv*/ - r8712_init_registrypriv_dev_network(padapter); - r8712_update_registrypriv_dev_network(padapter); - /*misc.*/ -} - -int r8712_init_drv_sw(struct _adapter *padapter) -{ - int ret; - - ret = r8712_init_cmd_priv(&padapter->cmdpriv); - if (ret) - return ret; - padapter->cmdpriv.padapter = padapter; - ret = r8712_init_evt_priv(&padapter->evtpriv); - if (ret) - goto free_cmd; - ret = r8712_init_mlme_priv(padapter); - if (ret) - goto free_evt; - ret = _r8712_init_xmit_priv(&padapter->xmitpriv, padapter); - if (ret) - goto free_mlme; - ret = _r8712_init_recv_priv(&padapter->recvpriv, padapter); - if (ret) - goto free_xmit; - memset((unsigned char *)&padapter->securitypriv, 0, - sizeof(struct security_priv)); - timer_setup(&padapter->securitypriv.tkip_timer, - r8712_use_tkipkey_handler, 0); - ret = _r8712_init_sta_priv(&padapter->stapriv); - if (ret) - goto free_recv; - padapter->stapriv.padapter = padapter; - r8712_init_bcmc_stainfo(padapter); - r8712_init_pwrctrl_priv(padapter); - mp871xinit(padapter); - init_default_value(padapter); - r8712_InitSwLeds(padapter); - mutex_init(&padapter->mutex_start); - - return 0; - -free_recv: - _r8712_free_recv_priv(&padapter->recvpriv); -free_xmit: - _free_xmit_priv(&padapter->xmitpriv); -free_mlme: - r8712_free_mlme_priv(&padapter->mlmepriv); -free_evt: - r8712_free_evt_priv(&padapter->evtpriv); -free_cmd: - r8712_free_cmd_priv(&padapter->cmdpriv); - return ret; -} - -void r8712_free_drv_sw(struct _adapter *padapter) -{ - r8712_free_cmd_priv(&padapter->cmdpriv); - r8712_free_evt_priv(&padapter->evtpriv); - r8712_DeInitSwLeds(padapter); - r8712_free_mlme_priv(&padapter->mlmepriv); - _free_xmit_priv(&padapter->xmitpriv); - _r8712_free_sta_priv(&padapter->stapriv); - _r8712_free_recv_priv(&padapter->recvpriv); - mp871xdeinit(padapter); -} - -static void enable_video_mode(struct _adapter *padapter, int cbw40_value) -{ - /* bit 8: - * 1 -> enable video mode to 96B AP - * 0 -> disable video mode to 96B AP - * bit 9: - * 1 -> enable 40MHz mode - * 0 -> disable 40MHz mode - * bit 10: - * 1 -> enable STBC - * 0 -> disable STBC - */ - u32 intcmd = 0xf4000500; /* enable bit8, bit10*/ - - if (cbw40_value) { - /* if the driver supports the 40M bandwidth, - * we can enable the bit 9. - */ - intcmd |= 0x200; - } - r8712_fw_cmd(padapter, intcmd); -} - -/* - * - * This function intends to handle the activation of an interface - * i.e. when it is brought Up/Active from a Down state. - * - */ -static int netdev_open(struct net_device *pnetdev) -{ - struct _adapter *padapter = netdev_priv(pnetdev); - - mutex_lock(&padapter->mutex_start); - if (!padapter->bup) { - padapter->driver_stopped = false; - padapter->surprise_removed = false; - padapter->bup = true; - if (rtl871x_hal_init(padapter) != _SUCCESS) - goto netdev_open_error; - if (!r8712_initmac) { - /* Use the mac address stored in the Efuse */ - eth_hw_addr_set(pnetdev, - padapter->eeprompriv.mac_addr); - } else { - /* We have to inform f/w to use user-supplied MAC - * address. - */ - msleep(200); - r8712_setMacAddr_cmd(padapter, - (const u8 *)pnetdev->dev_addr); - /* - * The "myid" function will get the wifi mac address - * from eeprompriv structure instead of netdev - * structure. So, we have to overwrite the mac_addr - * stored in the eeprompriv structure. In this case, - * the real mac address won't be used anymore. So that, - * the eeprompriv.mac_addr should store the mac which - * users specify. - */ - memcpy(padapter->eeprompriv.mac_addr, - pnetdev->dev_addr, ETH_ALEN); - } - if (start_drv_threads(padapter) != _SUCCESS) - goto netdev_open_error; - if (!padapter->dvobjpriv.inirp_init) - goto netdev_open_error; - else - padapter->dvobjpriv.inirp_init(padapter); - r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt, - padapter->registrypriv.smart_ps); - } - if (!netif_queue_stopped(pnetdev)) - netif_start_queue(pnetdev); - else - netif_wake_queue(pnetdev); - - if (video_mode) - enable_video_mode(padapter, cbw40_enable); - /* start driver mlme relation timer */ - start_drv_timers(padapter); - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK); - mutex_unlock(&padapter->mutex_start); - return 0; -netdev_open_error: - padapter->bup = false; - netif_carrier_off(pnetdev); - netif_stop_queue(pnetdev); - mutex_unlock(&padapter->mutex_start); - return -1; -} - -/* - * - * This function intends to handle the shutdown of an interface - * i.e. when it is brought Down from an Up/Active state. - * - */ -static int netdev_close(struct net_device *pnetdev) -{ - struct _adapter *padapter = netdev_priv(pnetdev); - - /* Close LED*/ - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_POWER_OFF); - msleep(200); - - /*s1.*/ - if (pnetdev) { - if (!netif_queue_stopped(pnetdev)) - netif_stop_queue(pnetdev); - } - /*s2.*/ - /*s2-1. issue disassoc_cmd to fw*/ - r8712_disassoc_cmd(padapter); - /*s2-2. indicate disconnect to os*/ - r8712_ind_disconnect(padapter); - /*s2-3.*/ - r8712_free_assoc_resources(padapter); - /*s2-4.*/ - r8712_free_network_queue(padapter); - return 0; -} - -#include "mlme_osdep.h" diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h deleted file mode 100644 index 9e75116c987ec32a518a8ece1829457180aee6a0..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/osdep_intf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __OSDEP_INTF_H_ -#define __OSDEP_INTF_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define RND4(x) (((x >> 2) + ((x & 3) != 0)) << 2) - -struct intf_priv { - u8 *intf_dev; - /* when in USB, IO is through interrupt in/out endpoints */ - struct usb_device *udev; - struct urb *piorw_urb; - struct completion io_retevt_comp; -}; - -int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); - -#endif /*_OSDEP_INTF_H_*/ diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h deleted file mode 100644 index 0d9bb42cbc589eb8e5350d70e7ce98039fbf01d2..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/osdep_service.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __OSDEP_SERVICE_H_ -#define __OSDEP_SERVICE_H_ - -#define _SUCCESS 1 -#define _FAIL 0 - -#include <linux/spinlock.h> - -#include <linux/interrupt.h> -#include <linux/semaphore.h> -#include <linux/sched/signal.h> -#include <linux/sem.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <net/iw_handler.h> -#include <linux/proc_fs.h> /* Necessary because we use the proc fs */ - -#include "basic_types.h" - -struct __queue { - struct list_head queue; - spinlock_t lock; -}; - -#define _pkt struct sk_buff -#define _buffer unsigned char - -#define _init_queue(pqueue) \ - do { \ - INIT_LIST_HEAD(&((pqueue)->queue)); \ - spin_lock_init(&((pqueue)->lock)); \ - } while (0) - -static inline u32 end_of_queue_search(struct list_head *head, - struct list_head *plist) -{ - return (head == plist); -} - -static inline void flush_signals_thread(void) -{ - if (signal_pending(current)) - flush_signals(current); -} - -#endif - diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c deleted file mode 100644 index 215fca4abb3a0669b2646edf4e060651a45aea67..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/recv_linux.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * recv_linux.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RECV_OSDEP_C_ - -#include <linux/usb.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "wifi.h" -#include "recv_osdep.h" -#include "osdep_intf.h" -#include "ethernet.h" -#include <linux/if_arp.h> -#include "usb_ops.h" - -/*init os related resource in struct recv_priv*/ -/*alloc os related resource in union recv_frame*/ -void r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe) -{ - precvframe->u.hdr.pkt_newalloc = NULL; - precvframe->u.hdr.pkt = NULL; -} - -/*alloc os related resource in struct recv_buf*/ -int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, - struct recv_buf *precvbuf) -{ - int res = 0; - - precvbuf->irp_pending = false; - precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); - if (!precvbuf->purb) - res = -ENOMEM; - precvbuf->pskb = NULL; - precvbuf->pallocated_buf = NULL; - precvbuf->pbuf = NULL; - precvbuf->pdata = NULL; - precvbuf->phead = NULL; - precvbuf->ptail = NULL; - precvbuf->pend = NULL; - precvbuf->transfer_len = 0; - precvbuf->len = 0; - return res; -} - -/*free os related resource in struct recv_buf*/ -void r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf) -{ - if (precvbuf->pskb) - dev_kfree_skb_any(precvbuf->pskb); - if (precvbuf->purb) { - usb_kill_urb(precvbuf->purb); - usb_free_urb(precvbuf->purb); - } -} - -void r8712_handle_tkip_mic_err(struct _adapter *adapter, u8 bgroup) -{ - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - struct mlme_priv *mlmepriv = &adapter->mlmepriv; - - memset(&ev, 0x00, sizeof(ev)); - if (bgroup) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - ev.src_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(ev.src_addr.sa_data, &mlmepriv->assoc_bssid[0]); - memset(&wrqu, 0x00, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); - wireless_send_event(adapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, - (char *)&ev); -} - -void r8712_recv_indicatepkt(struct _adapter *adapter, - union recv_frame *recvframe) -{ - struct recv_priv *recvpriv; - struct __queue *free_recv_queue; - _pkt *skb; - struct rx_pkt_attrib *attrib = &recvframe->u.hdr.attrib; - - recvpriv = &adapter->recvpriv; - free_recv_queue = &recvpriv->free_recv_queue; - skb = recvframe->u.hdr.pkt; - if (!skb) - goto _recv_indicatepkt_drop; - skb->data = recvframe->u.hdr.rx_data; - skb->len = recvframe->u.hdr.len; - skb_set_tail_pointer(skb, skb->len); - if ((attrib->tcpchk_valid == 1) && (attrib->tcp_chkrpt == 1)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - skb->dev = adapter->pnetdev; - skb->protocol = eth_type_trans(skb, adapter->pnetdev); - netif_rx(skb); - recvframe->u.hdr.pkt = NULL; /* pointers to NULL before - * r8712_free_recvframe() - */ - r8712_free_recvframe(recvframe, free_recv_queue); - return; -_recv_indicatepkt_drop: - /*enqueue back to free_recv_queue*/ - if (recvframe) - r8712_free_recvframe(recvframe, free_recv_queue); - recvpriv->rx_drop++; -} - -static void _r8712_reordering_ctrl_timeout_handler (struct timer_list *t) -{ - struct recv_reorder_ctrl *reorder_ctrl = - from_timer(reorder_ctrl, t, reordering_ctrl_timer); - - r8712_reordering_ctrl_timeout_handler(reorder_ctrl); -} - -void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl) -{ - timer_setup(&preorder_ctrl->reordering_ctrl_timer, - _r8712_reordering_ctrl_timeout_handler, 0); -} diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h deleted file mode 100644 index fbe3f28685064785dc1ecd9539b28d40737be22e..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/recv_osdep.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RECV_OSDEP_H_ -#define __RECV_OSDEP_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include <linux/skbuff.h> - -int _r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter); -void _r8712_free_recv_priv(struct recv_priv *precvpriv); -void r8712_recv_entry(union recv_frame *precv_frame); -void r8712_recv_indicatepkt(struct _adapter *adapter, - union recv_frame *precv_frame); -void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); -int r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter); -void r8712_free_recv_priv(struct recv_priv *precvpriv); -void r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe); -int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, - struct recv_buf *precvbuf); -void r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf); -void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); - -#endif diff --git a/drivers/staging/rtl8712/rtl8712_bitdef.h b/drivers/staging/rtl8712/rtl8712_bitdef.h deleted file mode 100644 index a4a687dcc2e7bb41e68012ece28952d4b587bc34..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_bitdef.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#ifndef __RTL8712_BITDEF_H__ -#define __RTL8712_BITDEF_H__ - -#include "rtl8712_cmdctrl_bitdef.h" -#include "rtl8712_syscfg_bitdef.h" -#include "rtl8712_macsetting_bitdef.h" -#include "rtl8712_timectrl_bitdef.h" -#include "rtl8712_fifoctrl_bitdef.h" -#include "rtl8712_ratectrl_bitdef.h" -#include "rtl8712_edcasetting_bitdef.h" -#include "rtl8712_wmac_bitdef.h" -#include "rtl8712_security_bitdef.h" -#include "rtl8712_powersave_bitdef.h" -#include "rtl8712_gp_bitdef.h" -#include "rtl8712_interrupt_bitdef.h" -#include "rtl8712_debugctrl_bitdef.h" - -#endif /* __RTL8712_BITDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c deleted file mode 100644 index bb7db96ed8219f250cbc039ba374637de5026796..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ /dev/null @@ -1,409 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl8712_cmd.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL8712_CMD_C_ - -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/sched/signal.h> -#include <linux/module.h> -#include <linux/kref.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/usb.h> -#include <linux/usb/ch9.h> -#include <linux/circ_buf.h> -#include <linux/uaccess.h> -#include <asm/byteorder.h> -#include <linux/atomic.h> -#include <linux/semaphore.h> -#include <linux/rtnetlink.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "mlme_osdep.h" -#include "rtl871x_ioctl_set.h" - -static void check_hw_pbc(struct _adapter *padapter) -{ - u8 tmp1byte; - - r8712_write8(padapter, MAC_PINMUX_CTRL, (GPIOMUX_EN | GPIOSEL_GPIO)); - tmp1byte = r8712_read8(padapter, GPIO_IO_SEL); - tmp1byte &= ~(HAL_8192S_HW_GPIO_WPS_BIT); - r8712_write8(padapter, GPIO_IO_SEL, tmp1byte); - tmp1byte = r8712_read8(padapter, GPIO_CTRL); - if (tmp1byte == 0xff) - return; - if (tmp1byte & HAL_8192S_HW_GPIO_WPS_BIT) { - /* Here we only set bPbcPressed to true - * After trigger PBC, the variable will be set to false - */ - netdev_dbg(padapter->pnetdev, "CheckPbcGPIO - PBC is pressed !!!!\n"); - /* 0 is the default value and it means the application monitors - * the HW PBC doesn't provide its pid to driver. - */ - if (padapter->pid == 0) - return; - kill_pid(find_vpid(padapter->pid), SIGUSR1, 1); - } -} - -/* query rx phy status from fw. - * Adhoc mode: beacon. - * Infrastructure mode: beacon , data. - */ -static void query_fw_rx_phy_status(struct _adapter *padapter) -{ - u32 val32 = 0; - int pollingcnts = 50; - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - r8712_write32(padapter, IOCMD_CTRL_REG, 0xf4000001); - msleep(100); - /* Wait FW complete IO Cmd */ - while ((r8712_read32(padapter, IOCMD_CTRL_REG)) && - (pollingcnts > 0)) { - pollingcnts--; - msleep(20); - } - if (pollingcnts != 0) - val32 = r8712_read32(padapter, IOCMD_DATA_REG); - else /* time out */ - val32 = 0; - val32 >>= 4; - padapter->recvpriv.fw_rssi = - (u8)r8712_signal_scale_mapping(val32); - } -} - -/* check mlme, hw, phy, or dynamic algorithm status. */ -static void StatusWatchdogCallback(struct _adapter *padapter) -{ - check_hw_pbc(padapter); - query_fw_rx_phy_status(padapter); -} - -static void r871x_internal_cmd_hdl(struct _adapter *padapter, u8 *pbuf) -{ - struct drvint_cmd_parm *pdrvcmd; - - if (!pbuf) - return; - pdrvcmd = (struct drvint_cmd_parm *)pbuf; - switch (pdrvcmd->i_cid) { - case WDG_WK_CID: - StatusWatchdogCallback(padapter); - break; - default: - break; - } - kfree(pdrvcmd->pbuf); -} - -static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) -{ - struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; - - r8712_free_cmd_obj(pcmd); - return H2C_SUCCESS; -} - -static u8 write_bbreg_hdl(struct _adapter *padapter, u8 *pbuf) -{ - void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); - struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; - - pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) - r8712_free_cmd_obj(pcmd); - else - pcmd_callback(padapter, pcmd); - return H2C_SUCCESS; -} - -static u8 read_rfreg_hdl(struct _adapter *padapter, u8 *pbuf) -{ - u32 val; - void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); - struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; - - if (pcmd->rsp && pcmd->rspsz > 0) - memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz); - pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) - r8712_free_cmd_obj(pcmd); - else - pcmd_callback(padapter, pcmd); - return H2C_SUCCESS; -} - -static u8 write_rfreg_hdl(struct _adapter *padapter, u8 *pbuf) -{ - void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); - struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; - - pcmd_callback = cmd_callback[pcmd->cmdcode].callback; - if (!pcmd_callback) - r8712_free_cmd_obj(pcmd); - else - pcmd_callback(padapter, pcmd); - return H2C_SUCCESS; -} - -static u8 sys_suspend_hdl(struct _adapter *padapter, u8 *pbuf) -{ - struct cmd_obj *pcmd = (struct cmd_obj *)pbuf; - - r8712_free_cmd_obj(pcmd); - return H2C_SUCCESS; -} - -static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, - struct cmd_obj *pcmd) -{ - struct cmd_obj *pcmd_r; - - if (!pcmd) - return pcmd; - pcmd_r = NULL; - - switch (pcmd->cmdcode) { - case GEN_CMD_CODE(_Read_BBREG): - read_bbreg_hdl(padapter, (u8 *)pcmd); - break; - case GEN_CMD_CODE(_Write_BBREG): - write_bbreg_hdl(padapter, (u8 *)pcmd); - break; - case GEN_CMD_CODE(_Read_RFREG): - read_rfreg_hdl(padapter, (u8 *)pcmd); - break; - case GEN_CMD_CODE(_Write_RFREG): - write_rfreg_hdl(padapter, (u8 *)pcmd); - break; - case GEN_CMD_CODE(_SetUsbSuspend): - sys_suspend_hdl(padapter, (u8 *)pcmd); - break; - case GEN_CMD_CODE(_JoinBss): - r8712_joinbss_reset(padapter); - /* Before set JoinBss_CMD to FW, driver must ensure FW is in - * PS_MODE_ACTIVE. Directly write rpwm to radio on and assign - * new pwr_mode to Driver, instead of use workitem to change - * state. - */ - if (padapter->pwrctrlpriv.pwr_mode > PS_MODE_ACTIVE) { - padapter->pwrctrlpriv.pwr_mode = PS_MODE_ACTIVE; - mutex_lock(&padapter->pwrctrlpriv.mutex_lock); - r8712_set_rpwm(padapter, PS_STATE_S4); - mutex_unlock(&padapter->pwrctrlpriv.mutex_lock); - } - pcmd_r = pcmd; - break; - case _DRV_INT_CMD_: - r871x_internal_cmd_hdl(padapter, pcmd->parmbuf); - r8712_free_cmd_obj(pcmd); - pcmd_r = NULL; - break; - default: - pcmd_r = pcmd; - break; - } - return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */ -} - -u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd) -{ - int pollingcnts = 50; - - r8712_write32(pAdapter, IOCMD_CTRL_REG, cmd); - msleep(100); - while ((r8712_read32(pAdapter, IOCMD_CTRL_REG != 0)) && - (pollingcnts > 0)) { - pollingcnts--; - msleep(20); - } - if (pollingcnts == 0) - return false; - return true; -} - -void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag) -{ - if (flag == 0) /* set */ - r8712_write32(pAdapter, IOCMD_DATA_REG, *value); - else /* query */ - *value = r8712_read32(pAdapter, IOCMD_DATA_REG); -} - -int r8712_cmd_thread(void *context) -{ - struct cmd_obj *pcmd; - unsigned int cmdsz, wr_sz; - __le32 *pcmdbuf; - struct tx_desc *pdesc; - void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd); - struct _adapter *padapter = context; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct completion *cmd_queue_comp = - &pcmdpriv->cmd_queue_comp; - struct mutex *pwctrl_lock = &padapter->pwrctrlpriv.mutex_lock; - - allow_signal(SIGTERM); - while (1) { - if (wait_for_completion_interruptible(cmd_queue_comp)) - break; - if (padapter->driver_stopped || padapter->surprise_removed) - break; - if (r8712_register_cmd_alive(padapter)) - continue; -_next: - pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue); - if (!(pcmd)) { - r8712_unregister_cmd_alive(padapter); - continue; - } - pcmdbuf = (__le32 *)pcmdpriv->cmd_buf; - pdesc = (struct tx_desc *)pcmdbuf; - memset(pdesc, 0, TXDESC_SIZE); - pcmd = cmd_hdl_filter(padapter, pcmd); - if (pcmd) { /* if pcmd != NULL, cmd will be handled by f/w */ - struct dvobj_priv *pdvobj = &padapter->dvobjpriv; - u8 blnPending = 0; - u16 cmdcode = pcmd->cmdcode; - - pcmdpriv->cmd_issued_cnt++; - cmdsz = round_up(pcmd->cmdsz, 8); - wr_sz = TXDESC_SIZE + 8 + cmdsz; - pdesc->txdw0 |= cpu_to_le32((wr_sz - TXDESC_SIZE) & - 0x0000ffff); - if (pdvobj->ishighspeed) { - if ((wr_sz % 512) == 0) - blnPending = 1; - } else { - if ((wr_sz % 64) == 0) - blnPending = 1; - } - if (blnPending) { /* 32 bytes for TX Desc - 8 offset */ - pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + - OFFSET_SZ + 8) << OFFSET_SHT) & - 0x00ff0000); - } else { - pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + - OFFSET_SZ) << - OFFSET_SHT) & - 0x00ff0000); - } - pdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - pdesc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & - 0x00001f00); - pcmdbuf += (TXDESC_SIZE >> 2); - *pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) | - (pcmd->cmdcode << 16) | - (pcmdpriv->cmd_seq << 24)); - pcmdbuf += 2; /* 8 bytes alignment */ - memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); - if (blnPending) - wr_sz += 8; /* Append 8 bytes */ - r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz, - (u8 *)pdesc); - pcmdpriv->cmd_seq++; - if (cmdcode == GEN_CMD_CODE(_CreateBss)) { - pcmd->res = H2C_SUCCESS; - pcmd_callback = cmd_callback[cmdcode].callback; - if (pcmd_callback) - pcmd_callback(padapter, pcmd); - continue; - } - if (cmdcode == GEN_CMD_CODE(_SetPwrMode)) { - if (padapter->pwrctrlpriv.bSleep) { - mutex_lock(pwctrl_lock); - r8712_set_rpwm(padapter, PS_STATE_S2); - mutex_unlock(pwctrl_lock); - } - } - r8712_free_cmd_obj(pcmd); - if (list_empty(&pcmdpriv->cmd_queue.queue)) { - r8712_unregister_cmd_alive(padapter); - continue; - } else { - goto _next; - } - } else { - goto _next; - } - flush_signals_thread(); - } - /* free all cmd_obj resources */ - do { - pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue); - if (!pcmd) - break; - r8712_free_cmd_obj(pcmd); - } while (1); - complete(&pcmdpriv->terminate_cmdthread_comp); - return 0; -} - -void r8712_event_handle(struct _adapter *padapter, __le32 *peventbuf) -{ - u8 evt_code, evt_seq; - u16 evt_sz; - void (*event_callback)(struct _adapter *dev, u8 *pbuf); - struct evt_priv *pevt_priv = &padapter->evtpriv; - - if (!peventbuf) - goto _abort_event_; - evt_sz = (u16)(le32_to_cpu(*peventbuf) & 0xffff); - evt_seq = (u8)((le32_to_cpu(*peventbuf) >> 24) & 0x7f); - evt_code = (u8)((le32_to_cpu(*peventbuf) >> 16) & 0xff); - /* checking event sequence... */ - if ((evt_seq & 0x7f) != pevt_priv->event_seq) { - pevt_priv->event_seq = ((evt_seq + 1) & 0x7f); - goto _abort_event_; - } - /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) { - pevt_priv->event_seq = ((evt_seq + 1) & 0x7f); - goto _abort_event_; - } else if ((evt_code == GEN_EVT_CODE(_Survey)) && - (evt_sz > sizeof(struct wlan_bssid_ex))) { - pevt_priv->event_seq = ((evt_seq + 1) & 0x7f); - goto _abort_event_; - } - /* checking if event size match the event parm size */ - if ((wlanevents[evt_code].parmsize) && - (wlanevents[evt_code].parmsize != evt_sz)) { - pevt_priv->event_seq = ((evt_seq + 1) & 0x7f); - goto _abort_event_; - } else if ((evt_sz == 0) && (evt_code != GEN_EVT_CODE(_WPS_PBC))) { - pevt_priv->event_seq = ((evt_seq + 1) & 0x7f); - goto _abort_event_; - } - pevt_priv->event_seq++; /* update evt_seq */ - if (pevt_priv->event_seq > 127) - pevt_priv->event_seq = 0; - /* move to event content, 8 bytes alignment */ - peventbuf = peventbuf + 2; - event_callback = wlanevents[evt_code].event_callback; - if (event_callback) - event_callback(padapter, (u8 *)peventbuf); - pevt_priv->evt_done_cnt++; -_abort_event_: - return; -} diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h deleted file mode 100644 index a34d0dd023f33bbc4960bc6e720f2d3c31c71706..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_cmd.h +++ /dev/null @@ -1,231 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_CMD_H_ -#define __RTL8712_CMD_H_ - -#define CMD_HDR_SZ 8 - -u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd); -void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag); - -struct cmd_hdr { - u32 cmd_dw0; - u32 cmd_dw1; -}; - -enum rtl8712_h2c_cmd { - GEN_CMD_CODE(_Read_MACREG), /*0*/ - GEN_CMD_CODE(_Write_MACREG), - GEN_CMD_CODE(_Read_BBREG), - GEN_CMD_CODE(_Write_BBREG), - GEN_CMD_CODE(_Read_RFREG), - GEN_CMD_CODE(_Write_RFREG), /*5*/ - GEN_CMD_CODE(_Read_EEPROM), - GEN_CMD_CODE(_Write_EEPROM), - GEN_CMD_CODE(_Read_EFUSE), - GEN_CMD_CODE(_Write_EFUSE), - - GEN_CMD_CODE(_Read_CAM), /*10*/ - GEN_CMD_CODE(_Write_CAM), - GEN_CMD_CODE(_setBCNITV), - GEN_CMD_CODE(_setMBIDCFG), - GEN_CMD_CODE(_JoinBss), /*14*/ - GEN_CMD_CODE(_DisConnect), /*15*/ - GEN_CMD_CODE(_CreateBss), - GEN_CMD_CODE(_SetOpMode), - GEN_CMD_CODE(_SiteSurvey), /*18*/ - GEN_CMD_CODE(_SetAuth), - - GEN_CMD_CODE(_SetKey), /*20*/ - GEN_CMD_CODE(_SetStaKey), - GEN_CMD_CODE(_SetAssocSta), - GEN_CMD_CODE(_DelAssocSta), - GEN_CMD_CODE(_SetStaPwrState), - GEN_CMD_CODE(_SetBasicRate), /*25*/ - GEN_CMD_CODE(_GetBasicRate), - GEN_CMD_CODE(_SetDataRate), - GEN_CMD_CODE(_GetDataRate), - GEN_CMD_CODE(_SetPhyInfo), - - GEN_CMD_CODE(_GetPhyInfo), /*30*/ - GEN_CMD_CODE(_SetPhy), - GEN_CMD_CODE(_GetPhy), - GEN_CMD_CODE(_readRssi), - GEN_CMD_CODE(_readGain), - GEN_CMD_CODE(_SetAtim), /*35*/ - GEN_CMD_CODE(_SetPwrMode), - GEN_CMD_CODE(_JoinbssRpt), - GEN_CMD_CODE(_SetRaTable), - GEN_CMD_CODE(_GetRaTable), - - GEN_CMD_CODE(_GetCCXReport), /*40*/ - GEN_CMD_CODE(_GetDTMReport), - GEN_CMD_CODE(_GetTXRateStatistics), - GEN_CMD_CODE(_SetUsbSuspend), - GEN_CMD_CODE(_SetH2cLbk), - GEN_CMD_CODE(_AddBAReq), /*45*/ - - GEN_CMD_CODE(_SetChannel), /*46*/ -/* MP_OFFLOAD Start (47~54)*/ - GEN_CMD_CODE(_SetTxPower), - GEN_CMD_CODE(_SwitchAntenna), - GEN_CMD_CODE(_SetCrystalCap), - GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/ - GEN_CMD_CODE(_SetSingleToneTx), - GEN_CMD_CODE(_SetCarrierSuppressionTx), - GEN_CMD_CODE(_SetContinuousTx), - GEN_CMD_CODE(_SwitchBandwidth), /*54*/ -/* MP_OFFLOAD End*/ - GEN_CMD_CODE(_TX_Beacon), /*55*/ - GEN_CMD_CODE(_SetPowerTracking), - GEN_CMD_CODE(_AMSDU_TO_AMPDU), /*57*/ - GEN_CMD_CODE(_SetMacAddress), /*58*/ - - GEN_CMD_CODE(_DisconnectCtrl), /*59*/ - GEN_CMD_CODE(_SetChannelPlan), /*60*/ - GEN_CMD_CODE(_DisconnectCtrlEx), /*61*/ - - /* To do, modify these h2c cmd, add or delete */ - GEN_CMD_CODE(_GetH2cLbk), - - /* WPS extra IE */ - GEN_CMD_CODE(_SetProbeReqExtraIE), - GEN_CMD_CODE(_SetAssocReqExtraIE), - GEN_CMD_CODE(_SetProbeRspExtraIE), - GEN_CMD_CODE(_SetAssocRspExtraIE), - - /* the following is driver will do */ - GEN_CMD_CODE(_GetCurDataRate), - - GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to - * transmit packet after association - */ - GEN_CMD_CODE(_GetRxRetrycnt), /* to record total number of the - * received frame with ReTry bit set in - * the WLAN header - */ - - GEN_CMD_CODE(_GetBCNOKcnt), - GEN_CMD_CODE(_GetBCNERRcnt), - GEN_CMD_CODE(_GetCurTxPwrLevel), - - GEN_CMD_CODE(_SetDIG), - GEN_CMD_CODE(_SetRA), - GEN_CMD_CODE(_SetPT), - GEN_CMD_CODE(_ReadTSSI), - - MAX_H2CCMD -}; - -#define _GetBBReg_CMD_ _Read_BBREG_CMD_ -#define _SetBBReg_CMD_ _Write_BBREG_CMD_ -#define _GetRFReg_CMD_ _Read_RFREG_CMD_ -#define _SetRFReg_CMD_ _Write_RFREG_CMD_ -#define _DRV_INT_CMD_ (MAX_H2CCMD + 1) -#define _SetRFIntFs_CMD_ (MAX_H2CCMD + 2) - -#ifdef _RTL8712_CMD_C_ -static struct _cmd_callback cmd_callback[] = { - {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/ - {GEN_CMD_CODE(_Write_MACREG), NULL}, - {GEN_CMD_CODE(_Read_BBREG), NULL}, - {GEN_CMD_CODE(_Write_BBREG), NULL}, - {GEN_CMD_CODE(_Read_RFREG), &r8712_getbbrfreg_cmdrsp_callback}, - {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/ - {GEN_CMD_CODE(_Read_EEPROM), NULL}, - {GEN_CMD_CODE(_Write_EEPROM), NULL}, - {GEN_CMD_CODE(_Read_EFUSE), NULL}, - {GEN_CMD_CODE(_Write_EFUSE), NULL}, - - {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/ - {GEN_CMD_CODE(_Write_CAM), NULL}, - {GEN_CMD_CODE(_setBCNITV), NULL}, - {GEN_CMD_CODE(_setMBIDCFG), NULL}, - {GEN_CMD_CODE(_JoinBss), &r8712_joinbss_cmd_callback}, /*14*/ - {GEN_CMD_CODE(_DisConnect), &r8712_disassoc_cmd_callback}, /*15*/ - {GEN_CMD_CODE(_CreateBss), &r8712_createbss_cmd_callback}, - {GEN_CMD_CODE(_SetOpMode), NULL}, - {GEN_CMD_CODE(_SiteSurvey), &r8712_survey_cmd_callback}, /*18*/ - {GEN_CMD_CODE(_SetAuth), NULL}, - - {GEN_CMD_CODE(_SetKey), NULL}, /*20*/ - {GEN_CMD_CODE(_SetStaKey), &r8712_setstaKey_cmdrsp_callback}, - {GEN_CMD_CODE(_SetAssocSta), &r8712_setassocsta_cmdrsp_callback}, - {GEN_CMD_CODE(_DelAssocSta), NULL}, - {GEN_CMD_CODE(_SetStaPwrState), NULL}, - {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/ - {GEN_CMD_CODE(_GetBasicRate), NULL}, - {GEN_CMD_CODE(_SetDataRate), NULL}, - {GEN_CMD_CODE(_GetDataRate), NULL}, - {GEN_CMD_CODE(_SetPhyInfo), NULL}, - - {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/ - {GEN_CMD_CODE(_SetPhy), NULL}, - {GEN_CMD_CODE(_GetPhy), NULL}, - {GEN_CMD_CODE(_readRssi), NULL}, - {GEN_CMD_CODE(_readGain), NULL}, - {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/ - {GEN_CMD_CODE(_SetPwrMode), NULL}, - {GEN_CMD_CODE(_JoinbssRpt), NULL}, - {GEN_CMD_CODE(_SetRaTable), NULL}, - {GEN_CMD_CODE(_GetRaTable), NULL}, - - {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/ - {GEN_CMD_CODE(_GetDTMReport), NULL}, - {GEN_CMD_CODE(_GetTXRateStatistics), NULL}, - {GEN_CMD_CODE(_SetUsbSuspend), NULL}, - {GEN_CMD_CODE(_SetH2cLbk), NULL}, - {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/ - - {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/ -/* MP_OFFLOAD Start (47~54)*/ - {GEN_CMD_CODE(_SetTxPower), NULL}, - {GEN_CMD_CODE(_SwitchAntenna), NULL}, - {GEN_CMD_CODE(_SetCrystalCap), NULL}, - {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/ - {GEN_CMD_CODE(_SetSingleToneTx), NULL}, - {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL}, - {GEN_CMD_CODE(_SetContinuousTx), NULL}, - {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/ -/* MP_OFFLOAD End*/ - {GEN_CMD_CODE(_TX_Beacon), NULL}, /*55*/ - {GEN_CMD_CODE(_SetPowerTracking), NULL}, - {GEN_CMD_CODE(_AMSDU_TO_AMPDU), NULL}, /*57*/ - {GEN_CMD_CODE(_SetMacAddress), NULL}, /*58*/ - - {GEN_CMD_CODE(_DisconnectCtrl), NULL}, /*59*/ - {GEN_CMD_CODE(_SetChannelPlan), NULL}, /*60*/ - {GEN_CMD_CODE(_DisconnectCtrlEx), NULL}, /*61*/ - - /* To do, modify these h2c cmd, add or delete */ - {GEN_CMD_CODE(_GetH2cLbk), NULL}, - - {_SetProbeReqExtraIE_CMD_, NULL}, - {_SetAssocReqExtraIE_CMD_, NULL}, - {_SetProbeRspExtraIE_CMD_, NULL}, - {_SetAssocRspExtraIE_CMD_, NULL}, - {_GetCurDataRate_CMD_, NULL}, - {_GetTxRetrycnt_CMD_, NULL}, - {_GetRxRetrycnt_CMD_, NULL}, - {_GetBCNOKcnt_CMD_, NULL}, - {_GetBCNERRcnt_CMD_, NULL}, - {_GetCurTxPwrLevel_CMD_, NULL}, - {_SetDIG_CMD_, NULL}, - {_SetRA_CMD_, NULL}, - {_SetPT_CMD_, NULL}, - {GEN_CMD_CODE(_ReadTSSI), &r8712_readtssi_cmdrsp_callback} -}; -#endif - -#endif diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h deleted file mode 100644 index 68bdec07f51e855846845674dc1bb9b814a6127c..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_CMDCTRL_BITDEF_H__ -#define __RTL8712_CMDCTRL_BITDEF_H__ - -/* - * 2. Command Control Registers (Offset: 0x0040 - 0x004F) - */ -/*--------------------------------------------------------------------------*/ -/* 8192S (CMD) command register bits (Offset 0x40, 16 bits)*/ -/*--------------------------------------------------------------------------*/ -#define _APSDOFF_STATUS BIT(15) -#define _APSDOFF BIT(14) -#define _BBRSTn BIT(13) /*Enable OFDM/CCK*/ -#define _BB_GLB_RSTn BIT(12) /*Enable BB*/ -#define _SCHEDULE_EN BIT(10) /*Enable MAC scheduler*/ -#define _MACRXEN BIT(9) -#define _MACTXEN BIT(8) -#define _DDMA_EN BIT(7) /*FW off load function enable*/ -#define _FW2HW_EN BIT(6) /*MAC every module reset */ -#define _RXDMA_EN BIT(5) -#define _TXDMA_EN BIT(4) -#define _HCI_RXDMA_EN BIT(3) -#define _HCI_TXDMA_EN BIT(2) - -/*TXPAUSE*/ -#define _STOPHCCA BIT(6) -#define _STOPHIGH BIT(5) -#define _STOPMGT BIT(4) -#define _STOPVO BIT(3) -#define _STOPVI BIT(2) -#define _STOPBE BIT(1) -#define _STOPBK BIT(0) - -/*TCR*/ -#define _DISCW BIT(20) -#define _ICV BIT(19) -#define _CFEND_FMT BIT(17) -#define _CRC BIT(16) -#define _FWRDY BIT(7) -#define _BASECHG BIT(6) -#define _IMEM_RDY BIT(5) -#define _DMEM_CODE_DONE BIT(4) -#define _EMEM_CHK_RPT BIT(3) -#define _EMEM_CODE_DONE BIT(2) -#define _IMEM_CHK_RPT BIT(1) -#define _IMEM_CODE_DONE BIT(0) - -#define _TXDMA_INIT_VALUE (_IMEM_CHK_RPT | _EMEM_CHK_RPT) - -/*RCR*/ -#define _ENMBID BIT(27) -#define _APP_PHYST_RXFF BIT(25) -#define _APP_PHYST_STAFF BIT(24) -#define _CBSSID BIT(23) -#define _APWRMGT BIT(22) -#define _ADD3 BIT(21) -#define _AMF BIT(20) -#define _ACF BIT(19) -#define _ADF BIT(18) -#define _APP_MIC BIT(17) -#define _APP_ICV BIT(16) -#define _RXFTH_MSK 0x0000E000 -#define _RXFTH_SHT 13 -#define _AICV BIT(12) -#define _RXPKTLMT_MSK 0x00000FC0 -#define _RXPKTLMT_SHT 6 -#define _ACRC32 BIT(5) -#define _AB BIT(3) -#define _AM BIT(2) -#define _APM BIT(1) -#define _AAP BIT(0) - -/*MSR*/ -#define _NETTYPE_MSK 0x03 -#define _NETTYPE_SHT 0 - -/*BT*/ -#define _BTMODE_MSK 0x06 -#define _BTMODE_SHT 1 -#define _ENBT BIT(0) - -/*MBIDCTRL*/ -#define _ENMBID_MODE BIT(15) -#define _BCNNO_MSK 0x7000 -#define _BCNNO_SHT 12 -#define _BCNSPACE_MSK 0x0FFF -#define _BCNSPACE_SHT 0 - -#endif /* __RTL8712_CMDCTRL_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h deleted file mode 100644 index fc67771c89b7851e01769eda3bb1f7ce200be9c5..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_CMDCTRL_REGDEF_H__ -#define __RTL8712_CMDCTRL_REGDEF_H__ - -#define CR (RTL8712_CMDCTRL_ + 0x0000) -#define TXPAUSE (RTL8712_CMDCTRL_ + 0x0002) -#define TCR (RTL8712_CMDCTRL_ + 0x0004) -#define RCR (RTL8712_CMDCTRL_ + 0x0008) -#define MSR (RTL8712_CMDCTRL_ + 0x000C) -#define SYSF_CFG (RTL8712_CMDCTRL_ + 0x000D) -#define MBIDCTRL (RTL8712_CMDCTRL_ + 0x000E) - -#endif /* __RTL8712_CMDCTRL_REGDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h deleted file mode 100644 index bb3863467f0d67951b03b1edc47135179805eae8..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_DEBUGCTRL_BITDEF_H__ -#define __RTL8712_DEBUGCTRL_BITDEF_H__ - -/*BIST*/ -#define _BIST_RST BIT(0) - -/*LMS*/ -#define _LMS_MSK 0x03 - -/*WDG_CTRL*/ -#define _OVSEL_MSK 0x0600 -#define _OVSEL_SHT 9 -#define _WDGCLR BIT(8) -#define _WDGEN_MSK 0x00FF -#define _WDGEN_SHT 0 - -/*INTM*/ -#define _TXTIMER_MSK 0xF000 -#define _TXTIMER_SHT 12 -#define _TXNUM_MSK 0x0F00 -#define _TXNUM_SHT 8 -#define _RXTIMER_MSK 0x00F0 -#define _RXTIMER_SHT 4 -#define _RXNUM_MSK 0x000F -#define _RXNUM_SHT 0 - -/*FDLOCKTURN0*/ -/*FDLOCKTURN1*/ -#define _TURN1 BIT(0) - -/*FDLOCKFLAG0*/ -/*FDLOCKFLAG1*/ -#define _LOCKFLAG1_MSK 0x03 - -#endif /* __RTL8712_DEBUGCTRL_BITDEF_H__ */ diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h deleted file mode 100644 index 319220e9d53de3f0111893b396c66ea80988b19e..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_DEBUGCTRL_REGDEF_H__ -#define __RTL8712_DEBUGCTRL_REGDEF_H__ - -#define BIST (RTL8712_DEBUGCTRL_ + 0x00) -#define DBS (RTL8712_DEBUGCTRL_ + 0x04) -#define LMS (RTL8712_DEBUGCTRL_ + 0x05) -#define CPUINST (RTL8712_DEBUGCTRL_ + 0x08) -#define CPUCAUSE (RTL8712_DEBUGCTRL_ + 0x0C) -#define LBUS_ERR_ADDR (RTL8712_DEBUGCTRL_ + 0x10) -#define LBUS_ERR_CMD (RTL8712_DEBUGCTRL_ + 0x14) -#define LBUS_ERR_DATA_L (RTL8712_DEBUGCTRL_ + 0x18) -#define LBUS_ERR_DATA_H (RTL8712_DEBUGCTRL_ + 0x1C) -#define LBUS_EXCEPTION_ADDR (RTL8712_DEBUGCTRL_ + 0x20) -#define WDG_CTRL (RTL8712_DEBUGCTRL_ + 0x24) -#define INTMTU (RTL8712_DEBUGCTRL_ + 0x28) -#define INTM (RTL8712_DEBUGCTRL_ + 0x2A) -#define FDLOCKTURN0 (RTL8712_DEBUGCTRL_ + 0x2C) -#define FDLOCKTURN1 (RTL8712_DEBUGCTRL_ + 0x2D) -#define FDLOCKFLAG0 (RTL8712_DEBUGCTRL_ + 0x2E) -#define FDLOCKFLAG1 (RTL8712_DEBUGCTRL_ + 0x2F) -#define TRXPKTBUF_DBG_DATA (RTL8712_DEBUGCTRL_ + 0x30) -#define TRXPKTBUF_DBG_CTRL (RTL8712_DEBUGCTRL_ + 0x38) -#define DPLL_MON (RTL8712_DEBUGCTRL_ + 0x3A) - -#endif /* __RTL8712_DEBUGCTRL_REGDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h deleted file mode 100644 index 9048d6a6529697ddd9b71f1ac811497afd550402..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_EDCASETTING_BITDEF_H__ -#define __RTL8712_EDCASETTING_BITDEF_H__ - -/*EDCAPARAM*/ -#define _TXOPLIMIT_MSK 0xFFFF0000 -#define _TXOPLIMIT_SHT 16 -#define _ECWIN_MSK 0x0000FF00 -#define _ECWIN_SHT 8 -#define _AIFS_MSK 0x000000FF -#define _AIFS_SHT 0 - -/*BCNTCFG*/ -#define _BCNECW_MSK 0xFF00 -#define _BCNECW_SHT 8 -#define _BCNIFS_MSK 0x00FF -#define _BCNIFS_SHT 0 - -/*CWRR*/ -#define _CWRR_MSK 0x03FF - -/*ACMAVG*/ -#define _AVG_TIME_UP BIT(3) -#define _AVGPERIOD_MSK 0x03 - -/*ACMHWCTRL*/ -#define _VOQ_ACM_STATUS BIT(6) -#define _VIQ_ACM_STATUS BIT(5) -#define _BEQ_ACM_STATUS BIT(4) -#define _VOQ_ACM_EN BIT(3) -#define _VIQ_ACM_EN BIT(2) -#define _BEQ_ACM_EN BIT(1) -#define _ACMHWEN BIT(0) - -/*VO_ADMTIME*/ -#define _VO_ACM_RUT BIT(18) -#define _VO_ADMTIME_MSK 0x0003FFF - -/*VI_ADMTIME*/ -#define _VI_ACM_RUT BIT(18) -#define _VI_ADMTIME_MSK 0x0003FFF - -/*BE_ADMTIME*/ -#define _BE_ACM_RUT BIT(18) -#define _BE_ADMTIME_MSK 0x0003FFF - -/*Retry limit reg*/ -#define _SRL_MSK 0xFF00 -#define _SRL_SHT 8 -#define _LRL_MSK 0x00FF -#define _LRL_SHT 0 - -#endif /* __RTL8712_EDCASETTING_BITDEF_H__*/ diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h deleted file mode 100644 index 02ec9f3bba6659774eaa6eacbab93ad852ae4d5a..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_EDCASETTING_REGDEF_H__ -#define __RTL8712_EDCASETTING_REGDEF_H__ - -#define EDCA_VO_PARAM (RTL8712_EDCASETTING_ + 0x00) -#define EDCA_VI_PARAM (RTL8712_EDCASETTING_ + 0x04) -#define EDCA_BE_PARAM (RTL8712_EDCASETTING_ + 0x08) -#define EDCA_BK_PARAM (RTL8712_EDCASETTING_ + 0x0C) -#define BCNTCFG (RTL8712_EDCASETTING_ + 0x10) -#define CWRR (RTL8712_EDCASETTING_ + 0x12) -#define ACMAVG (RTL8712_EDCASETTING_ + 0x16) -#define ACMHWCTRL (RTL8712_EDCASETTING_ + 0x17) -#define VO_ADMTIME (RTL8712_EDCASETTING_ + 0x18) -#define VI_ADMTIME (RTL8712_EDCASETTING_ + 0x1C) -#define BE_ADMTIME (RTL8712_EDCASETTING_ + 0x20) -#define RL (RTL8712_EDCASETTING_ + 0x24) - -#endif /* __RTL8712_EDCASETTING_REGDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c deleted file mode 100644 index a39d6c06648f5d7dc4a286ce71cf120c4b649baf..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_efuse.c +++ /dev/null @@ -1,563 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * rtl8712_efuse.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL8712_EFUSE_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "rtl8712_efuse.h" - -/* reserve 3 bytes for HW stop read */ -static int efuse_available_max_size = EFUSE_MAX_SIZE - 3 /*0x1FD*/; - -static void efuse_reg_ctrl(struct _adapter *adapter, u8 bPowerOn) -{ - u8 tmpu8 = 0; - - if (bPowerOn) { - /* -----------------e-fuse pwr & clk reg ctrl --------------- - * Enable LDOE25 Macro Block - */ - tmpu8 = r8712_read8(adapter, EFUSE_TEST + 3); - tmpu8 |= 0x80; - r8712_write8(adapter, EFUSE_TEST + 3, tmpu8); - msleep(20); /* for some platform , need some delay time */ - /* Change Efuse Clock for write action to 40MHZ */ - r8712_write8(adapter, EFUSE_CLK_CTRL, 0x03); - msleep(20); /* for some platform , need some delay time */ - } else { - /* -----------------e-fuse pwr & clk reg ctrl ----------------- - * Disable LDOE25 Macro Block - */ - tmpu8 = r8712_read8(adapter, EFUSE_TEST + 3); - tmpu8 &= 0x7F; - r8712_write8(adapter, EFUSE_TEST + 3, tmpu8); - /* Change Efuse Clock for write action to 500K */ - r8712_write8(adapter, EFUSE_CLK_CTRL, 0x02); - } -} - -/* - * Before write E-Fuse, this function must be called. - */ -u8 r8712_efuse_reg_init(struct _adapter *adapter) -{ - return true; -} - -void r8712_efuse_reg_uninit(struct _adapter *adapter) -{ - efuse_reg_ctrl(adapter, false); -} - -static u8 efuse_one_byte_read(struct _adapter *adapter, u16 addr, u8 *data) -{ - u8 tmpidx = 0, bResult; - - /* -----------------e-fuse reg ctrl --------------------------------- */ - r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */ - r8712_write8(adapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) | - (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC)); - r8712_write8(adapter, EFUSE_CTRL + 3, 0x72); /* read cmd */ - /* wait for complete */ - while (!(0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) { - *data = r8712_read8(adapter, EFUSE_CTRL); - bResult = true; - } else { - *data = 0xff; - bResult = false; - } - return bResult; -} - -static u8 efuse_one_byte_write(struct _adapter *adapter, u16 addr, u8 data) -{ - u8 tmpidx = 0, bResult; - - /* -----------------e-fuse reg ctrl -------------------------------- */ - r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */ - r8712_write8(adapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) | - (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC)); - r8712_write8(adapter, EFUSE_CTRL, data); /* data */ - r8712_write8(adapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */ - /* wait for complete */ - while ((0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) - bResult = true; - else - bResult = false; - return bResult; -} - -static u8 efuse_one_byte_rw(struct _adapter *adapter, u8 bRead, u16 addr, - u8 *data) -{ - u8 tmpidx = 0, tmpv8 = 0, bResult; - - /* -----------------e-fuse reg ctrl --------------------------------- */ - r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */ - tmpv8 = ((u8)((addr >> 8) & 0x03)) | - (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC); - r8712_write8(adapter, EFUSE_CTRL + 2, tmpv8); - if (bRead) { - r8712_write8(adapter, EFUSE_CTRL + 3, 0x72); /* read cmd */ - while (!(0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) { - *data = r8712_read8(adapter, EFUSE_CTRL); - bResult = true; - } else { - *data = 0; - bResult = false; - } - } else { - r8712_write8(adapter, EFUSE_CTRL, *data); /* data */ - r8712_write8(adapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */ - while ((0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) && - (tmpidx < 100)) - tmpidx++; - if (tmpidx < 100) - bResult = true; - else - bResult = false; - } - return bResult; -} - -static u8 efuse_is_empty(struct _adapter *adapter, u8 *empty) -{ - u8 value, ret = true; - - /* read one byte to check if E-Fuse is empty */ - if (efuse_one_byte_rw(adapter, true, 0, &value)) { - if (value == 0xFF) - *empty = true; - else - *empty = false; - } else { - ret = false; - } - return ret; -} - -void r8712_efuse_change_max_size(struct _adapter *adapter) -{ - u16 pre_pg_data_saddr = 0x1FB; - u16 i; - u16 pre_pg_data_size = 5; - u8 pre_pg_data[5]; - - for (i = 0; i < pre_pg_data_size; i++) - efuse_one_byte_read(adapter, pre_pg_data_saddr + i, - &pre_pg_data[i]); - if ((pre_pg_data[0] == 0x03) && (pre_pg_data[1] == 0x00) && - (pre_pg_data[2] == 0x00) && (pre_pg_data[3] == 0x00) && - (pre_pg_data[4] == 0x0C)) - efuse_available_max_size -= pre_pg_data_size; -} - -int r8712_efuse_get_max_size(struct _adapter *adapter) -{ - return efuse_available_max_size; -} - -static u8 calculate_word_cnts(const u8 word_en) -{ - u8 word_cnts = 0; - u8 word_idx; - - for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) - if (!(word_en & BIT(word_idx))) - word_cnts++; /* 0 : write enable */ - return word_cnts; -} - -static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata, - u8 *targetdata) -{ - u8 tmpindex = 0; - u8 word_idx, byte_idx; - - for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) { - if (!(word_en & BIT(word_idx))) { - byte_idx = word_idx * 2; - targetdata[byte_idx] = sourdata[tmpindex++]; - targetdata[byte_idx + 1] = sourdata[tmpindex++]; - } - } -} - -u16 r8712_efuse_get_current_size(struct _adapter *adapter) -{ - int bContinual = true; - u16 efuse_addr = 0; - u8 hworden = 0; - u8 efuse_data, word_cnts = 0; - - while (bContinual && efuse_one_byte_read(adapter, efuse_addr, &efuse_data) && - (efuse_addr < efuse_available_max_size)) { - if (efuse_data != 0xFF) { - hworden = efuse_data & 0x0F; - word_cnts = calculate_word_cnts(hworden); - /* read next header */ - efuse_addr = efuse_addr + (word_cnts * 2) + 1; - } else { - bContinual = false; - } - } - return efuse_addr; -} - -u8 r8712_efuse_pg_packet_read(struct _adapter *adapter, u8 offset, u8 *data) -{ - u8 hoffset = 0, hworden = 0, word_cnts = 0; - u16 efuse_addr = 0; - u8 efuse_data; - u8 tmpidx = 0; - u8 tmpdata[PGPKT_DATA_SIZE]; - u8 ret = true; - - if (!data) - return false; - if (offset > 0x0f) - return false; - memset(data, 0xFF, sizeof(u8) * PGPKT_DATA_SIZE); - while (efuse_addr < efuse_available_max_size) { - if (efuse_one_byte_read(adapter, efuse_addr, &efuse_data)) { - if (efuse_data == 0xFF) - break; - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - word_cnts = calculate_word_cnts(hworden); - if (hoffset == offset) { - memset(tmpdata, 0xFF, PGPKT_DATA_SIZE); - for (tmpidx = 0; tmpidx < word_cnts * 2; - tmpidx++) { - if (efuse_one_byte_read(adapter, efuse_addr + 1 + tmpidx, - &efuse_data)) { - tmpdata[tmpidx] = efuse_data; - } else { - ret = false; - } - } - pgpacket_copy_data(hworden, tmpdata, data); - } - efuse_addr += 1 + (word_cnts * 2); - } else { - ret = false; - break; - } - } - return ret; -} - -static u8 fix_header(struct _adapter *adapter, u8 header, u16 header_addr) -{ - struct PGPKT_STRUCT pkt; - u8 offset, word_en, value; - u16 addr; - int i; - u8 ret = true; - - pkt.offset = GET_EFUSE_OFFSET(header); - pkt.word_en = GET_EFUSE_WORD_EN(header); - addr = header_addr + 1 + calculate_word_cnts(pkt.word_en) * 2; - if (addr > efuse_available_max_size) - return false; - /* retrieve original data */ - addr = 0; - while (addr < header_addr) { - if (!efuse_one_byte_read(adapter, addr++, &value)) { - ret = false; - break; - } - offset = GET_EFUSE_OFFSET(value); - word_en = GET_EFUSE_WORD_EN(value); - if (pkt.offset != offset) { - addr += calculate_word_cnts(word_en) * 2; - continue; - } - for (i = 0; i < PGPKG_MAX_WORDS; i++) { - if (!(BIT(i) & word_en)) - continue; - if (BIT(i) & pkt.word_en) { - if (efuse_one_byte_read(adapter, - addr, - &value)) - pkt.data[i * 2] = value; - else - return false; - if (efuse_one_byte_read(adapter, - addr + 1, - &value)) - pkt.data[i * 2 + 1] = value; - else - return false; - } - addr += 2; - } - } - if (addr != header_addr) - return false; - addr++; - /* fill original data */ - for (i = 0; i < PGPKG_MAX_WORDS; i++) { - if (BIT(i) & pkt.word_en) { - efuse_one_byte_write(adapter, addr, pkt.data[i * 2]); - efuse_one_byte_write(adapter, addr + 1, - pkt.data[i * 2 + 1]); - /* additional check */ - if (!efuse_one_byte_read(adapter, addr, &value)) { - ret = false; - } else if (pkt.data[i * 2] != value) { - ret = false; - if (value == 0xFF) /* write again */ - efuse_one_byte_write(adapter, addr, - pkt.data[i * 2]); - } - if (!efuse_one_byte_read(adapter, addr + 1, &value)) { - ret = false; - } else if (pkt.data[i * 2 + 1] != value) { - ret = false; - if (value == 0xFF) /* write again */ - efuse_one_byte_write(adapter, addr + 1, - pkt.data[i * 2 + - 1]); - } - } - addr += 2; - } - return ret; -} - -u8 r8712_efuse_pg_packet_write(struct _adapter *adapter, const u8 offset, - const u8 word_en, const u8 *data) -{ - u8 pg_header = 0; - u16 efuse_addr = 0, curr_size = 0; - u8 efuse_data, target_word_cnts = 0; - int repeat_times; - int sub_repeat; - u8 bResult = true; - - /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */ - efuse_data = r8712_read8(adapter, EFUSE_CLK_CTRL); - if (efuse_data != 0x03) - return false; - pg_header = MAKE_EFUSE_HEADER(offset, word_en); - target_word_cnts = calculate_word_cnts(word_en); - repeat_times = 0; - efuse_addr = 0; - while (efuse_addr < efuse_available_max_size) { - curr_size = r8712_efuse_get_current_size(adapter); - if ((curr_size + 1 + target_word_cnts * 2) > - efuse_available_max_size) - return false; /*target_word_cnts + pg header(1 byte)*/ - efuse_addr = curr_size; /* current size is also the last addr*/ - efuse_one_byte_write(adapter, efuse_addr, pg_header); /*hdr*/ - sub_repeat = 0; - /* check if what we read is what we write */ - while (!efuse_one_byte_read(adapter, efuse_addr, - &efuse_data)) { - if (++sub_repeat > _REPEAT_THRESHOLD_) { - bResult = false; /* continue to blind write */ - break; /* continue to blind write */ - } - } - if ((sub_repeat > _REPEAT_THRESHOLD_) || - (pg_header == efuse_data)) { - /* write header ok OR can't check header(creep) */ - u8 i; - - /* go to next address */ - efuse_addr++; - for (i = 0; i < target_word_cnts * 2; i++) { - efuse_one_byte_write(adapter, - efuse_addr + i, - *(data + i)); - if (!efuse_one_byte_read(adapter, - efuse_addr + i, - &efuse_data)) - bResult = false; - else if (*(data + i) != efuse_data) /* fail */ - bResult = false; - } - break; - } - /* write header fail */ - bResult = false; - if (efuse_data == 0xFF) - return bResult; /* nothing damaged. */ - /* call rescue procedure */ - if (!fix_header(adapter, efuse_data, efuse_addr)) - return false; /* rescue fail */ - - if (++repeat_times > _REPEAT_THRESHOLD_) /* fail */ - break; - /* otherwise, take another risk... */ - } - return bResult; -} - -u8 r8712_efuse_access(struct _adapter *adapter, u8 bRead, u16 start_addr, - u16 cnts, u8 *data) -{ - int i; - u8 res = true; - - if (start_addr > EFUSE_MAX_SIZE) - return false; - if (!bRead && ((start_addr + cnts) > - efuse_available_max_size)) - return false; - if (!bRead && !r8712_efuse_reg_init(adapter)) - return false; - /* -----------------e-fuse one byte read / write ---------------------*/ - for (i = 0; i < cnts; i++) { - if ((start_addr + i) > EFUSE_MAX_SIZE) { - res = false; - break; - } - res = efuse_one_byte_rw(adapter, bRead, start_addr + i, - data + i); - if (!bRead && !res) - break; - } - if (!bRead) - r8712_efuse_reg_uninit(adapter); - return res; -} - -u8 r8712_efuse_map_read(struct _adapter *adapter, u16 addr, u16 cnts, u8 *data) -{ - u8 offset, ret = true; - u8 pktdata[PGPKT_DATA_SIZE]; - int i, idx; - - if ((addr + cnts) > EFUSE_MAP_MAX_SIZE) - return false; - if (efuse_is_empty(adapter, &offset) && offset) { - for (i = 0; i < cnts; i++) - data[i] = 0xFF; - return ret; - } - offset = (addr >> 3) & 0xF; - ret = r8712_efuse_pg_packet_read(adapter, offset, pktdata); - i = addr & 0x7; /* pktdata index */ - idx = 0; /* data index */ - - do { - for (; i < PGPKT_DATA_SIZE; i++) { - data[idx++] = pktdata[i]; - if (idx == cnts) - return ret; - } - offset++; - if (!r8712_efuse_pg_packet_read(adapter, offset, pktdata)) - ret = false; - i = 0; - } while (1); - return ret; -} - -u8 r8712_efuse_map_write(struct _adapter *adapter, u16 addr, u16 cnts, - u8 *data) -{ - u8 offset, word_en, empty; - u8 pktdata[PGPKT_DATA_SIZE], newdata[PGPKT_DATA_SIZE]; - int i, j, idx; - - if ((addr + cnts) > EFUSE_MAP_MAX_SIZE) - return false; - /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */ - empty = r8712_read8(adapter, EFUSE_CLK_CTRL); - if (empty != 0x03) - return false; - if (efuse_is_empty(adapter, &empty)) { - if (empty) - memset(pktdata, 0xFF, PGPKT_DATA_SIZE); - } else { - return false; - } - offset = (addr >> 3) & 0xF; - if (!empty) - if (!r8712_efuse_pg_packet_read(adapter, offset, pktdata)) - return false; - word_en = 0xF; - memset(newdata, 0xFF, PGPKT_DATA_SIZE); - i = addr & 0x7; /* pktdata index */ - j = 0; /* newdata index */ - idx = 0; /* data index */ - - if (i & 0x1) { - /* odd start */ - if (data[idx] != pktdata[i]) { - word_en &= ~BIT(i >> 1); - newdata[j++] = pktdata[i - 1]; - newdata[j++] = data[idx]; - } - i++; - idx++; - } - do { - for (; i < PGPKT_DATA_SIZE; i += 2) { - if ((cnts - idx) == 1) { - if (data[idx] != pktdata[i]) { - word_en &= ~BIT(i >> 1); - newdata[j++] = data[idx]; - newdata[j++] = pktdata[1 + 1]; - } - idx++; - break; - } - - if ((data[idx] != pktdata[i]) || (data[idx + 1] != - pktdata[i + 1])) { - word_en &= ~BIT(i >> 1); - newdata[j++] = data[idx]; - newdata[j++] = data[idx + 1]; - } - idx += 2; - - if (idx == cnts) - break; - } - - if (word_en != 0xF) - if (!r8712_efuse_pg_packet_write(adapter, offset, - word_en, newdata)) - return false; - if (idx == cnts) - break; - offset++; - if (!empty) - if (!r8712_efuse_pg_packet_read(adapter, offset, - pktdata)) - return false; - i = 0; - j = 0; - word_en = 0xF; - memset(newdata, 0xFF, PGPKT_DATA_SIZE); - } while (1); - - return true; -} diff --git a/drivers/staging/rtl8712/rtl8712_efuse.h b/drivers/staging/rtl8712/rtl8712_efuse.h deleted file mode 100644 index 7a49740212eb5c1f78d1faa1ad78f7b407a0b4ed..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_efuse.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __RTL8712_EFUSE_H__ -#define __RTL8712_EFUSE_H__ - -#include "osdep_service.h" - -#define _REPEAT_THRESHOLD_ 3 - -#define EFUSE_MAX_SIZE 512 -#define EFUSE_MAP_MAX_SIZE 128 - -#define PGPKG_MAX_WORDS 4 -#define PGPKT_DATA_SIZE 8 /* PGPKG_MAX_WORDS*2; BYTES sizeof(u8)*8*/ -#define MAX_PGPKT_SIZE 9 /* 1 + PGPKT_DATA_SIZE; header + 2 * 4 words (BYTES)*/ - -#define GET_EFUSE_OFFSET(header) ((header & 0xF0) >> 4) -#define GET_EFUSE_WORD_EN(header) (header & 0x0F) -#define MAKE_EFUSE_HEADER(offset, word_en) ((((offset) & 0x0F) << 4) | \ - ((word_en) & 0x0F)) -/*--------------------------------------------------------------------------*/ -struct PGPKT_STRUCT { - u8 offset; - u8 word_en; - u8 data[PGPKT_DATA_SIZE]; -}; - -/*--------------------------------------------------------------------------*/ -u8 r8712_efuse_reg_init(struct _adapter *padapter); -void r8712_efuse_reg_uninit(struct _adapter *padapter); -u16 r8712_efuse_get_current_size(struct _adapter *padapter); -int r8712_efuse_get_max_size(struct _adapter *padapter); -void r8712_efuse_change_max_size(struct _adapter *padapter); -u8 r8712_efuse_pg_packet_read(struct _adapter *padapter, - u8 offset, u8 *data); -u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, - const u8 offset, const u8 word_en, - const u8 *data); -u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead, - u16 start_addr, u16 cnts, u8 *data); -u8 r8712_efuse_map_read(struct _adapter *padapter, u16 addr, - u16 cnts, u8 *data); -u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr, - u16 cnts, u8 *data); -#endif diff --git a/drivers/staging/rtl8712/rtl8712_event.h b/drivers/staging/rtl8712/rtl8712_event.h deleted file mode 100644 index 0d3e5feadcc01027d5b8106b200a4b976c5e49d5..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_event.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL8712_EVENT_H_ -#define _RTL8712_EVENT_H_ - -void r8712_event_handle(struct _adapter *padapter, __le32 *peventbuf); -void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf); - -enum rtl8712_c2h_event { - GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ - GEN_EVT_CODE(_Read_BBREG), - GEN_EVT_CODE(_Read_RFREG), - GEN_EVT_CODE(_Read_EEPROM), - GEN_EVT_CODE(_Read_EFUSE), - GEN_EVT_CODE(_Read_CAM), /*5*/ - GEN_EVT_CODE(_Get_BasicRate), - GEN_EVT_CODE(_Get_DataRate), - GEN_EVT_CODE(_Survey), /*8*/ - GEN_EVT_CODE(_SurveyDone), /*9*/ - - GEN_EVT_CODE(_JoinBss), /*10*/ - GEN_EVT_CODE(_AddSTA), - GEN_EVT_CODE(_DelSTA), - GEN_EVT_CODE(_AtimDone), - GEN_EVT_CODE(_TX_Report), - GEN_EVT_CODE(_CCX_Report), /*15*/ - GEN_EVT_CODE(_DTM_Report), - GEN_EVT_CODE(_TX_Rate_Statistics), - GEN_EVT_CODE(_C2HLBK), - GEN_EVT_CODE(_FWDBG), - GEN_EVT_CODE(_C2HFEEDBACK), /*20*/ - GEN_EVT_CODE(_ADDBA), - GEN_EVT_CODE(_C2HBCN), - GEN_EVT_CODE(_ReportPwrState), /*filen: only for PCIE, USB*/ - GEN_EVT_CODE(_WPS_PBC), /*24*/ - GEN_EVT_CODE(_ADDBAReq_Report), /*25*/ - MAX_C2HEVT -}; - -#ifdef _RTL8712_CMD_C_ - -static struct fwevent wlanevents[] = { - {0, NULL}, /*0*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, &r8712_survey_event_callback}, /*8*/ - {sizeof(struct surveydone_event), - &r8712_surveydone_event_callback}, /*9*/ - - {0, &r8712_joinbss_event_callback}, /*10*/ - {sizeof(struct stassoc_event), &r8712_stassoc_event_callback}, - {sizeof(struct stadel_event), &r8712_stadel_event_callback}, - {0, &r8712_atimdone_event_callback}, - {0, NULL}, - {0, NULL}, /*15*/ - {0, NULL}, - {0, NULL}, - {0, NULL}, - {0, NULL}, /*fwdbg_event_callback},*/ - {0, NULL}, /*20*/ - {0, NULL}, - {0, NULL}, - {0, &r8712_cpwm_event_callback}, - {0, &r8712_wpspbc_event_callback}, - {0, &r8712_got_addbareq_event_callback}, -}; - -#endif/*_RTL8712_CMD_C_*/ - -#endif diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h deleted file mode 100644 index f09645fa1886e44de061ab6b752bceb2ca38bc51..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_FIFOCTRL_BITDEF_H__ -#define __RTL8712_FIFOCTRL_BITDEF_H__ - -/*PBP*/ -#define _PSTX_MSK 0xF0 -#define _PSTX_SHT 4 -#define _PSRX_MSK 0x0F -#define _PSRX_SHT 0 - -/*TXFF_STATUS*/ -#define _TXSTATUS_OVF BIT(15) - -/*RXFF_STATUS*/ -#define _STATUSFF1_OVF BIT(7) -#define _STATUSFF1_EMPTY BIT(6) -#define _STATUSFF0_OVF BIT(5) -#define _STATUSFF0_EMPTY BIT(4) -#define _RXFF1_OVF BIT(3) -#define _RXFF1_EMPTY BIT(2) -#define _RXFF0_OVF BIT(1) -#define _RXFF0_EMPTY BIT(0) - -/*TXFF_EMPTY_TH*/ -#define _BKQ_EMPTY_TH_MSK 0x0F0000 -#define _BKQ_EMPTY_TH_SHT 16 -#define _BEQ_EMPTY_TH_MSK 0x00F000 -#define _BEQ_EMPTY_TH_SHT 12 -#define _VIQ_EMPTY_TH_MSK 0x000F00 -#define _VIQ_EMPTY_TH_SHT 8 -#define _VOQ_EMPTY_TH_MSK 0x0000F0 -#define _VOQ_EMPTY_TH_SHT 4 -#define _BMCQ_EMPTY_TH_MSK 0x00000F -#define _BMCQ_EMPTY_TH_SHT 0 - -/*SDIO_RX_BLKSZ*/ -#define _SDIO_RX_BLKSZ_MSK 0x07 - -/*RXDMA_CTRL*/ -#define _C2HFF_POLL BIT(4) -#define _RXPKT_POLL BIT(0) - -/*RXPKT_NUM*/ -#define _RXCMD_NUM_MSK 0xFF00 -#define _RXCMD_NUM_SHT 8 -#define _RXFF0_NUM_MSK 0x00FF -#define _RXFF0_NUM_SHT 0 - -/*FIFOPAGE2*/ -#define _PUB_AVAL_PG_MSK 0xFFFF0000 -#define _PUB_AVAL_PG_SHT 16 -#define _BCN_AVAL_PG_MSK 0x0000FFFF -#define _BCN_AVAL_PG_SHT 0 - -/*RX0PKTNUM*/ -#define _RXFF0_DEC_POLL BIT(15) -#define _RXFF0_PKT_DEC_NUM_MSK 0x3F00 -#define _RXFF0_PKT_DEC_NUM_SHT 8 -#define _RXFF0_PKTNUM_RPT_MSK 0x00FF -#define _RXFF0_PKTNUM_RPT_SHT 0 - -/*RX1PKTNUM*/ -#define _RXFF1_DEC_POLL BIT(15) -#define _RXFF1_PKT_DEC_NUM_MSK 0x3F00 -#define _RXFF1_PKT_DEC_NUM_SHT 8 -#define _RXFF1_PKTNUM_RPT_MSK 0x00FF -#define _RXFF1_PKTNUM_RPT_SHT 0 - -/*RXFLTMAP0*/ -#define _MGTFLT13EN BIT(13) -#define _MGTFLT12EN BIT(12) -#define _MGTFLT11EN BIT(11) -#define _MGTFLT10EN BIT(10) -#define _MGTFLT9EN BIT(9) -#define _MGTFLT8EN BIT(8) -#define _MGTFLT5EN BIT(5) -#define _MGTFLT4EN BIT(4) -#define _MGTFLT3EN BIT(3) -#define _MGTFLT2EN BIT(2) -#define _MGTFLT1EN BIT(1) -#define _MGTFLT0EN BIT(0) - -/*RXFLTMAP1*/ -#define _CTRLFLT15EN BIT(15) -#define _CTRLFLT14EN BIT(14) -#define _CTRLFLT13EN BIT(13) -#define _CTRLFLT12EN BIT(12) -#define _CTRLFLT11EN BIT(11) -#define _CTRLFLT10EN BIT(10) -#define _CTRLFLT9EN BIT(9) -#define _CTRLFLT8EN BIT(8) -#define _CTRLFLT7EN BIT(7) -#define _CTRLFLT6EN BIT(6) - -/*RXFLTMAP2*/ -#define _DATAFLT15EN BIT(15) -#define _DATAFLT14EN BIT(14) -#define _DATAFLT13EN BIT(13) -#define _DATAFLT12EN BIT(12) -#define _DATAFLT11EN BIT(11) -#define _DATAFLT10EN BIT(10) -#define _DATAFLT9EN BIT(9) -#define _DATAFLT8EN BIT(8) -#define _DATAFLT7EN BIT(7) -#define _DATAFLT6EN BIT(6) -#define _DATAFLT5EN BIT(5) -#define _DATAFLT4EN BIT(4) -#define _DATAFLT3EN BIT(3) -#define _DATAFLT2EN BIT(2) -#define _DATAFLT1EN BIT(1) -#define _DATAFLT0EN BIT(0) - -/*RXFLTMAP3*/ -#define _MESHAFLT1EN BIT(1) -#define _MESHAFLT0EN BIT(0) - -/*TXPKT_NUM_CTRL*/ -#define _TXPKTNUM_DEC BIT(8) -#define _TXPKTNUM_MSK 0x00FF -#define _TXPKTNUM_SHT 0 - -/*TXFF_PG_NUM*/ -#define _TXFF_PG_NUM_MSK 0x0FFF - -#endif /* __RTL8712_FIFOCTRL_BITDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h deleted file mode 100644 index 189fdeb16d7d31fb779f3ad4fd6499033b411b6f..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_FIFOCTRL_REGDEF_H__ -#define __RTL8712_FIFOCTRL_REGDEF_H__ - -#define RQPN (RTL8712_FIFOCTRL_ + 0x00) -#define RXFF_BNDY (RTL8712_FIFOCTRL_ + 0x0C) -#define RXRPT_BNDY (RTL8712_FIFOCTRL_ + 0x10) -#define TXPKTBUF_PGBNDY (RTL8712_FIFOCTRL_ + 0x14) -#define PBP (RTL8712_FIFOCTRL_ + 0x15) -#define RX_DRVINFO_SZ (RTL8712_FIFOCTRL_ + 0x16) -#define TXFF_STATUS (RTL8712_FIFOCTRL_ + 0x17) -#define RXFF_STATUS (RTL8712_FIFOCTRL_ + 0x18) -#define TXFF_EMPTY_TH (RTL8712_FIFOCTRL_ + 0x19) -#define SDIO_RX_BLKSZ (RTL8712_FIFOCTRL_ + 0x1C) -#define RXDMA_RXCTRL (RTL8712_FIFOCTRL_ + 0x1D) -#define RXPKT_NUM (RTL8712_FIFOCTRL_ + 0x1E) -#define RXPKT_NUM_C2H (RTL8712_FIFOCTRL_ + 0x1F) -#define C2HCMD_UDT_SIZE (RTL8712_FIFOCTRL_ + 0x20) -#define C2HCMD_UDT_ADDR (RTL8712_FIFOCTRL_ + 0x22) -#define FIFOPAGE2 (RTL8712_FIFOCTRL_ + 0x24) -#define FIFOPAGE1 (RTL8712_FIFOCTRL_ + 0x28) -#define FW_RSVD_PG_CTRL (RTL8712_FIFOCTRL_ + 0x30) -#define TXRPTFF_RDPTR (RTL8712_FIFOCTRL_ + 0x40) -#define TXRPTFF_WTPTR (RTL8712_FIFOCTRL_ + 0x44) -#define C2HFF_RDPTR (RTL8712_FIFOCTRL_ + 0x48) -#define C2HFF_WTPTR (RTL8712_FIFOCTRL_ + 0x4C) -#define RXFF0_RDPTR (RTL8712_FIFOCTRL_ + 0x50) -#define RXFF0_WTPTR (RTL8712_FIFOCTRL_ + 0x54) -#define RXFF1_RDPTR (RTL8712_FIFOCTRL_ + 0x58) -#define RXFF1_WTPTR (RTL8712_FIFOCTRL_ + 0x5C) -#define RXRPT0FF_RDPTR (RTL8712_FIFOCTRL_ + 0x60) -#define RXRPT0FF_WTPTR (RTL8712_FIFOCTRL_ + 0x64) -#define RXRPT1FF_RDPTR (RTL8712_FIFOCTRL_ + 0x68) -#define RXRPT1FF_WTPTR (RTL8712_FIFOCTRL_ + 0x6C) -#define RX0PKTNUM (RTL8712_FIFOCTRL_ + 0x72) -#define RX1PKTNUM (RTL8712_FIFOCTRL_ + 0x74) -#define RXFLTMAP0 (RTL8712_FIFOCTRL_ + 0x76) -#define RXFLTMAP1 (RTL8712_FIFOCTRL_ + 0x78) -#define RXFLTMAP2 (RTL8712_FIFOCTRL_ + 0x7A) -#define RXFLTMAP3 (RTL8712_FIFOCTRL_ + 0x7c) -#define TBDA (RTL8712_FIFOCTRL_ + 0x84) -#define THPDA (RTL8712_FIFOCTRL_ + 0x88) -#define TCDA (RTL8712_FIFOCTRL_ + 0x8C) -#define TMDA (RTL8712_FIFOCTRL_ + 0x90) -#define HDA (RTL8712_FIFOCTRL_ + 0x94) -#define TVODA (RTL8712_FIFOCTRL_ + 0x98) -#define TVIDA (RTL8712_FIFOCTRL_ + 0x9C) -#define TBEDA (RTL8712_FIFOCTRL_ + 0xA0) -#define TBKDA (RTL8712_FIFOCTRL_ + 0xA4) -#define RCDA (RTL8712_FIFOCTRL_ + 0xA8) -#define RDSA (RTL8712_FIFOCTRL_ + 0xAC) -#define TXPKT_NUM_CTRL (RTL8712_FIFOCTRL_ + 0xB0) -#define TXQ_PGADD (RTL8712_FIFOCTRL_ + 0xB3) -#define TXFF_PG_NUM (RTL8712_FIFOCTRL_ + 0xB4) - -#endif /* __RTL8712_FIFOCTRL_REGDEF_H__ */ diff --git a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h deleted file mode 100644 index ee651fb3fde3fce6114201fe024a68f75b981451..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_GP_BITDEF_H__ -#define __RTL8712_GP_BITDEF_H__ - -/*GPIO_CTRL*/ -#define _GPIO_MOD_MSK 0xFF000000 -#define _GPIO_MOD_SHT 24 -#define _GPIO_IO_SEL_MSK 0x00FF0000 -#define _GPIO_IO_SEL_SHT 16 -#define _GPIO_OUT_MSK 0x0000FF00 -#define _GPIO_OUT_SHT 8 -#define _GPIO_IN_MSK 0x000000FF -#define _GPIO_IN_SHT 0 - -/*SYS_PINMUX_CFG*/ -#define _GPIOSEL_MSK 0x0003 -#define _GPIOSEL_SHT 0 - -/*LED_CFG*/ -#define _LED1SV BIT(7) -#define _LED1CM_MSK 0x0070 -#define _LED1CM_SHT 4 -#define _LED0SV BIT(3) -#define _LED0CM_MSK 0x0007 -#define _LED0CM_SHT 0 - -/*PHY_REG*/ -#define _HST_RDRDY_SHT 0 -#define _HST_RDRDY_MSK 0xFF -#define _HST_RDRDY BIT(_HST_RDRDY_SHT) -#define _CPU_WTBUSY_SHT 1 -#define _CPU_WTBUSY_MSK 0xFF -#define _CPU_WTBUSY BIT(_CPU_WTBUSY_SHT) - -/* 11. General Purpose Registers (Offset: 0x02E0 - 0x02FF)*/ - -/* 8192S GPIO Config Setting (offset 0x2F1, 1 byte)*/ - -/*----------------------------------------------------------------------------*/ - -#define GPIOMUX_EN BIT(3) /* When this bit is set to "1", - * GPIO PINs will switch to MAC - * GPIO Function - */ -#define GPIOSEL_GPIO 0 /* UART or JTAG or pure GPIO*/ -#define GPIOSEL_PHYDBG 1 /* PHYDBG*/ -#define GPIOSEL_BT 2 /* BT_coex*/ -#define GPIOSEL_WLANDBG 3 /* WLANDBG*/ -#define GPIOSEL_GPIO_MASK (~(BIT(0) | BIT(1))) -/* HW Radio OFF switch (GPIO BIT) */ -#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3) -#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 -#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4) - -#endif /*__RTL8712_GP_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_gp_regdef.h b/drivers/staging/rtl8712/rtl8712_gp_regdef.h deleted file mode 100644 index 892a7fb1392355c9dd757011c05f708cfddb83ab..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_gp_regdef.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_GP_REGDEF_H__ -#define __RTL8712_GP_REGDEF_H__ - -#define PSTIMER (RTL8712_GP_ + 0x00) -#define TIMER1 (RTL8712_GP_ + 0x04) -#define TIMER2 (RTL8712_GP_ + 0x08) -#define GPIO_CTRL (RTL8712_GP_ + 0x0C) -#define GPIO_IO_SEL (RTL8712_GP_ + 0x0E) -#define GPIO_INTCTRL (RTL8712_GP_ + 0x10) -#define MAC_PINMUX_CTRL (RTL8712_GP_ + 0x11) -#define LEDCFG (RTL8712_GP_ + 0x12) -#define PHY_REG_RPT (RTL8712_GP_ + 0x13) -#define PHY_REG_DATA (RTL8712_GP_ + 0x14) - -#endif /*__RTL8712_GP_REGDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h deleted file mode 100644 index 66cc4645e2d1c9692477c5e0b46d063c2344363d..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_hal.h +++ /dev/null @@ -1,142 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_HAL_H__ -#define __RTL8712_HAL_H__ - -enum _HW_VERSION { - RTL8712_FPGA, - RTL8712_1stCUT, /*A Cut (RTL8712_ASIC)*/ - RTL8712_2ndCUT, /*B Cut*/ - RTL8712_3rdCUT, /*C Cut*/ -}; - -enum _LOOPBACK_TYPE { - RTL8712_AIR_TRX = 0, - RTL8712_MAC_LBK, - RTL8712_BB_LBK, - RTL8712_MAC_FW_LBK = 4, - RTL8712_BB_FW_LBK = 8, -}; - -enum RTL871X_HCI_TYPE { - RTL8712_SDIO, - RTL8712_USB, -}; - -enum RTL8712_RF_CONFIG { - RTL8712_RF_1T1R, - RTL8712_RF_1T2R, - RTL8712_RF_2T2R -}; - -enum _RTL8712_HCI_TYPE_ { - RTL8712_HCI_TYPE_PCIE = 0x01, - RTL8712_HCI_TYPE_AP_PCIE = 0x81, - RTL8712_HCI_TYPE_USB = 0x02, - RTL8712_HCI_TYPE_92USB = 0x02, - RTL8712_HCI_TYPE_AP_USB = 0x82, - RTL8712_HCI_TYPE_72USB = 0x12, - RTL8712_HCI_TYPE_SDIO = 0x04, - RTL8712_HCI_TYPE_72SDIO = 0x14 -}; - -struct fw_priv { /*8-bytes alignment required*/ - /*--- long word 0 ----*/ - unsigned char signature_0; /*0x12: CE product, 0x92: IT product*/ - unsigned char signature_1; /*0x87: CE product, 0x81: IT product*/ - unsigned char hci_sel; /*0x81: PCI-AP, 01:PCIe, 02: 92S-U, 0x82: USB-AP, - * 0x12: 72S-U, 03:SDIO - */ - unsigned char chip_version; /*the same value as register value*/ - unsigned char customer_ID_0; /*customer ID low byte*/ - unsigned char customer_ID_1; /*customer ID high byte*/ - unsigned char rf_config; /*0x11: 1T1R, 0x12: 1T2R, 0x92: 1T2R turbo, - * 0x22: 2T2R - */ - unsigned char usb_ep_num; /* 4: 4EP, 6: 6EP, 11: 11EP*/ - /*--- long word 1 ----*/ - unsigned char regulatory_class_0; /*regulatory class bit map 0*/ - unsigned char regulatory_class_1; /*regulatory class bit map 1*/ - unsigned char regulatory_class_2; /*regulatory class bit map 2*/ - unsigned char regulatory_class_3; /*regulatory class bit map 3*/ - unsigned char rfintfs; /* 0:SWSI, 1:HWSI, 2:HWPI*/ - unsigned char def_nettype; - unsigned char turbo_mode; - unsigned char low_power_mode;/* 0: normal mode, 1: low power mode*/ - /*--- long word 2 ----*/ - unsigned char lbk_mode; /*0x00: normal, 0x03: MACLBK, 0x01: PHYLBK*/ - unsigned char mp_mode; /* 1: for MP use, 0: for normal driver */ - unsigned char vcs_type; /* 0:off 1:on 2:auto */ - unsigned char vcs_mode; /* 1:RTS/CTS 2:CTS to self */ - unsigned char rsvd022; - unsigned char rsvd023; - unsigned char rsvd024; - unsigned char rsvd025; - /*--- long word 3 ----*/ - unsigned char qos_en; /*1: QoS enable*/ - unsigned char bw_40MHz_en; /*1: 40MHz BW enable*/ - unsigned char AMSDU2AMPDU_en; /*1: 4181 convert AMSDU to AMPDU, - * 0: disable - */ - unsigned char AMPDU_en; /*1: 11n AMPDU enable*/ - unsigned char rate_control_offload; /*1: FW offloads,0: driver handles*/ - unsigned char aggregation_offload; /*1: FW offloads,0: driver handles*/ - unsigned char rsvd030; - unsigned char rsvd031; - /*--- long word 4 ----*/ - unsigned char beacon_offload; /* 1. FW offloads, 0: driver handles*/ - unsigned char MLME_offload; /* 2. FW offloads, 0: driver handles*/ - unsigned char hwpc_offload; /* 3. FW offloads, 0: driver handles*/ - unsigned char tcp_checksum_offload; /*4. FW offloads,0: driver handles*/ - unsigned char tcp_offload; /* 5. FW offloads, 0: driver handles*/ - unsigned char ps_control_offload; /* 6. FW offloads, 0: driver handles*/ - unsigned char WWLAN_offload; /* 7. FW offloads, 0: driver handles*/ - unsigned char rsvd040; - /*--- long word 5 ----*/ - unsigned char tcp_tx_frame_len_L; /*tcp tx packet length low byte*/ - unsigned char tcp_tx_frame_len_H; /*tcp tx packet length high byte*/ - unsigned char tcp_rx_frame_len_L; /*tcp rx packet length low byte*/ - unsigned char tcp_rx_frame_len_H; /*tcp rx packet length high byte*/ - unsigned char rsvd050; - unsigned char rsvd051; - unsigned char rsvd052; - unsigned char rsvd053; -}; - -struct fw_hdr {/*8-byte alignment required*/ - unsigned short signature; - unsigned short version; /* 0x8000 ~ 0x8FFF for FPGA version, - * 0x0000 ~ 0x7FFF for ASIC version, - */ - unsigned int dmem_size; /*define the size of boot loader*/ - unsigned int img_IMEM_size; /*define the size of FW in IMEM*/ - unsigned int img_SRAM_size; /*define the size of FW in SRAM*/ - unsigned int fw_priv_sz; /*define the size of DMEM variable*/ - unsigned short efuse_addr; - unsigned short h2ccnd_resp_addr; - unsigned int SVNRevision; - unsigned int release_time; /*Mon:Day:Hr:Min*/ - struct fw_priv fwpriv; -}; - -struct hal_priv { - /*Endpoint handles*/ - struct net_device *pipehdls_r8712[10]; - u8 (*hal_bus_init)(struct _adapter *adapter); -}; - -uint rtl8712_hal_init(struct _adapter *padapter); -int rtl871x_load_fw(struct _adapter *padapter); - -#endif diff --git a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h b/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h deleted file mode 100644 index e9732a1bcd7ef8f058bf7dcd0424304abcfe3ead..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_INTERRUPT_BITDEF_H__ -#define __RTL8712_INTERRUPT_BITDEF_H__ - -/*HIMR*/ -/*HISR*/ -#define _CPUERR BIT(29) -#define _ATIMEND BIT(28) -#define _TXBCNOK BIT(27) -#define _TXBCNERR BIT(26) -#define _BCNDMAINT4 BIT(25) -#define _BCNDMAINT3 BIT(24) -#define _BCNDMAINT2 BIT(23) -#define _BCNDMAINT1 BIT(22) -#define _BCNDOK4 BIT(21) -#define _BCNDOK3 BIT(20) -#define _BCNDOK2 BIT(19) -#define _BCNDOK1 BIT(18) -#define _TIMEOUT2 BIT(17) -#define _TIMEOUT1 BIT(16) -#define _TXFOVW BIT(15) -#define _PSTIMEOUT BIT(14) -#define _BCNDMAINT0 BIT(13) -#define _FOVW BIT(12) -#define _RDU BIT(11) -#define _RXCMDOK BIT(10) -#define _BCNDOK0 BIT(9) -#define _HIGHDOK BIT(8) -#define _COMDOK BIT(7) -#define _MGTDOK BIT(6) -#define _HCCADOK BIT(5) -#define _BKDOK BIT(4) -#define _BEDOK BIT(3) -#define _VIDOK BIT(2) -#define _VODOK BIT(1) -#define _RXOK BIT(0) - -#endif /*__RTL8712_INTERRUPT_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_io.c b/drivers/staging/rtl8712/rtl8712_io.c deleted file mode 100644 index 384cbdb05e1963015656cc83a1ffb6a1ae3927a7..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_io.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl8712_io.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com>. - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL8712_IO_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "rtl871x_io.h" -#include "osdep_intf.h" -#include "usb_ops.h" - -u8 r8712_read8(struct _adapter *adapter, u32 addr) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - return hdl->io_ops._read8(hdl, addr); -} - -u16 r8712_read16(struct _adapter *adapter, u32 addr) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - return hdl->io_ops._read16(hdl, addr); -} - -u32 r8712_read32(struct _adapter *adapter, u32 addr) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - return hdl->io_ops._read32(hdl, addr); -} - -void r8712_write8(struct _adapter *adapter, u32 addr, u8 val) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - hdl->io_ops._write8(hdl, addr, val); -} - -void r8712_write16(struct _adapter *adapter, u32 addr, u16 val) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - hdl->io_ops._write16(hdl, addr, val); -} - -void r8712_write32(struct _adapter *adapter, u32 addr, u32 val) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - hdl->io_ops._write32(hdl, addr, val); -} - -void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - if (adapter->driver_stopped || adapter->surprise_removed) - return; - - hdl->io_ops._read_mem(hdl, addr, cnt, pmem); -} - -void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - hdl->io_ops._write_mem(hdl, addr, cnt, pmem); -} - -void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - if (adapter->driver_stopped || adapter->surprise_removed) - return; - - hdl->io_ops._read_port(hdl, addr, cnt, pmem); -} - -void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem) -{ - struct intf_hdl *hdl = &adapter->pio_queue->intf; - - hdl->io_ops._write_port(hdl, addr, cnt, pmem); -} diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c deleted file mode 100644 index 6d9be5dec4e72898aaa2e6ebfbfd68dd9135ae22..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_led.c +++ /dev/null @@ -1,1830 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl8712_led.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#include "drv_types.h" - -/*=========================================================================== - * Constant. - *=========================================================================== - - * - * Default LED behavior. - */ -#define LED_BLINK_NORMAL_INTERVAL 100 -#define LED_BLINK_SLOWLY_INTERVAL 200 -#define LED_BLINK_LONG_INTERVAL 400 - -#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000 -#define LED_BLINK_LINK_INTERVAL_ALPHA 500 -#define LED_BLINK_SCAN_INTERVAL_ALPHA 180 -#define LED_BLINK_FASTER_INTERVAL_ALPHA 50 -#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000 - -/*=========================================================================== - * LED object. - *=========================================================================== - */ -enum _LED_STATE_871x { - LED_UNKNOWN = 0, - LED_STATE_ON = 1, - LED_STATE_OFF = 2, - LED_BLINK_NORMAL = 3, - LED_BLINK_SLOWLY = 4, - LED_POWER_ON_BLINK = 5, - LED_SCAN_BLINK = 6, /* LED is blinking during scanning period, - * the # of times to blink is depend on time - * for scanning. - */ - LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */ - LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer - * Server case - */ - LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */ - LED_TXRX_BLINK = 10, - LED_BLINK_WPS_STOP = 11, /*for ALPHA */ - LED_BLINK_WPS_STOP_OVERLAP = 12, /*for BELKIN */ -}; - -/*=========================================================================== - * Prototype of protected function. - *=========================================================================== - */ -static void BlinkTimerCallback(struct timer_list *t); - -static void BlinkWorkItemCallback(struct work_struct *work); -/*=========================================================================== - * LED_819xUsb routines. - *=========================================================================== - * - * - * - * Description: - * Initialize an LED_871x object. - */ -static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed, - enum LED_PIN_871x LedPin) -{ - pLed->padapter = padapter; - pLed->LedPin = LedPin; - pLed->CurrLedState = LED_STATE_OFF; - pLed->bLedOn = false; - pLed->bLedBlinkInProgress = false; - pLed->BlinkTimes = 0; - pLed->BlinkingLedState = LED_UNKNOWN; - timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0); - INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback); -} - -/* - * Description: - * DeInitialize an LED_871x object. - */ -static void DeInitLed871x(struct LED_871x *pLed) -{ - del_timer_sync(&pLed->BlinkTimer); - /* We should reset bLedBlinkInProgress if we cancel - * the LedControlTimer, - */ - pLed->bLedBlinkInProgress = false; -} - -/* - * Description: - * Turn on LED according to LedPin specified. - */ -static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed) -{ - u8 LedCfg; - - if (padapter->surprise_removed || padapter->driver_stopped) - return; - LedCfg = r8712_read8(padapter, LEDCFG); - switch (pLed->LedPin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - /* SW control led0 on.*/ - r8712_write8(padapter, LEDCFG, LedCfg & 0xf0); - break; - case LED_PIN_LED1: - /* SW control led1 on.*/ - r8712_write8(padapter, LEDCFG, LedCfg & 0x0f); - break; - default: - break; - } - pLed->bLedOn = true; -} - -/* - * Description: - * Turn off LED according to LedPin specified. - */ -static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed) -{ - u8 LedCfg; - - if (padapter->surprise_removed || padapter->driver_stopped) - return; - LedCfg = r8712_read8(padapter, LEDCFG); - switch (pLed->LedPin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - LedCfg &= 0xf0; /* Set to software control.*/ - r8712_write8(padapter, LEDCFG, (LedCfg | BIT(3))); - break; - case LED_PIN_LED1: - LedCfg &= 0x0f; /* Set to software control.*/ - r8712_write8(padapter, LEDCFG, (LedCfg | BIT(7))); - break; - default: - break; - } - pLed->bLedOn = false; -} - -/*=========================================================================== - * Interface to manipulate LED objects. - *=========================================================================== - * - * Description: - * Initialize all LED_871x objects. - */ -void r8712_InitSwLeds(struct _adapter *padapter) -{ - struct led_priv *pledpriv = &padapter->ledpriv; - - pledpriv->LedControlHandler = LedControl871x; - InitLed871x(padapter, &pledpriv->SwLed0, LED_PIN_LED0); - InitLed871x(padapter, &pledpriv->SwLed1, LED_PIN_LED1); -} - -/* Description: - * DeInitialize all LED_819xUsb objects. - */ -void r8712_DeInitSwLeds(struct _adapter *padapter) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - - DeInitLed871x(&ledpriv->SwLed0); - DeInitLed871x(&ledpriv->SwLed1); -} - -/* Description: - * Implementation of LED blinking behavior. - * It toggle off LED and schedule corresponding timer if necessary. - */ -static void SwLedBlink(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 bStopBlinking = false; - - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - SwLedOff(padapter, pLed); - /* Determine if we shall change LED state again. */ - pLed->BlinkTimes--; - switch (pLed->CurrLedState) { - case LED_BLINK_NORMAL: - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - break; - case LED_BLINK_StartToBlink: - if (check_fwstate(pmlmepriv, _FW_LINKED) && - (pmlmepriv->fw_state & WIFI_STATION_STATE)) - bStopBlinking = true; - if (check_fwstate(pmlmepriv, _FW_LINKED) && - ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) || - (pmlmepriv->fw_state & WIFI_ADHOC_MASTER_STATE))) - bStopBlinking = true; - else if (pLed->BlinkTimes == 0) - bStopBlinking = true; - break; - case LED_BLINK_WPS: - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - break; - default: - bStopBlinking = true; - break; - } - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED) && - !pLed->bLedOn) - SwLedOn(padapter, pLed); - else if (check_fwstate(pmlmepriv, _FW_LINKED) && pLed->bLedOn) - SwLedOff(padapter, pLed); - pLed->BlinkTimes = 0; - pLed->bLedBlinkInProgress = false; - } else { - /* Assign LED state to toggle. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - - /* Schedule a timer to toggle LED state. */ - switch (pLed->CurrLedState) { - case LED_BLINK_NORMAL: - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - break; - case LED_BLINK_SLOWLY: - case LED_BLINK_StartToBlink: - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); - break; - case LED_BLINK_WPS: - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LONG_INTERVAL)); - break; - default: - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); - break; - } - } -} - -static void SwLedBlink1(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - struct led_priv *ledpriv = &padapter->ledpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct eeprom_priv *peeprompriv = &padapter->eeprompriv; - struct LED_871x *pLed1 = &ledpriv->SwLed1; - u8 bStopBlinking = false; - - if (peeprompriv->CustomerID == RT_CID_819x_CAMEO) - pLed = &ledpriv->SwLed1; - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - SwLedOff(padapter, pLed); - if (peeprompriv->CustomerID == RT_CID_DEFAULT) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (!pLed1->bSWLedCtrl) { - SwLedOn(padapter, pLed1); - pLed1->bSWLedCtrl = true; - } else if (!pLed1->bLedOn) { - SwLedOn(padapter, pLed1); - } - } else { - if (!pLed1->bSWLedCtrl) { - SwLedOff(padapter, pLed1); - pLed1->bSWLedCtrl = true; - } else if (pLed1->bLedOn) { - SwLedOff(padapter, pLed1); - } - } - } - switch (pLed->CurrLedState) { - case LED_BLINK_SLOWLY: - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - break; - case LED_BLINK_NORMAL: - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - break; - case LED_SCAN_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->bLedLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - } - pLed->bLedScanBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_TXRX_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->bLedLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - } - pLed->BlinkTimes = 0; - pLed->bLedBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_BLINK_WPS: - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - break; - case LED_BLINK_WPS_STOP: /* WPS success */ - if (pLed->BlinkingLedState == LED_STATE_ON) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); - bStopBlinking = false; - } else { - bStopBlinking = true; - } - if (bStopBlinking) { - pLed->bLedLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - } - pLed->bLedWPSBlinkInProgress = false; - break; - default: - break; - } -} - -static void SwLedBlink2(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 bStopBlinking = false; - - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - SwLedOff(padapter, pLed); - switch (pLed->CurrLedState) { - case LED_SCAN_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - SwLedOn(padapter, pLed); - } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - SwLedOff(padapter, pLed); - } - pLed->bLedScanBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_TXRX_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - SwLedOn(padapter, pLed); - } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - SwLedOff(padapter, pLed); - } - pLed->bLedBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - default: - break; - } -} - -static void SwLedBlink3(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 bStopBlinking = false; - - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - if (pLed->CurrLedState != LED_BLINK_WPS_STOP) - SwLedOff(padapter, pLed); - switch (pLed->CurrLedState) { - case LED_SCAN_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (!pLed->bLedOn) - SwLedOn(padapter, pLed); - } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedOn) - SwLedOff(padapter, pLed); - } - pLed->bLedScanBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_TXRX_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (!pLed->bLedOn) - SwLedOn(padapter, pLed); - } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedOn) - SwLedOff(padapter, pLed); - } - pLed->bLedBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_BLINK_WPS: - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - break; - case LED_BLINK_WPS_STOP: /*WPS success*/ - if (pLed->BlinkingLedState == LED_STATE_ON) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); - bStopBlinking = false; - } else { - bStopBlinking = true; - } - if (bStopBlinking) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - SwLedOn(padapter, pLed); - pLed->bLedWPSBlinkInProgress = false; - } - break; - default: - break; - } -} - -static void SwLedBlink4(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - struct led_priv *ledpriv = &padapter->ledpriv; - struct LED_871x *pLed1 = &ledpriv->SwLed1; - u8 bStopBlinking = false; - - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - SwLedOff(padapter, pLed); - if (!pLed1->bLedWPSBlinkInProgress && - pLed1->BlinkingLedState == LED_UNKNOWN) { - pLed1->BlinkingLedState = LED_STATE_OFF; - pLed1->CurrLedState = LED_STATE_OFF; - SwLedOff(padapter, pLed1); - } - switch (pLed->CurrLedState) { - case LED_BLINK_SLOWLY: - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - break; - case LED_BLINK_StartToBlink: - if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); - } else { - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - } - break; - case LED_SCAN_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - pLed->bLedScanBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_TXRX_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - pLed->bLedBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_BLINK_WPS: - if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); - } else { - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - } - break; - case LED_BLINK_WPS_STOP: /*WPS authentication fail*/ - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - break; - case LED_BLINK_WPS_STOP_OVERLAP: /*WPS session overlap */ - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) { - if (pLed->bLedOn) - pLed->BlinkTimes = 1; - else - bStopBlinking = true; - } - if (bStopBlinking) { - pLed->BlinkTimes = 10; - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - } - break; - default: - break; - } -} - -static void SwLedBlink5(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - u8 bStopBlinking = false; - - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - SwLedOff(padapter, pLed); - switch (pLed->CurrLedState) { - case LED_SCAN_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (!pLed->bLedOn) - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - pLed->bLedScanBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_TXRX_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (!pLed->bLedOn) - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - pLed->bLedBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - default: - break; - } -} - -static void SwLedBlink6(struct LED_871x *pLed) -{ - struct _adapter *padapter = pLed->padapter; - u8 bStopBlinking = false; - - /* Change LED according to BlinkingLedState specified. */ - if (pLed->BlinkingLedState == LED_STATE_ON) - SwLedOn(padapter, pLed); - else - SwLedOff(padapter, pLed); - switch (pLed->CurrLedState) { - case LED_TXRX_BLINK: - pLed->BlinkTimes--; - if (pLed->BlinkTimes == 0) - bStopBlinking = true; - if (bStopBlinking) { - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (!pLed->bLedOn) - SwLedOn(padapter, pLed); - pLed->bLedBlinkInProgress = false; - } else { - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_BLINK_WPS: - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - break; - - default: - break; - } -} - -/* Description: - * Callback function of LED BlinkTimer, - * it just schedules to corresponding BlinkWorkItem. - */ -static void BlinkTimerCallback(struct timer_list *t) -{ - struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer); - - /* This fixed the crash problem on Fedora 12 when trying to do the - * insmod;ifconfig up;rmmod commands. - */ - if (pLed->padapter->surprise_removed || pLed->padapter->driver_stopped) - return; - schedule_work(&pLed->BlinkWorkItem); -} - -/* Description: - * Callback function of LED BlinkWorkItem. - * We dispatch actual LED blink action according to LedStrategy. - */ -static void BlinkWorkItemCallback(struct work_struct *work) -{ - struct LED_871x *pLed = container_of(work, struct LED_871x, - BlinkWorkItem); - struct led_priv *ledpriv = &pLed->padapter->ledpriv; - - switch (ledpriv->LedStrategy) { - case SW_LED_MODE0: - SwLedBlink(pLed); - break; - case SW_LED_MODE1: - SwLedBlink1(pLed); - break; - case SW_LED_MODE2: - SwLedBlink2(pLed); - break; - case SW_LED_MODE3: - SwLedBlink3(pLed); - break; - case SW_LED_MODE4: - SwLedBlink4(pLed); - break; - case SW_LED_MODE5: - SwLedBlink5(pLed); - break; - case SW_LED_MODE6: - SwLedBlink6(pLed); - break; - default: - SwLedBlink(pLed); - break; - } -} - -/*============================================================================ - * Default LED behavior. - *============================================================================ - * - * Description: - * Implement each led action for SW_LED_MODE0. - * This is default strategy. - */ - -static void SwLedControlMode1(struct _adapter *padapter, - enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - struct LED_871x *pLed = &ledpriv->SwLed0; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl; - - if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO) - pLed = &ledpriv->SwLed1; - switch (LedAction) { - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if (!pLed->bLedNoLinkBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - } - break; - case LED_CTL_LINK: - if (!pLed->bLedLinkBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_NORMAL; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA)); - } - break; - case LED_CTL_SITE_SURVEY: - if (psitesurveyctrl->traffic_busy && - check_fwstate(pmlmepriv, _FW_LINKED)) - ; /* dummy branch */ - else if (!pLed->bLedScanBlinkInProgress) { - if (IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedScanBlinkInProgress = true; - pLed->CurrLedState = LED_SCAN_BLINK; - pLed->BlinkTimes = 24; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_TX: - case LED_CTL_RX: - if (!pLed->bLedBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - pLed->bLedBlinkInProgress = true; - pLed->CurrLedState = LED_TXRX_BLINK; - pLed->BlinkTimes = 2; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - - case LED_CTL_START_WPS: /*wait until xinpin finish */ - case LED_CTL_START_WPS_BOTTON: - if (!pLed->bLedWPSBlinkInProgress) { - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_WPS; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_STOP_WPS: - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - if (pLed->bLedWPSBlinkInProgress) - del_timer(&pLed->BlinkTimer); - else - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_WPS_STOP; - if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); - } else { - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - break; - case LED_CTL_STOP_WPS_FAIL: - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - default: - break; - } -} - -static void SwLedControlMode2(struct _adapter *padapter, - enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct LED_871x *pLed = &ledpriv->SwLed0; - - switch (LedAction) { - case LED_CTL_SITE_SURVEY: - if (pmlmepriv->sitesurveyctrl.traffic_busy) - ; /* dummy branch */ - else if (!pLed->bLedScanBlinkInProgress) { - if (IS_LED_WPS_BLINKING(pLed)) - return; - - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedScanBlinkInProgress = true; - pLed->CurrLedState = LED_SCAN_BLINK; - pLed->BlinkTimes = 24; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - - case LED_CTL_TX: - case LED_CTL_RX: - if (!pLed->bLedBlinkInProgress && - check_fwstate(pmlmepriv, _FW_LINKED)) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - pLed->bLedBlinkInProgress = true; - pLed->CurrLedState = LED_TXRX_BLINK; - pLed->BlinkTimes = 2; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - - case LED_CTL_LINK: - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - - case LED_CTL_START_WPS: /*wait until xinpin finish*/ - case LED_CTL_START_WPS_BOTTON: - if (!pLed->bLedWPSBlinkInProgress) { - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - break; - - case LED_CTL_STOP_WPS: - pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - - case LED_CTL_STOP_WPS_FAIL: - pLed->bLedWPSBlinkInProgress = false; - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if (!IS_LED_BLINKING(pLed)) { - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - default: - break; - } -} - -static void SwLedControlMode3(struct _adapter *padapter, - enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct LED_871x *pLed = &ledpriv->SwLed0; - - switch (LedAction) { - case LED_CTL_SITE_SURVEY: - if (pmlmepriv->sitesurveyctrl.traffic_busy) - ; /* dummy branch */ - else if (!pLed->bLedScanBlinkInProgress) { - if (IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedScanBlinkInProgress = true; - pLed->CurrLedState = LED_SCAN_BLINK; - pLed->BlinkTimes = 24; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_TX: - case LED_CTL_RX: - if (!pLed->bLedBlinkInProgress && - check_fwstate(pmlmepriv, _FW_LINKED)) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - pLed->bLedBlinkInProgress = true; - pLed->CurrLedState = LED_TXRX_BLINK; - pLed->BlinkTimes = 2; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_CTL_LINK: - if (IS_LED_WPS_BLINKING(pLed)) - return; - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - case LED_CTL_START_WPS: /* wait until xinpin finish */ - case LED_CTL_START_WPS_BOTTON: - if (!pLed->bLedWPSBlinkInProgress) { - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_WPS; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_STOP_WPS: - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } else { - pLed->bLedWPSBlinkInProgress = true; - } - pLed->CurrLedState = LED_BLINK_WPS_STOP; - if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA)); - } else { - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - break; - case LED_CTL_STOP_WPS_FAIL: - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if (!IS_LED_BLINKING(pLed)) { - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - default: - break; - } -} - -static void SwLedControlMode4(struct _adapter *padapter, - enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct LED_871x *pLed = &ledpriv->SwLed0; - struct LED_871x *pLed1 = &ledpriv->SwLed1; - - switch (LedAction) { - case LED_CTL_START_TO_LINK: - if (pLed1->bLedWPSBlinkInProgress) { - pLed1->bLedWPSBlinkInProgress = false; - del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_STATE_OFF; - pLed1->CurrLedState = LED_STATE_OFF; - if (pLed1->bLedOn) - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - if (!pLed->bLedStartToLinkBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - pLed->bLedStartToLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_StartToBlink; - if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); - } else { - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - } - } - break; - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - /*LED1 settings*/ - if (LedAction == LED_CTL_LINK) { - if (pLed1->bLedWPSBlinkInProgress) { - pLed1->bLedWPSBlinkInProgress = false; - del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_STATE_OFF; - pLed1->CurrLedState = LED_STATE_OFF; - if (pLed1->bLedOn) - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - } - if (!pLed->bLedNoLinkBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - } - break; - case LED_CTL_SITE_SURVEY: - if (pmlmepriv->sitesurveyctrl.traffic_busy && - check_fwstate(pmlmepriv, _FW_LINKED)) - ; - else if (!pLed->bLedScanBlinkInProgress) { - if (IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedScanBlinkInProgress = true; - pLed->CurrLedState = LED_SCAN_BLINK; - pLed->BlinkTimes = 24; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_TX: - case LED_CTL_RX: - if (!pLed->bLedBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK || - IS_LED_WPS_BLINKING(pLed)) - return; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - pLed->bLedBlinkInProgress = true; - pLed->CurrLedState = LED_TXRX_BLINK; - pLed->BlinkTimes = 2; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_CTL_START_WPS: /*wait until xinpin finish*/ - case LED_CTL_START_WPS_BOTTON: - if (pLed1->bLedWPSBlinkInProgress) { - pLed1->bLedWPSBlinkInProgress = false; - del_timer(&pLed1->BlinkTimer); - pLed1->BlinkingLedState = LED_STATE_OFF; - pLed1->CurrLedState = LED_STATE_OFF; - if (pLed1->bLedOn) - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - } - if (!pLed->bLedWPSBlinkInProgress) { - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_WPS; - if (pLed->bLedOn) { - pLed->BlinkingLedState = LED_STATE_OFF; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL)); - } else { - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - } - } - break; - case LED_CTL_STOP_WPS: /*WPS connect success*/ - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - break; - case LED_CTL_STOP_WPS_FAIL: /*WPS authentication fail*/ - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - /*LED1 settings*/ - if (pLed1->bLedWPSBlinkInProgress) - del_timer(&pLed1->BlinkTimer); - else - pLed1->bLedWPSBlinkInProgress = true; - pLed1->CurrLedState = LED_BLINK_WPS_STOP; - if (pLed1->bLedOn) - pLed1->BlinkingLedState = LED_STATE_OFF; - else - pLed1->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - break; - case LED_CTL_STOP_WPS_FAIL_OVERLAP: /*WPS session overlap*/ - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - pLed->bLedNoLinkBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA)); - /*LED1 settings*/ - if (pLed1->bLedWPSBlinkInProgress) - del_timer(&pLed1->BlinkTimer); - else - pLed1->bLedWPSBlinkInProgress = true; - pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; - pLed1->BlinkTimes = 10; - if (pLed1->bLedOn) - pLed1->BlinkingLedState = LED_STATE_OFF; - else - pLed1->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL)); - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedNoLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedNoLinkBlinkInProgress = false; - } - if (pLed->bLedLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; - } - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - if (pLed->bLedScanBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedScanBlinkInProgress = false; - } - if (pLed->bLedStartToLinkBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedStartToLinkBlinkInProgress = false; - } - if (pLed1->bLedWPSBlinkInProgress) { - del_timer(&pLed1->BlinkTimer); - pLed1->bLedWPSBlinkInProgress = false; - } - pLed1->BlinkingLedState = LED_UNKNOWN; - SwLedOff(padapter, pLed); - SwLedOff(padapter, pLed1); - break; - default: - break; - } -} - -static void SwLedControlMode5(struct _adapter *padapter, - enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct LED_871x *pLed = &ledpriv->SwLed0; - - if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO) - pLed = &ledpriv->SwLed1; - - switch (LedAction) { - case LED_CTL_POWER_ON: - case LED_CTL_NO_LINK: - case LED_CTL_LINK: /* solid blue */ - if (pLed->CurrLedState == LED_SCAN_BLINK) - return; - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - pLed->bLedBlinkInProgress = false; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - case LED_CTL_SITE_SURVEY: - if (pmlmepriv->sitesurveyctrl.traffic_busy && - check_fwstate(pmlmepriv, _FW_LINKED)) - ; /* dummy branch */ - else if (!pLed->bLedScanBlinkInProgress) { - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedScanBlinkInProgress = true; - pLed->CurrLedState = LED_SCAN_BLINK; - pLed->BlinkTimes = 24; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_TX: - case LED_CTL_RX: - if (!pLed->bLedBlinkInProgress) { - if (pLed->CurrLedState == LED_SCAN_BLINK) - return; - pLed->bLedBlinkInProgress = true; - pLed->CurrLedState = LED_TXRX_BLINK; - pLed->BlinkTimes = 2; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - SwLedOff(padapter, pLed); - break; - default: - break; - } -} - -static void SwLedControlMode6(struct _adapter *padapter, - enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct LED_871x *pLed = &ledpriv->SwLed0; - - switch (LedAction) { - case LED_CTL_POWER_ON: - case LED_CTL_NO_LINK: - case LED_CTL_LINK: /*solid blue*/ - case LED_CTL_SITE_SURVEY: - if (IS_LED_WPS_BLINKING(pLed)) - return; - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - pLed->bLedBlinkInProgress = false; - mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0)); - break; - case LED_CTL_TX: - case LED_CTL_RX: - if (!pLed->bLedBlinkInProgress && - check_fwstate(pmlmepriv, _FW_LINKED)) { - if (IS_LED_WPS_BLINKING(pLed)) - return; - pLed->bLedBlinkInProgress = true; - pLed->CurrLedState = LED_TXRX_BLINK; - pLed->BlinkTimes = 2; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA)); - } - break; - case LED_CTL_START_WPS: /*wait until xinpin finish*/ - case LED_CTL_START_WPS_BOTTON: - if (!pLed->bLedWPSBlinkInProgress) { - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - pLed->bLedWPSBlinkInProgress = true; - pLed->CurrLedState = LED_BLINK_WPS; - if (pLed->bLedOn) - pLed->BlinkingLedState = LED_STATE_OFF; - else - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, jiffies + - msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA)); - } - break; - case LED_CTL_STOP_WPS_FAIL: - case LED_CTL_STOP_WPS: - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - pLed->CurrLedState = LED_STATE_ON; - pLed->BlinkingLedState = LED_STATE_ON; - mod_timer(&pLed->BlinkTimer, - jiffies + msecs_to_jiffies(0)); - break; - case LED_CTL_POWER_OFF: - pLed->CurrLedState = LED_STATE_OFF; - pLed->BlinkingLedState = LED_STATE_OFF; - if (pLed->bLedBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedBlinkInProgress = false; - } - if (pLed->bLedWPSBlinkInProgress) { - del_timer(&pLed->BlinkTimer); - pLed->bLedWPSBlinkInProgress = false; - } - SwLedOff(padapter, pLed); - break; - default: - break; - } -} - -/* Description: - * Dispatch LED action according to pHalData->LedStrategy. - */ -void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction) -{ - struct led_priv *ledpriv = &padapter->ledpriv; - - if (!ledpriv->bRegUseLed) - return; - switch (ledpriv->LedStrategy) { - case SW_LED_MODE0: - break; - case SW_LED_MODE1: - SwLedControlMode1(padapter, LedAction); - break; - case SW_LED_MODE2: - SwLedControlMode2(padapter, LedAction); - break; - case SW_LED_MODE3: - SwLedControlMode3(padapter, LedAction); - break; - case SW_LED_MODE4: - SwLedControlMode4(padapter, LedAction); - break; - case SW_LED_MODE5: - SwLedControlMode5(padapter, LedAction); - break; - case SW_LED_MODE6: - SwLedControlMode6(padapter, LedAction); - break; - default: - break; - } -} - -void r8712_flush_led_works(struct _adapter *padapter) -{ - struct led_priv *pledpriv = &padapter->ledpriv; - - flush_work(&pledpriv->SwLed0.BlinkWorkItem); - flush_work(&pledpriv->SwLed1.BlinkWorkItem); -} diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h deleted file mode 100644 index 46d758d3f3a4dd286501eabee589154144cf7727..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_MACSETTING_BITDEF_H__ -#define __RTL8712_MACSETTING_BITDEF_H__ - -/*MACID*/ -/*BSSID*/ - -/*HWVID*/ -#define _HWVID_MSK 0x0F - -/*MAR*/ -/*MBIDCANCONTENT*/ - -/*MBIDCANCFG*/ -#define _POOLING BIT(31) -#define _WRITE_EN BIT(16) -#define _CAM_ADDR_MSK 0x001F -#define _CAM_ADDR_SHT 0 - -/*BUILDTIME*/ -#define _BUILDTIME_MSK 0x3FFFFFFF - -/*BUILDUSER*/ - -#endif /* __RTL8712_MACSETTING_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h deleted file mode 100644 index 64740d99c252334d42d6e53a4d38b206471defb2..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_MACSETTING_REGDEF_H__ -#define __RTL8712_MACSETTING_REGDEF_H__ - -#define MACID (RTL8712_MACIDSETTING_ + 0x0000) -#define BSSIDR (RTL8712_MACIDSETTING_ + 0x0008) -#define HWVID (RTL8712_MACIDSETTING_ + 0x000E) -#define MAR (RTL8712_MACIDSETTING_ + 0x0010) -#define MBIDCANCONTENT (RTL8712_MACIDSETTING_ + 0x0018) -#define MBIDCANCFG (RTL8712_MACIDSETTING_ + 0x0020) -#define BUILDTIME (RTL8712_MACIDSETTING_ + 0x0024) -#define BUILDUSER (RTL8712_MACIDSETTING_ + 0x0028) - -#endif /*__RTL8712_MACSETTING_REGDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h b/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h deleted file mode 100644 index 53e0d6b440f34ee5bc3a4893e4df9d70a2f2f967..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_POWERSAVE_BITDEF_H__ -#define __RTL8712_POWERSAVE_BITDEF_H__ - -/*WOWCTRL*/ -#define _UWF BIT(3) -#define _MAGIC BIT(2) -#define _WOW_EN BIT(1) -#define _PMEN BIT(0) - -/*PSSTATUS*/ -#define _PSSTATUS_SEL_MSK 0x0F - -/*PSSWITCH*/ -#define _PSSWITCH_ACT BIT(7) -#define _PSSWITCH_SEL_MSK 0x0F -#define _PSSWITCH_SEL_SHT 0 - -/*LPNAV_CTRL*/ -#define _LPNAV_EN BIT(31) -#define _LPNAV_EARLY_MSK 0x7FFF0000 -#define _LPNAV_EARLY_SHT 16 -#define _LPNAV_TH_MSK 0x0000FFFF -#define _LPNAV_TH_SHT 0 - -/*RPWM*/ -/*CPWM*/ -#define _TOGGLING BIT(7) -#define _WWLAN BIT(3) -#define _RPS_ST BIT(2) -#define _WLAN_TRX BIT(1) -#define _SYS_CLK BIT(0) - -#endif /* __RTL8712_POWERSAVE_BITDEF_H__*/ diff --git a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h b/drivers/staging/rtl8712/rtl8712_powersave_regdef.h deleted file mode 100644 index 1bcfde4b1c11f1647d9c0208cbb8a192ca8fd105..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_POWERSAVE_REGDEF_H__ -#define __RTL8712_POWERSAVE_REGDEF_H__ - -#define WOWCTRL (RTL8712_POWERSAVE_ + 0x00) -#define PSSTATUS (RTL8712_POWERSAVE_ + 0x01) -#define PSSWITCH (RTL8712_POWERSAVE_ + 0x02) -#define MIMOPS_WAITPERIOD (RTL8712_POWERSAVE_ + 0x03) -#define LPNAV_CTRL (RTL8712_POWERSAVE_ + 0x04) -#define WFM0 (RTL8712_POWERSAVE_ + 0x10) -#define WFM1 (RTL8712_POWERSAVE_ + 0x20) -#define WFM2 (RTL8712_POWERSAVE_ + 0x30) -#define WFM3 (RTL8712_POWERSAVE_ + 0x40) -#define WFM4 (RTL8712_POWERSAVE_ + 0x50) -#define WFM5 (RTL8712_POWERSAVE_ + 0x60) -#define WFCRC (RTL8712_POWERSAVE_ + 0x70) -#define RPWM (RTL8712_POWERSAVE_ + 0x7C) -#define CPWM (RTL8712_POWERSAVE_ + 0x7D) - -#endif /* __RTL8712_POWERSAVE_REGDEF_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h deleted file mode 100644 index 1de51c48f9c1b2d01866a3a6ec9dbc03ac9d35c2..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_RATECTRL_BITDEF_H__ -#define __RTL8712_RATECTRL_BITDEF_H__ - -/*INIRTSMCS_SEL*/ -#define _INIRTSMCS_SEL_MSK 0x3F - -/* RRSR*/ -#define _RRSR_SHORT BIT(23) -#define _RRSR_RSC_MSK 0x600000 -#define _RRSR_RSC_SHT 21 -#define _RRSR_BITMAP_MSK 0x0FFFFF -#define _RRSR_BITMAP_SHT 0 - -/* AGGLEN_LMT_H*/ -#define _AGGLMT_MCS32_MSK 0xF0 -#define _AGGLMT_MCS32_SHT 4 -#define _AGGLMT_MCS15_SGI_MSK 0x0F -#define _AGGLMT_MCS15_SGI_SHT 0 - -/* DARFRC*/ -/* RARFRC*/ -/* MCS_TXAGC*/ -/* CCK_TXAGC*/ -#define _CCK_MSK 0xFF00 -#define _CCK_SHT 8 -#define _BARKER_MSK 0x00FF -#define _BARKER_SHT 0 - -#endif /* __RTL8712_RATECTRL_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h deleted file mode 100644 index 9ed5653f3f7f117716d7772883a195f1c5907b4e..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_RATECTRL_REGDEF_H__ -#define __RTL8712_RATECTRL_REGDEF_H__ - -#define INIMCS_SEL (RTL8712_RATECTRL_ + 0x00) -#define INIRTSMCS_SEL (RTL8712_RATECTRL_ + 0x20) -#define RRSR (RTL8712_RATECTRL_ + 0x21) -#define ARFR0 (RTL8712_RATECTRL_ + 0x24) -#define ARFR1 (RTL8712_RATECTRL_ + 0x28) -#define ARFR2 (RTL8712_RATECTRL_ + 0x2C) -#define ARFR3 (RTL8712_RATECTRL_ + 0x30) -#define ARFR4 (RTL8712_RATECTRL_ + 0x34) -#define ARFR5 (RTL8712_RATECTRL_ + 0x38) -#define ARFR6 (RTL8712_RATECTRL_ + 0x3C) -#define ARFR7 (RTL8712_RATECTRL_ + 0x40) -#define AGGLEN_LMT_H (RTL8712_RATECTRL_ + 0x47) -#define AGGLEN_LMT_L (RTL8712_RATECTRL_ + 0x48) -#define DARFRC (RTL8712_RATECTRL_ + 0x50) -#define RARFRC (RTL8712_RATECTRL_ + 0x58) -#define MCS_TXAGC0 (RTL8712_RATECTRL_ + 0x60) -#define MCS_TXAGC1 (RTL8712_RATECTRL_ + 0x61) -#define MCS_TXAGC2 (RTL8712_RATECTRL_ + 0x62) -#define MCS_TXAGC3 (RTL8712_RATECTRL_ + 0x63) -#define MCS_TXAGC4 (RTL8712_RATECTRL_ + 0x64) -#define MCS_TXAGC5 (RTL8712_RATECTRL_ + 0x65) -#define MCS_TXAGC6 (RTL8712_RATECTRL_ + 0x66) -#define MCS_TXAGC7 (RTL8712_RATECTRL_ + 0x67) -#define CCK_TXAGC (RTL8712_RATECTRL_ + 0x68) - -#endif /*__RTL8712_RATECTRL_REGDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c deleted file mode 100644 index ab344d676bb94665ac57e8d74a27f7283b8a781a..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ /dev/null @@ -1,1075 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl8712_recv.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL8712_RECV_C_ - -#include <linux/if_ether.h> -#include <linux/ip.h> -#include <net/cfg80211.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "mlme_osdep.h" -#include "ethernet.h" -#include "usb_ops.h" -#include "wifi.h" - -static void recv_tasklet(struct tasklet_struct *t); - -int r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter) -{ - int i; - struct recv_buf *precvbuf; - addr_t tmpaddr = 0; - int alignment = 0; - struct sk_buff *pskb = NULL; - - /*init recv_buf*/ - _init_queue(&precvpriv->free_recv_buf_queue); - precvpriv->pallocated_recv_buf = - kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC); - if (!precvpriv->pallocated_recv_buf) - return -ENOMEM; - precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - - ((addr_t)(precvpriv->pallocated_recv_buf) & 3); - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - INIT_LIST_HEAD(&precvbuf->list); - spin_lock_init(&precvbuf->recvbuf_lock); - if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf)) - break; - precvbuf->ref_cnt = 0; - precvbuf->adapter = padapter; - list_add_tail(&precvbuf->list, - &precvpriv->free_recv_buf_queue.queue); - precvbuf++; - } - precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; - tasklet_setup(&precvpriv->recv_tasklet, recv_tasklet); - skb_queue_head_init(&precvpriv->rx_skb_queue); - - skb_queue_head_init(&precvpriv->free_recv_skb_queue); - for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { - pskb = netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ + - RECVBUFF_ALIGN_SZ); - if (pskb) { - tmpaddr = (addr_t)pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); - skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - } - pskb = NULL; - } - return 0; -} - -void r8712_free_recv_priv(struct recv_priv *precvpriv) -{ - int i; - struct recv_buf *precvbuf; - struct _adapter *padapter = precvpriv->adapter; - - precvbuf = (struct recv_buf *)precvpriv->precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - r8712_os_recvbuf_resource_free(padapter, precvbuf); - precvbuf++; - } - kfree(precvpriv->pallocated_recv_buf); - skb_queue_purge(&precvpriv->rx_skb_queue); - if (skb_queue_len(&precvpriv->rx_skb_queue)) - netdev_warn(padapter->pnetdev, "r8712u: rx_skb_queue not empty\n"); - skb_queue_purge(&precvpriv->free_recv_skb_queue); - if (skb_queue_len(&precvpriv->free_recv_skb_queue)) - netdev_warn(padapter->pnetdev, "r8712u: free_recv_skb_queue not empty %d\n", - skb_queue_len(&precvpriv->free_recv_skb_queue)); -} - -void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) -{ - precvbuf->transfer_len = 0; - precvbuf->len = 0; - precvbuf->ref_cnt = 0; - if (precvbuf->pbuf) { - precvbuf->pdata = precvbuf->pbuf; - precvbuf->phead = precvbuf->pbuf; - precvbuf->ptail = precvbuf->pbuf; - precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ; - } -} - -void r8712_free_recvframe(union recv_frame *precvframe, - struct __queue *pfree_recv_queue) -{ - unsigned long irqL; - struct _adapter *padapter = precvframe->u.hdr.adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - if (precvframe->u.hdr.pkt) { - dev_kfree_skb_any(precvframe->u.hdr.pkt);/*free skb by driver*/ - precvframe->u.hdr.pkt = NULL; - } - spin_lock_irqsave(&pfree_recv_queue->lock, irqL); - list_del_init(&precvframe->u.hdr.list); - list_add_tail(&precvframe->u.hdr.list, &pfree_recv_queue->queue); - if (padapter) { - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt++; - } - spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL); -} - -static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, - struct recv_stat *prxstat) -{ - /*TODO: - * Offset 0 - */ - pattrib->bdecrypted = (le32_to_cpu(prxstat->rxdw0) & BIT(27)) == 0; - pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) != 0; - /*Offset 4*/ - /*Offset 8*/ - /*Offset 12*/ - if (le32_to_cpu(prxstat->rxdw3) & BIT(13)) { - pattrib->tcpchk_valid = 1; /* valid */ - if (le32_to_cpu(prxstat->rxdw3) & BIT(11)) - pattrib->tcp_chkrpt = 1; /* correct */ - else - pattrib->tcp_chkrpt = 0; /* incorrect */ - if (le32_to_cpu(prxstat->rxdw3) & BIT(12)) - pattrib->ip_chkrpt = 1; /* correct */ - else - pattrib->ip_chkrpt = 0; /* incorrect */ - } else { - pattrib->tcpchk_valid = 0; /* invalid */ - } - pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f); - pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 14) & 0x1); - /*Offset 16*/ - /*Offset 20*/ - /*phy_info*/ -} - -/*perform defrag*/ -static union recv_frame *recvframe_defrag(struct _adapter *adapter, - struct __queue *defrag_q) -{ - struct list_head *plist, *phead; - u8 wlanhdr_offset; - u8 curfragnum; - struct recv_frame_hdr *pfhdr, *pnfhdr; - union recv_frame *prframe, *pnextrframe; - struct __queue *pfree_recv_queue; - - pfree_recv_queue = &adapter->recvpriv.free_recv_queue; - phead = &defrag_q->queue; - plist = phead->next; - prframe = container_of(plist, union recv_frame, u.list); - list_del_init(&prframe->u.list); - pfhdr = &prframe->u.hdr; - curfragnum = 0; - if (curfragnum != pfhdr->attrib.frag_num) { - /*the first fragment number must be 0 - *free the whole queue - */ - r8712_free_recvframe(prframe, pfree_recv_queue); - r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); - return NULL; - } - curfragnum++; - plist = &defrag_q->queue; - plist = plist->next; - while (!end_of_queue_search(phead, plist)) { - pnextrframe = container_of(plist, union recv_frame, u.list); - pnfhdr = &pnextrframe->u.hdr; - /*check the fragment sequence (2nd ~n fragment frame) */ - if (curfragnum != pnfhdr->attrib.frag_num) { - /* the fragment number must increase (after decache) - * release the defrag_q & prframe - */ - r8712_free_recvframe(prframe, pfree_recv_queue); - r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); - return NULL; - } - curfragnum++; - /* copy the 2nd~n fragment frame's payload to the first fragment - * get the 2nd~last fragment frame's payload - */ - wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; - recvframe_pull(pnextrframe, wlanhdr_offset); - /* append to first fragment frame's tail (if privacy frame, - * pull the ICV) - */ - recvframe_pull_tail(prframe, pfhdr->attrib.icv_len); - memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len); - recvframe_put(prframe, pnfhdr->len); - pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len; - plist = plist->next; - } - /* free the defrag_q queue and return the prframe */ - r8712_free_recvframe_queue(defrag_q, pfree_recv_queue); - return prframe; -} - -/* check if need to defrag, if needed queue the frame to defrag_q */ -union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, - union recv_frame *precv_frame) -{ - u8 ismfrag; - u8 fragnum; - u8 *psta_addr; - struct recv_frame_hdr *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - struct list_head *phead; - union recv_frame *prtnframe = NULL; - struct __queue *pfree_recv_queue, *pdefrag_q; - - pstapriv = &padapter->stapriv; - pfhdr = &precv_frame->u.hdr; - pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - /* need to define struct of wlan header frame ctrl */ - ismfrag = pfhdr->attrib.mfrag; - fragnum = pfhdr->attrib.frag_num; - psta_addr = pfhdr->attrib.ta; - psta = r8712_get_stainfo(pstapriv, psta_addr); - if (!psta) - pdefrag_q = NULL; - else - pdefrag_q = &psta->sta_recvpriv.defrag_q; - - if ((ismfrag == 0) && (fragnum == 0)) - prtnframe = precv_frame;/*isn't a fragment frame*/ - if (ismfrag == 1) { - /* 0~(n-1) fragment frame - * enqueue to defraf_g - */ - if (pdefrag_q) { - if (fragnum == 0) { - /*the first fragment*/ - if (!list_empty(&pdefrag_q->queue)) { - /*free current defrag_q */ - r8712_free_recvframe_queue(pdefrag_q, pfree_recv_queue); - } - } - /* Then enqueue the 0~(n-1) fragment to the defrag_q */ - phead = &pdefrag_q->queue; - list_add_tail(&pfhdr->list, phead); - prtnframe = NULL; - } else { - /* can't find this ta's defrag_queue, so free this - * recv_frame - */ - r8712_free_recvframe(precv_frame, pfree_recv_queue); - prtnframe = NULL; - } - } - if ((ismfrag == 0) && (fragnum != 0)) { - /* the last fragment frame - * enqueue the last fragment - */ - if (pdefrag_q) { - phead = &pdefrag_q->queue; - list_add_tail(&pfhdr->list, phead); - /*call recvframe_defrag to defrag*/ - precv_frame = recvframe_defrag(padapter, pdefrag_q); - prtnframe = precv_frame; - } else { - /* can't find this ta's defrag_queue, so free this - * recv_frame - */ - r8712_free_recvframe(precv_frame, pfree_recv_queue); - prtnframe = NULL; - } - } - if (prtnframe && (prtnframe->u.hdr.attrib.privacy)) { - /* after defrag we must check tkip mic code */ - if (r8712_recvframe_chkmic(padapter, prtnframe) == _FAIL) { - r8712_free_recvframe(prtnframe, pfree_recv_queue); - prtnframe = NULL; - } - } - return prtnframe; -} - -static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) -{ - int a_len, padding_len; - u16 eth_type, nSubframe_Length; - u8 nr_subframes, i; - unsigned char *pdata; - struct rx_pkt_attrib *pattrib; - _pkt *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; - - nr_subframes = 0; - pattrib = &prframe->u.hdr.attrib; - recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen); - if (prframe->u.hdr.attrib.iv_len > 0) - recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len); - a_len = prframe->u.hdr.len; - pdata = prframe->u.hdr.rx_data; - while (a_len > ETH_HLEN) { - /* Offset 12 denote 2 mac address */ - nSubframe_Length = *((u16 *)(pdata + 12)); - /*==m==>change the length order*/ - nSubframe_Length = (nSubframe_Length >> 8) + - (nSubframe_Length << 8); - if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { - netdev_warn(padapter->pnetdev, "r8712u: nRemain_Length is %d and nSubframe_Length is: %d\n", - a_len, nSubframe_Length); - goto exit; - } - /* move the data point to data content */ - pdata += ETH_HLEN; - a_len -= ETH_HLEN; - /* Allocate new skb for releasing to upper layer */ - sub_skb = dev_alloc_skb(nSubframe_Length + 12); - if (!sub_skb) - break; - skb_reserve(sub_skb, 12); - skb_put_data(sub_skb, pdata, nSubframe_Length); - subframes[nr_subframes++] = sub_skb; - if (nr_subframes >= MAX_SUBFRAME_COUNT) { - netdev_warn(padapter->pnetdev, "r8712u: ParseSubframe(): Too many Subframes! Packets dropped!\n"); - break; - } - pdata += nSubframe_Length; - a_len -= nSubframe_Length; - if (a_len != 0) { - padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & 3); - if (padding_len == 4) - padding_len = 0; - if (a_len < padding_len) - goto exit; - pdata += padding_len; - a_len -= padding_len; - } - } - for (i = 0; i < nr_subframes; i++) { - sub_skb = subframes[i]; - /* convert hdr + possible LLC headers into Ethernet header */ - eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7]; - if (sub_skb->len >= 8 && - ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) && - eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || - !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType - */ - skb_pull(sub_skb, SNAP_SIZE); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, - ETH_ALEN); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, - ETH_ALEN); - } else { - __be16 len; - /* Leave Ethernet header part of hdr and full payload */ - len = htons(sub_skb->len); - memcpy(skb_push(sub_skb, 2), &len, 2); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, - ETH_ALEN); - memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, - ETH_ALEN); - } - /* Indicate the packets to upper layer */ - if (sub_skb) { - sub_skb->protocol = - eth_type_trans(sub_skb, padapter->pnetdev); - sub_skb->dev = padapter->pnetdev; - if ((pattrib->tcpchk_valid == 1) && - (pattrib->tcp_chkrpt == 1)) { - sub_skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - sub_skb->ip_summed = CHECKSUM_NONE; - } - netif_rx(sub_skb); - } - } -exit: - prframe->u.hdr.len = 0; - r8712_free_recvframe(prframe, pfree_recv_queue); -} - -void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf) -{ - __le32 voffset; - u8 *poffset; - u16 cmd_len, drvinfo_sz; - struct recv_stat *prxstat; - - poffset = prxcmdbuf; - voffset = *(__le32 *)poffset; - prxstat = prxcmdbuf; - drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; - drvinfo_sz <<= 3; - poffset += RXDESC_SIZE + drvinfo_sz; - do { - voffset = *(__le32 *)poffset; - cmd_len = (u16)(le32_to_cpu(voffset) & 0xffff); - r8712_event_handle(padapter, (__le32 *)poffset); - poffset += (cmd_len + 8);/*8 bytes alignment*/ - } while (le32_to_cpu(voffset) & BIT(31)); -} - -static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, - u16 seq_num) -{ - u8 wsize = preorder_ctrl->wsize_b; - u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) % 4096; - - /* Rx Reorder initialize condition.*/ - if (preorder_ctrl->indicate_seq == 0xffff) - preorder_ctrl->indicate_seq = seq_num; - /* Drop out the packet which SeqNum is smaller than WinStart */ - if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) - return false; - /* - * Sliding window manipulation. Conditions includes: - * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 - * 2. Incoming SeqNum is larger than the WinEnd => Window shift N - */ - if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) - preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + - 1) % 4096; - else if (SN_LESS(wend, seq_num)) { - if (seq_num >= (wsize - 1)) - preorder_ctrl->indicate_seq = seq_num + 1 - wsize; - else - preorder_ctrl->indicate_seq = 4095 - (wsize - - (seq_num + 1)) + 1; - } - return true; -} - -static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, - union recv_frame *prframe) -{ - struct list_head *phead, *plist; - union recv_frame *pnextrframe; - struct rx_pkt_attrib *pnextattrib; - struct __queue *ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; - - phead = &ppending_recvframe_queue->queue; - plist = phead->next; - while (!end_of_queue_search(phead, plist)) { - pnextrframe = container_of(plist, union recv_frame, u.list); - pnextattrib = &pnextrframe->u.hdr.attrib; - - if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) - return false; - - if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) - plist = plist->next; - else - break; - } - list_del_init(&prframe->u.hdr.list); - list_add_tail(&prframe->u.hdr.list, plist); - return true; -} - -int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, - struct recv_reorder_ctrl *preorder_ctrl, - int bforced) -{ - struct list_head *phead, *plist; - union recv_frame *prframe; - struct rx_pkt_attrib *pattrib; - int bPktInBuf = false; - struct __queue *ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - - phead = &ppending_recvframe_queue->queue; - plist = phead->next; - /* Handling some condition for forced indicate case.*/ - if (bforced) { - if (list_empty(phead)) - return true; - - prframe = container_of(plist, union recv_frame, u.list); - pattrib = &prframe->u.hdr.attrib; - preorder_ctrl->indicate_seq = pattrib->seq_num; - } - /* Prepare indication list and indication. - * Check if there is any packet need indicate. - */ - while (!list_empty(phead)) { - prframe = container_of(plist, union recv_frame, u.list); - pattrib = &prframe->u.hdr.attrib; - if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) { - plist = plist->next; - list_del_init(&prframe->u.hdr.list); - if (SN_EQUAL(preorder_ctrl->indicate_seq, - pattrib->seq_num)) - preorder_ctrl->indicate_seq = - (preorder_ctrl->indicate_seq + 1) % 4096; - /*indicate this recv_frame*/ - if (!pattrib->amsdu) { - if (!padapter->driver_stopped && - !padapter->surprise_removed) { - /* indicate this recv_frame */ - r8712_recv_indicatepkt(padapter, - prframe); - } - } else if (pattrib->amsdu == 1) { - amsdu_to_msdu(padapter, prframe); - } - /* Update local variables. */ - bPktInBuf = false; - } else { - bPktInBuf = true; - break; - } - } - return bPktInBuf; -} - -static int recv_indicatepkt_reorder(struct _adapter *padapter, - union recv_frame *prframe) -{ - unsigned long irql; - struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; - struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl; - struct __queue *ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - - if (!pattrib->amsdu) { - /* s1. */ - r8712_wlanhdr_to_ethhdr(prframe); - if (pattrib->qos != 1) { - if (!padapter->driver_stopped && - !padapter->surprise_removed) { - r8712_recv_indicatepkt(padapter, prframe); - return 0; - } else { - return -EINVAL; - } - } - } - spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); - /*s2. check if winstart_b(indicate_seq) needs to be updated*/ - if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) - goto _err_exit; - /*s3. Insert all packet into Reorder Queue to maintain its ordering.*/ - if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) - goto _err_exit; - /*s4. - * Indication process. - * After Packet dropping and Sliding Window shifting as above, we can - * now just indicate the packets with the SeqNum smaller than latest - * WinStart and buffer other packets. - * - * For Rx Reorder condition: - * 1. All packets with SeqNum smaller than WinStart => Indicate - * 2. All packets with SeqNum larger than or equal to - * WinStart => Buffer it. - */ - if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) { - mod_timer(&preorder_ctrl->reordering_ctrl_timer, - jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); - spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); - } else { - spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); - del_timer(&preorder_ctrl->reordering_ctrl_timer); - } - return 0; -_err_exit: - spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); - return -ENOMEM; -} - -void r8712_reordering_ctrl_timeout_handler(void *pcontext) -{ - unsigned long irql; - struct recv_reorder_ctrl *preorder_ctrl = pcontext; - struct _adapter *padapter = preorder_ctrl->padapter; - struct __queue *ppending_recvframe_queue = - &preorder_ctrl->pending_recvframe_queue; - - if (padapter->driver_stopped || padapter->surprise_removed) - return; - spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); - r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, true); - spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); -} - -static int r8712_process_recv_indicatepkts(struct _adapter *padapter, - union recv_frame *prframe) -{ - int retval = _SUCCESS; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ - if (recv_indicatepkt_reorder(padapter, prframe)) { - /* including perform A-MPDU Rx Ordering Buffer Control*/ - if (!padapter->driver_stopped && - !padapter->surprise_removed) - return _FAIL; - } - } else { /*B/G mode*/ - retval = r8712_wlanhdr_to_ethhdr(prframe); - if (retval) - return _FAIL; - if (!padapter->driver_stopped && !padapter->surprise_removed) { - /* indicate this recv_frame */ - r8712_recv_indicatepkt(padapter, prframe); - } else { - return _FAIL; - } - } - return retval; -} - -static u8 query_rx_pwr_percentage(s8 antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; -} - -static u8 evm_db2percentage(s8 value) -{ - /* - * -33dB~0dB to 0%~99% - */ - s8 ret_val = clamp(-value, 0, 33) * 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} - -s32 r8712_signal_scale_mapping(s32 cur_sig) -{ - s32 ret_sig; - - if (cur_sig >= 51 && cur_sig <= 100) - ret_sig = 100; - else if (cur_sig >= 41 && cur_sig <= 50) - ret_sig = 80 + ((cur_sig - 40) * 2); - else if (cur_sig >= 31 && cur_sig <= 40) - ret_sig = 66 + (cur_sig - 30); - else if (cur_sig >= 21 && cur_sig <= 30) - ret_sig = 54 + (cur_sig - 20); - else if (cur_sig >= 10 && cur_sig <= 20) - ret_sig = 42 + (((cur_sig - 10) * 2) / 3); - else if (cur_sig >= 5 && cur_sig <= 9) - ret_sig = 22 + (((cur_sig - 5) * 3) / 2); - else if (cur_sig >= 1 && cur_sig <= 4) - ret_sig = 6 + (((cur_sig - 1) * 3) / 2); - else - ret_sig = cur_sig; - return ret_sig; -} - -static s32 translate2dbm(struct _adapter *padapter, u8 signal_strength_idx) -{ - s32 signal_power; /* in dBm.*/ - /* Translate to dBm (x=0.5y-95).*/ - signal_power = (s32)((signal_strength_idx + 1) >> 1); - signal_power -= 95; - return signal_power; -} - -static void query_rx_phy_status(struct _adapter *padapter, - union recv_frame *prframe) -{ - u8 i, max_spatial_stream, evm; - struct recv_stat *prxstat = (struct recv_stat *)prframe->u.hdr.rx_head; - struct phy_stat *pphy_stat = (struct phy_stat *)(prxstat + 1); - u8 *pphy_head = (u8 *)(prxstat + 1); - s8 rx_pwr[4], rx_pwr_all; - u8 pwdb_all; - u32 rssi, total_rssi = 0; - u8 bcck_rate = 0, rf_rx_num = 0, cck_highpwr = 0; - struct phy_cck_rx_status *pcck_buf; - u8 sq; - - /* Record it for next packet processing*/ - bcck_rate = (prframe->u.hdr.attrib.mcs_rate <= 3 ? 1 : 0); - if (bcck_rate) { - u8 report; - - /* CCK Driver info Structure is not the same as OFDM packet.*/ - pcck_buf = (struct phy_cck_rx_status *)pphy_stat; - /* (1)Hardware does not provide RSSI for CCK - * (2)PWDB, Average PWDB calculated by hardware - * (for rate adaptive) - */ - if (!cck_highpwr) { - report = pcck_buf->cck_agc_rpt & 0xc0; - report >>= 6; - switch (report) { - /* Modify the RF RNA gain value to -40, -20, - * -2, 14 by Jenyu's suggestion - * Note: different RF with the different - * RNA gain. - */ - case 0x3: - rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - case 0x2: - rx_pwr_all = -20 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - case 0x1: - rx_pwr_all = -2 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - case 0x0: - rx_pwr_all = 14 - (pcck_buf->cck_agc_rpt & - 0x3e); - break; - } - } else { - report = ((u8)(le32_to_cpu(pphy_stat->phydw1) >> 8)) & - 0x60; - report >>= 5; - switch (report) { - case 0x3: - rx_pwr_all = -40 - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -20 - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -2 - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = 14 - ((pcck_buf->cck_agc_rpt & - 0x1f) << 1); - break; - } - } - pwdb_all = query_rx_pwr_percentage(rx_pwr_all); - /* CCK gain is smaller than OFDM/MCS gain,*/ - /* so we add gain diff by experiences, the val is 6 */ - pwdb_all += 6; - if (pwdb_all > 100) - pwdb_all = 100; - /* modify the offset to make the same gain index with OFDM.*/ - if (pwdb_all > 34 && pwdb_all <= 42) - pwdb_all -= 2; - else if (pwdb_all > 26 && pwdb_all <= 34) - pwdb_all -= 6; - else if (pwdb_all > 14 && pwdb_all <= 26) - pwdb_all -= 8; - else if (pwdb_all > 4 && pwdb_all <= 14) - pwdb_all -= 4; - /* - * (3) Get Signal Quality (EVM) - */ - if (pwdb_all > 40) { - sq = 100; - } else { - sq = pcck_buf->sq_rpt; - if (pcck_buf->sq_rpt > 64) - sq = 0; - else if (pcck_buf->sq_rpt < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - prframe->u.hdr.attrib.signal_qual = sq; - prframe->u.hdr.attrib.rx_mimo_signal_qual[0] = sq; - prframe->u.hdr.attrib.rx_mimo_signal_qual[1] = -1; - } else { - /* (1)Get RSSI for HT rate */ - for (i = 0; i < ((padapter->registrypriv.rf_config) & - 0x0f); i++) { - rf_rx_num++; - rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i] - & 0x3F) * 2) - 110; - /* Translate DBM to percentage. */ - rssi = query_rx_pwr_percentage(rx_pwr[i]); - total_rssi += rssi; - } - /* (2)PWDB, Average PWDB calculated by hardware (for - * rate adaptive) - */ - rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f) - - 106; - pwdb_all = query_rx_pwr_percentage(rx_pwr_all); - - { - /* (3)EVM of HT rate */ - if (prframe->u.hdr.attrib.htc && - prframe->u.hdr.attrib.mcs_rate >= 20 && - prframe->u.hdr.attrib.mcs_rate <= 27) { - /* both spatial stream make sense */ - max_spatial_stream = 2; - } else { - /* only spatial stream 1 makes sense */ - max_spatial_stream = 1; - } - for (i = 0; i < max_spatial_stream; i++) { - evm = evm_db2percentage((pphy_head - [PHY_STAT_RXEVM_SHT + i]));/*dbm*/ - prframe->u.hdr.attrib.signal_qual = - (u8)(evm & 0xff); - prframe->u.hdr.attrib.rx_mimo_signal_qual[i] = - (u8)(evm & 0xff); - } - } - } - /* UI BSS List signal strength(in percentage), make it good looking, - * from 0~100. It is assigned to the BSS List in - * GetValueFromBeaconOrProbeRsp(). - */ - if (bcck_rate) { - prframe->u.hdr.attrib.signal_strength = - (u8)r8712_signal_scale_mapping(pwdb_all); - } else { - if (rf_rx_num != 0) - prframe->u.hdr.attrib.signal_strength = - (u8)(r8712_signal_scale_mapping(total_rssi /= - rf_rx_num)); - } -} - -static void process_link_qual(struct _adapter *padapter, - union recv_frame *prframe) -{ - u32 last_evm = 0, avg_val; - struct rx_pkt_attrib *pattrib; - struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data; - - if (!prframe || !padapter) - return; - pattrib = &prframe->u.hdr.attrib; - if (pattrib->signal_qual != 0) { - /* - * 1. Record the general EVM to the sliding window. - */ - if (sqd->total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) { - sqd->total_num = PHY_LINKQUALITY_SLID_WIN_MAX; - last_evm = sqd->elements[sqd->index]; - sqd->total_val -= last_evm; - } - sqd->total_val += pattrib->signal_qual; - sqd->elements[sqd->index++] = pattrib->signal_qual; - if (sqd->index >= PHY_LINKQUALITY_SLID_WIN_MAX) - sqd->index = 0; - - /* <1> Showed on UI for user, in percentage. */ - avg_val = sqd->total_val / sqd->total_num; - padapter->recvpriv.signal = (u8)avg_val; - } -} - -static void process_rssi(struct _adapter *padapter, union recv_frame *prframe) -{ - u32 last_rssi, tmp_val; - struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; - struct smooth_rssi_data *ssd = &padapter->recvpriv.signal_strength_data; - - if (ssd->total_num++ >= PHY_RSSI_SLID_WIN_MAX) { - ssd->total_num = PHY_RSSI_SLID_WIN_MAX; - last_rssi = ssd->elements[ssd->index]; - ssd->total_val -= last_rssi; - } - ssd->total_val += pattrib->signal_strength; - ssd->elements[ssd->index++] = pattrib->signal_strength; - if (ssd->index >= PHY_RSSI_SLID_WIN_MAX) - ssd->index = 0; - tmp_val = ssd->total_val / ssd->total_num; - padapter->recvpriv.rssi = (s8)translate2dbm(padapter, (u8)tmp_val); -} - -static void process_phy_info(struct _adapter *padapter, - union recv_frame *prframe) -{ - query_rx_phy_status(padapter, prframe); - process_rssi(padapter, prframe); - process_link_qual(padapter, prframe); -} - -int recv_func(struct _adapter *padapter, void *pcontext) -{ - struct rx_pkt_attrib *pattrib; - union recv_frame *prframe, *orig_prframe; - int retval = _SUCCESS; - struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - prframe = pcontext; - orig_prframe = prframe; - pattrib = &prframe->u.hdr.attrib; - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - if (pattrib->crc_err == 1) - padapter->mppriv.rx_crcerrpktcount++; - else - padapter->mppriv.rx_pktcount++; - if (!check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE)) { - /* free this recv_frame */ - r8712_free_recvframe(orig_prframe, pfree_recv_queue); - goto _exit_recv_func; - } - } - /* check the frame crtl field and decache */ - retval = r8712_validate_recv_frame(padapter, prframe); - if (retval != _SUCCESS) { - /* free this recv_frame */ - r8712_free_recvframe(orig_prframe, pfree_recv_queue); - goto _exit_recv_func; - } - process_phy_info(padapter, prframe); - prframe = r8712_decryptor(padapter, prframe); - if (!prframe) { - retval = _FAIL; - goto _exit_recv_func; - } - prframe = r8712_recvframe_chk_defrag(padapter, prframe); - if (!prframe) - goto _exit_recv_func; - prframe = r8712_portctrl(padapter, prframe); - if (!prframe) { - retval = _FAIL; - goto _exit_recv_func; - } - retval = r8712_process_recv_indicatepkts(padapter, prframe); - if (retval != _SUCCESS) { - r8712_free_recvframe(orig_prframe, pfree_recv_queue); - goto _exit_recv_func; - } -_exit_recv_func: - return retval; -} - -static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) -{ - u8 *pbuf, shift_sz = 0; - u8 frag, mf; - uint pkt_len; - u32 transfer_len; - struct recv_stat *prxstat; - u16 pkt_cnt, drvinfo_sz, pkt_offset, tmp_len, alloc_sz; - struct __queue *pfree_recv_queue; - _pkt *pkt_copy = NULL; - union recv_frame *precvframe = NULL; - struct recv_priv *precvpriv = &padapter->recvpriv; - - pfree_recv_queue = &precvpriv->free_recv_queue; - pbuf = pskb->data; - prxstat = (struct recv_stat *)pbuf; - pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff; - pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff; - transfer_len = pskb->len; - /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R - * pairs. The packet count will be a big number so that the containing - * packet will effect the Rx reordering. - */ - if (transfer_len < pkt_len) { - /* In this case, it means the MAX_RECVBUF_SZ is too small to - * get the data from 8712u. - */ - return; - } - do { - prxstat = (struct recv_stat *)pbuf; - pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff; - /* more fragment bit */ - mf = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1; - /* ragmentation number */ - frag = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf; - /* uint 2^3 = 8 bytes */ - drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; - drvinfo_sz <<= 3; - if (pkt_len <= 0) - return; - /* Qos data, wireless lan header length is 26 */ - if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01) - shift_sz = 2; - precvframe = r8712_alloc_recvframe(pfree_recv_queue); - if (!precvframe) - return; - INIT_LIST_HEAD(&precvframe->u.hdr.list); - precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/ - precvframe->u.hdr.len = 0; - tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE; - pkt_offset = (u16)round_up(tmp_len, 128); - /* for first fragment packet, driver need allocate 1536 + - * drvinfo_sz + RXDESC_SIZE to defrag packet. - */ - if ((mf == 1) && (frag == 0)) - /*1658+6=1664, 1664 is 128 alignment.*/ - alloc_sz = max_t(u16, tmp_len, 1658); - else - alloc_sz = tmp_len; - /* 2 is for IP header 4 bytes alignment in QoS packet case. - * 4 is for skb->data 4 bytes alignment. - */ - alloc_sz += 6; - pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz); - if (!pkt_copy) - return; - - precvframe->u.hdr.pkt = pkt_copy; - skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) % 4)); - skb_reserve(pkt_copy, shift_sz); - memcpy(pkt_copy->data, pbuf, tmp_len); - precvframe->u.hdr.rx_head = pkt_copy->data; - precvframe->u.hdr.rx_data = pkt_copy->data; - precvframe->u.hdr.rx_tail = pkt_copy->data; - precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz; - - recvframe_put(precvframe, tmp_len); - recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); - /* because the endian issue, driver avoid reference to the - * rxstat after calling update_recvframe_attrib_from_recvstat(); - */ - update_recvframe_attrib_from_recvstat(&precvframe->u.hdr.attrib, - prxstat); - r8712_recv_entry(precvframe); - transfer_len -= pkt_offset; - pbuf += pkt_offset; - pkt_cnt--; - precvframe = NULL; - pkt_copy = NULL; - } while ((transfer_len > 0) && pkt_cnt > 0); -} - -static void recv_tasklet(struct tasklet_struct *t) -{ - struct sk_buff *pskb; - struct _adapter *padapter = from_tasklet(padapter, t, - recvpriv.recv_tasklet); - struct recv_priv *precvpriv = &padapter->recvpriv; - - while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) { - recvbuf2recvframe(padapter, pskb); - skb_reset_tail_pointer(pskb); - pskb->len = 0; - if (!skb_cloned(pskb)) - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); - else - consume_skb(pskb); - } -} diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h deleted file mode 100644 index a1360dcf91cec4e64ec3bfba79fba1b43f716e6d..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ /dev/null @@ -1,145 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL8712_RECV_H_ -#define _RTL8712_RECV_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -/* Realtek's v2.6.6 reduced this to 4. However, under heavy network and CPU - * loads, even 8 receive buffers might not be enough; cutting it to 4 seemed - * unwise. - */ -#define NR_RECVBUFF (8) - -#define NR_PREALLOC_RECV_SKB (8) -#define RXDESC_SIZE 24 -#define RXDESC_OFFSET RXDESC_SIZE -#define RECV_BLK_SZ 512 -#define RECV_BLK_CNT 16 -#define RECV_BLK_TH RECV_BLK_CNT -#define MAX_RECVBUF_SZ 9100 -#define RECVBUFF_ALIGN_SZ 512 -#define RSVD_ROOM_SZ (0) -/*These definition is used for Rx packet reordering.*/ -#define SN_LESS(a, b) (((a-b) & 0x800) != 0) -#define SN_EQUAL(a, b) (a == b) -#define REORDER_WAIT_TIME 30 /* (ms)*/ - -struct recv_stat { - __le32 rxdw0; - __le32 rxdw1; - __le32 rxdw2; - __le32 rxdw3; - __le32 rxdw4; - __le32 rxdw5; -}; - -struct phy_cck_rx_status { - /* For CCK rate descriptor. This is a unsigned 8:1 variable. - * LSB bit present 0.5. And MSB 7 bts present a signed value. - * Range from -64~+63.5. - */ - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -struct phy_stat { - __le32 phydw0; - __le32 phydw1; - __le32 phydw2; - __le32 phydw3; - __le32 phydw4; - __le32 phydw5; - __le32 phydw6; - __le32 phydw7; -}; - -#define PHY_STAT_GAIN_TRSW_SHT 0 -#define PHY_STAT_PWDB_ALL_SHT 4 -#define PHY_STAT_CFOSHO_SHT 5 -#define PHY_STAT_CCK_AGC_RPT_SHT 5 -#define PHY_STAT_CFOTAIL_SHT 9 -#define PHY_STAT_RXEVM_SHT 13 -#define PHY_STAT_RXSNR_SHT 15 -#define PHY_STAT_PDSNR_SHT 19 -#define PHY_STAT_CSI_CURRENT_SHT 21 -#define PHY_STAT_CSI_TARGET_SHT 23 -#define PHY_STAT_SIGEVM_SHT 25 -#define PHY_STAT_MAX_EX_PWR_SHT 26 - -union recvstat { - struct recv_stat recv_stat; - unsigned int value[RXDESC_SIZE >> 2]; -}; - -struct recv_buf { - struct list_head list; - spinlock_t recvbuf_lock; - u32 ref_cnt; - struct _adapter *adapter; - struct urb *purb; - _pkt *pskb; - u8 irp_pending; - u32 transfer_len; - uint len; - u8 *phead; - u8 *pdata; - u8 *ptail; - u8 *pend; - u8 *pbuf; - u8 *pallocated_buf; -}; - -/* - * head -----> - * data -----> - * payload - * tail -----> - * end -----> - * len = (unsigned int )(tail - data); - */ -struct recv_frame_hdr { - struct list_head list; - _pkt *pkt; - _pkt *pkt_newalloc; - struct _adapter *adapter; - u8 fragcnt; - struct rx_pkt_attrib attrib; - uint len; - u8 *rx_head; - u8 *rx_data; - u8 *rx_tail; - u8 *rx_end; - void *precvbuf; - struct sta_info *psta; - /*for A-MPDU Rx reordering buffer control*/ - struct recv_reorder_ctrl *preorder_ctrl; -}; - -union recv_frame { - union { - struct list_head list; - struct recv_frame_hdr hdr; - } u; -}; - -void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); -void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf); -s32 r8712_signal_scale_mapping(s32 cur_sig); -void r8712_reordering_ctrl_timeout_handler(void *pcontext); - -#endif - diff --git a/drivers/staging/rtl8712/rtl8712_regdef.h b/drivers/staging/rtl8712/rtl8712_regdef.h deleted file mode 100644 index 28aec9aa539fd315367c1bab84088c0e703d389c..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_regdef.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_REGDEF_H__ -#define __RTL8712_REGDEF_H__ - -#include "rtl8712_syscfg_regdef.h" -#include "rtl8712_cmdctrl_regdef.h" -#include "rtl8712_macsetting_regdef.h" -#include "rtl8712_timectrl_regdef.h" -#include "rtl8712_fifoctrl_regdef.h" -#include "rtl8712_ratectrl_regdef.h" -#include "rtl8712_edcasetting_regdef.h" -#include "rtl8712_wmac_regdef.h" -#include "rtl8712_powersave_regdef.h" -#include "rtl8712_gp_regdef.h" -#include "rtl8712_debugctrl_regdef.h" - -#define HIMR (RTL8712_INTERRUPT_ + 0x08) - -#endif /* __RTL8712_REGDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_security_bitdef.h b/drivers/staging/rtl8712/rtl8712_security_bitdef.h deleted file mode 100644 index 44275ef455a0ae1a022e6ec7aa65b80f56b740ab..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_security_bitdef.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_SECURITY_BITDEF_H__ -#define __RTL8712_SECURITY_BITDEF_H__ - -/*CAMCMD*/ -#define _SECCAM_POLLING BIT(31) -#define _SECCAM_CLR BIT(30) -#define _SECCAM_WE BIT(16) -#define _SECCAM_ADR_MSK 0x000000FF -#define _SECCAM_ADR_SHT 0 - -/*CAMDBG*/ -#define _SECCAM_INFO BIT(31) -#define _SEC_KEYFOUND BIT(30) -#define _SEC_CONFIG_MSK 0x3F000000 -#define _SEC_CONFIG_SHT 24 -#define _SEC_KEYCONTENT_MSK 0x00FFFFFF -#define _SEC_KEYCONTENT_SHT 0 - -/*SECCFG*/ -#define _NOSKMC BIT(5) -#define _SKBYA2 BIT(4) -#define _RXDEC BIT(3) -#define _TXENC BIT(2) -#define _RXUSEDK BIT(1) -#define _TXUSEDK BIT(0) - -#endif /*__RTL8712_SECURITY_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_spec.h b/drivers/staging/rtl8712/rtl8712_spec.h deleted file mode 100644 index 613a410e5714bcb4725be55a3f38d5f18646c665..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_spec.h +++ /dev/null @@ -1,121 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_SPEC_H__ -#define __RTL8712_SPEC_H__ - -#define RTL8712_IOBASE_TXPKT 0x10200000 /*IOBASE_TXPKT*/ -#define RTL8712_IOBASE_RXPKT 0x10210000 /*IOBASE_RXPKT*/ -#define RTL8712_IOBASE_RXCMD 0x10220000 /*IOBASE_RXCMD*/ -#define RTL8712_IOBASE_TXSTATUS 0x10230000 /*IOBASE_TXSTATUS*/ -#define RTL8712_IOBASE_RXSTATUS 0x10240000 /*IOBASE_RXSTATUS*/ -#define RTL8712_IOBASE_IOREG 0x10250000 /*IOBASE_IOREG ADDR*/ -#define RTL8712_IOBASE_SCHEDULER 0x10260000 /*IOBASE_SCHEDULE*/ - -#define RTL8712_IOBASE_TRXDMA 0x10270000 /*IOBASE_TRXDMA*/ -#define RTL8712_IOBASE_TXLLT 0x10280000 /*IOBASE_TXLLT*/ -#define RTL8712_IOBASE_WMAC 0x10290000 /*IOBASE_WMAC*/ -#define RTL8712_IOBASE_FW2HW 0x102A0000 /*IOBASE_FW2HW*/ -#define RTL8712_IOBASE_ACCESS_PHYREG 0x102B0000 /*IOBASE_ACCESS_PHYREG*/ - -#define RTL8712_IOBASE_FF 0x10300000 /*IOBASE_FIFO 0x1031000~0x103AFFFF*/ - -/*IOREG Offset for 8712*/ -#define RTL8712_SYSCFG_ RTL8712_IOBASE_IOREG -#define RTL8712_CMDCTRL_ (RTL8712_IOBASE_IOREG + 0x40) -#define RTL8712_MACIDSETTING_ (RTL8712_IOBASE_IOREG + 0x50) -#define RTL8712_TIMECTRL_ (RTL8712_IOBASE_IOREG + 0x80) -#define RTL8712_FIFOCTRL_ (RTL8712_IOBASE_IOREG + 0xA0) -#define RTL8712_RATECTRL_ (RTL8712_IOBASE_IOREG + 0x160) -#define RTL8712_EDCASETTING_ (RTL8712_IOBASE_IOREG + 0x1D0) -#define RTL8712_WMAC_ (RTL8712_IOBASE_IOREG + 0x200) -#define RTL8712_SECURITY_ (RTL8712_IOBASE_IOREG + 0x240) -#define RTL8712_POWERSAVE_ (RTL8712_IOBASE_IOREG + 0x260) -#define RTL8712_GP_ (RTL8712_IOBASE_IOREG + 0x2E0) -#define RTL8712_INTERRUPT_ (RTL8712_IOBASE_IOREG + 0x300) -#define RTL8712_DEBUGCTRL_ (RTL8712_IOBASE_IOREG + 0x310) -#define RTL8712_OFFLOAD_ (RTL8712_IOBASE_IOREG + 0x2D0) - -/*FIFO for 8712*/ -#define RTL8712_DMA_BCNQ (RTL8712_IOBASE_FF + 0x10000) -#define RTL8712_DMA_MGTQ (RTL8712_IOBASE_FF + 0x20000) -#define RTL8712_DMA_BMCQ (RTL8712_IOBASE_FF + 0x30000) -#define RTL8712_DMA_VOQ (RTL8712_IOBASE_FF + 0x40000) -#define RTL8712_DMA_VIQ (RTL8712_IOBASE_FF + 0x50000) -#define RTL8712_DMA_BEQ (RTL8712_IOBASE_FF + 0x60000) -#define RTL8712_DMA_BKQ (RTL8712_IOBASE_FF + 0x70000) -#define RTL8712_DMA_RX0FF (RTL8712_IOBASE_FF + 0x80000) -#define RTL8712_DMA_H2CCMD (RTL8712_IOBASE_FF + 0x90000) -#define RTL8712_DMA_C2HCMD (RTL8712_IOBASE_FF + 0xA0000) - -/*------------------------------*/ - -/*BIT 16 15*/ -#define DID_SDIO_LOCAL 0 /* 0 0*/ -#define DID_WLAN_IOREG 1 /* 0 1*/ -#define DID_WLAN_FIFO 3 /* 1 1*/ -#define DID_UNDEFINE (-1) - -#define CMD_ADDR_MAPPING_SHIFT 2 /*SDIO CMD ADDR MAPPING, - *shift 2 bit for match - * offset[14:2] - */ - -/*Offset for SDIO LOCAL*/ -#define OFFSET_SDIO_LOCAL 0x0FFF - -/*Offset for WLAN IOREG*/ -#define OFFSET_WLAN_IOREG 0x0FFF - -/*Offset for WLAN FIFO*/ -#define OFFSET_TX_BCNQ 0x0300 -#define OFFSET_TX_HIQ 0x0310 -#define OFFSET_TX_CMDQ 0x0320 -#define OFFSET_TX_MGTQ 0x0330 -#define OFFSET_TX_HCCAQ 0x0340 -#define OFFSET_TX_VOQ 0x0350 -#define OFFSET_TX_VIQ 0x0360 -#define OFFSET_TX_BEQ 0x0370 -#define OFFSET_TX_BKQ 0x0380 -#define OFFSET_RX_RX0FFQ 0x0390 -#define OFFSET_RX_C2HFFQ 0x03A0 - -#define BK_QID_01 1 -#define BK_QID_02 2 -#define BE_QID_01 0 -#define BE_QID_02 3 -#define VI_QID_01 4 -#define VI_QID_02 5 -#define VO_QID_01 6 -#define VO_QID_02 7 -#define HCCA_QID_01 8 -#define HCCA_QID_02 9 -#define HCCA_QID_03 10 -#define HCCA_QID_04 11 -#define HCCA_QID_05 12 -#define HCCA_QID_06 13 -#define HCCA_QID_07 14 -#define HCCA_QID_08 15 -#define HI_QID 17 -#define CMD_QID 19 -#define MGT_QID 18 -#define BCN_QID 16 - -#include "rtl8712_regdef.h" - -#include "rtl8712_bitdef.h" - -#include "basic_types.h" - -#endif /* __RTL8712_SPEC_H__ */ - diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h deleted file mode 100644 index d92df3fbd2b193c89d6b51e0311792d5523f8e42..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h +++ /dev/null @@ -1,163 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_SYSCFG_BITDEF_H__ -#define __RTL8712_SYSCFG_BITDEF_H__ - -/*SYS_PWR_CTRL*/ -/*SRCTRL0*/ -/*SRCTRL1*/ -/*SYS_CLKR*/ - -/*SYS_IOS_CTRL*/ -#define iso_LDR2RP_SHT 8 /* EE Loader to Retention Path*/ -#define iso_LDR2RP BIT(iso_LDR2RP_SHT) /* 1:isolation, 0:attach*/ - -/*SYS_CTRL*/ -#define FEN_DIO_SDIO_SHT 0 -#define FEN_DIO_SDIO BIT(FEN_DIO_SDIO_SHT) -#define FEN_SDIO_SHT 1 -#define FEN_SDIO BIT(FEN_SDIO_SHT) -#define FEN_USBA_SHT 2 -#define FEN_USBA BIT(FEN_USBA_SHT) -#define FEN_UPLL_SHT 3 -#define FEN_UPLL BIT(FEN_UPLL_SHT) -#define FEN_USBD_SHT 4 -#define FEN_USBD BIT(FEN_USBD_SHT) -#define FEN_DIO_PCIE_SHT 5 -#define FEN_DIO_PCIE BIT(FEN_DIO_PCIE_SHT) -#define FEN_PCIEA_SHT 6 -#define FEN_PCIEA BIT(FEN_PCIEA_SHT) -#define FEN_PPLL_SHT 7 -#define FEN_PPLL BIT(FEN_PPLL_SHT) -#define FEN_PCIED_SHT 8 -#define FEN_PCIED BIT(FEN_PCIED_SHT) -#define FEN_CPUEN_SHT 10 -#define FEN_CPUEN BIT(FEN_CPUEN_SHT) -#define FEN_DCORE_SHT 11 -#define FEN_DCORE BIT(FEN_DCORE_SHT) -#define FEN_ELDR_SHT 12 -#define FEN_ELDR BIT(FEN_ELDR_SHT) -#define PWC_DV2LDR_SHT 13 -#define PWC_DV2LDR BIT(PWC_DV2LDR_SHT) /* Loader Power Enable*/ - -/*=== SYS_CLKR ===*/ -#define SYS_CLKSEL_SHT 0 -#define SYS_CLKSEL BIT(SYS_CLKSEL_SHT) /* System Clock 80MHz*/ -#define PS_CLKSEL_SHT 1 -#define PS_CLKSEL BIT(PS_CLKSEL_SHT) /*System power save - * clock select. - */ -#define CPU_CLKSEL_SHT 2 -#define CPU_CLKSEL BIT(CPU_CLKSEL_SHT) /* System Clock select, - * 1: AFE source, - * 0: System clock(L-Bus) - */ -#define INT32K_EN_SHT 3 -#define INT32K_EN BIT(INT32K_EN_SHT) -#define MACSLP_SHT 4 -#define MACSLP BIT(MACSLP_SHT) -#define MAC_CLK_EN_SHT 11 -#define MAC_CLK_EN BIT(MAC_CLK_EN_SHT) /* MAC Clock Enable.*/ -#define SYS_CLK_EN_SHT 12 -#define SYS_CLK_EN BIT(SYS_CLK_EN_SHT) -#define RING_CLK_EN_SHT 13 -#define RING_CLK_EN BIT(RING_CLK_EN_SHT) -#define SWHW_SEL_SHT 14 -#define SWHW_SEL BIT(SWHW_SEL_SHT) /* Load done, - * control path switch. - */ -#define FWHW_SEL_SHT 15 -#define FWHW_SEL BIT(FWHW_SEL_SHT) /* Sleep exit, - * control path switch. - */ - -/*9346CR*/ -#define _VPDIDX_MSK 0xFF00 -#define _VPDIDX_SHT 8 -#define _EEM_MSK 0x00C0 -#define _EEM_SHT 6 -#define _EEM0 BIT(6) -#define _EEM1 BIT(7) -#define _EEPROM_EN BIT(5) -#define _9356SEL BIT(4) -#define _EECS BIT(3) -#define _EESK BIT(2) -#define _EEDI BIT(1) -#define _EEDO BIT(0) - -/*AFE_MISC*/ -#define AFE_MISC_USB_MBEN_SHT 7 -#define AFE_MISC_USB_MBEN BIT(AFE_MISC_USB_MBEN_SHT) -#define AFE_MISC_USB_BGEN_SHT 6 -#define AFE_MISC_USB_BGEN BIT(AFE_MISC_USB_BGEN_SHT) -#define AFE_MISC_LD12_VDAJ_SHT 4 -#define AFE_MISC_LD12_VDAJ_MSK 0X0030 -#define AFE_MISC_LD12_VDAJ BIT(AFE_MISC_LD12_VDAJ_SHT) -#define AFE_MISC_I32_EN_SHT 3 -#define AFE_MISC_I32_EN BIT(AFE_MISC_I32_EN_SHT) -#define AFE_MISC_E32_EN_SHT 2 -#define AFE_MISC_E32_EN BIT(AFE_MISC_E32_EN_SHT) -#define AFE_MISC_MBEN_SHT 1 -#define AFE_MISC_MBEN BIT(AFE_MISC_MBEN_SHT)/* Enable AFE Macro - * Block's Mbias. - */ -#define AFE_MISC_BGEN_SHT 0 -#define AFE_MISC_BGEN BIT(AFE_MISC_BGEN_SHT)/* Enable AFE Macro - * Block's Bandgap. - */ - -/*--------------------------------------------------------------------------*/ -/* SPS1_CTRL bits (Offset 0x18-1E, 56bits)*/ -/*--------------------------------------------------------------------------*/ -#define SPS1_SWEN BIT(1) /* Enable vsps18 SW Macro Block.*/ -#define SPS1_LDEN BIT(0) /* Enable VSPS12 LDO Macro block.*/ - -/*----------------------------------------------------------------------------*/ -/* LDOA15_CTRL bits (Offset 0x20, 8bits)*/ -/*----------------------------------------------------------------------------*/ -#define LDA15_EN BIT(0) /* Enable LDOA15 Macro Block*/ - -/*----------------------------------------------------------------------------*/ -/* 8192S LDOV12D_CTRL bit (Offset 0x21, 8bits)*/ -/*----------------------------------------------------------------------------*/ -#define LDV12_EN BIT(0) /* Enable LDOVD12 Macro Block*/ -#define LDV12_SDBY BIT(1) /* LDOVD12 standby mode*/ - -/*CLK_PS_CTRL*/ -#define _CLK_GATE_EN BIT(0) - -/* EFUSE_CTRL*/ -#define EF_FLAG BIT(31) /* Access Flag, Write:1; - * Read:0 - */ -#define EF_PGPD 0x70000000 /* E-fuse Program time*/ -#define EF_RDT 0x0F000000 /* E-fuse read time: in the - * unit of cycle time - */ -#define EF_PDN_EN BIT(19) /* EFuse Power down enable*/ -#define ALD_EN BIT(18) /* Autoload Enable*/ -#define EF_ADDR 0x0003FF00 /* Access Address*/ -#define EF_DATA 0x000000FF /* Access Data*/ - -/* EFUSE_TEST*/ -#define LDOE25_EN BIT(31) /* Enable LDOE25 Macro Block*/ - -/* EFUSE_CLK_CTRL*/ -#define EFUSE_CLK_EN BIT(1) /* E-Fuse Clock Enable*/ -#define EFUSE_CLK_SEL BIT(0) /* E-Fuse Clock Select, - * 0:500K, 1:40M - */ - -#endif /*__RTL8712_SYSCFG_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h deleted file mode 100644 index da5efcdedabe2f091fee39cb104b086539264185..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_SYSCFG_REGDEF_H__ -#define __RTL8712_SYSCFG_REGDEF_H__ - -#define SYS_ISO_CTRL (RTL8712_SYSCFG_ + 0x0000) -#define SYS_FUNC_EN (RTL8712_SYSCFG_ + 0x0002) -#define PMC_FSM (RTL8712_SYSCFG_ + 0x0004) -#define SYS_CLKR (RTL8712_SYSCFG_ + 0x0008) -#define EE_9346CR (RTL8712_SYSCFG_ + 0x000A) -#define EE_VPD (RTL8712_SYSCFG_ + 0x000C) -#define AFE_MISC (RTL8712_SYSCFG_ + 0x0010) -#define SPS0_CTRL (RTL8712_SYSCFG_ + 0x0011) -#define SPS1_CTRL (RTL8712_SYSCFG_ + 0x0018) -#define RF_CTRL (RTL8712_SYSCFG_ + 0x001F) -#define LDOA15_CTRL (RTL8712_SYSCFG_ + 0x0020) -#define LDOV12D_CTRL (RTL8712_SYSCFG_ + 0x0021) -#define LDOHCI12_CTRL (RTL8712_SYSCFG_ + 0x0022) -#define LDO_USB_CTRL (RTL8712_SYSCFG_ + 0x0023) -#define LPLDO_CTRL (RTL8712_SYSCFG_ + 0x0024) -#define AFE_XTAL_CTRL (RTL8712_SYSCFG_ + 0x0026) -#define AFE_PLL_CTRL (RTL8712_SYSCFG_ + 0x0028) -#define EFUSE_CTRL (RTL8712_SYSCFG_ + 0x0030) -#define EFUSE_TEST (RTL8712_SYSCFG_ + 0x0034) -#define PWR_DATA (RTL8712_SYSCFG_ + 0x0038) -#define DPS_TIMER (RTL8712_SYSCFG_ + 0x003C) -#define RCLK_MON (RTL8712_SYSCFG_ + 0x003E) -#define EFUSE_CLK_CTRL (RTL8712_SYSCFG_ + 0x02F8) - -#endif /*__RTL8712_SYSCFG_REGDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h deleted file mode 100644 index d7bc9dd5cecd21d7d6c53b398ecb38b979edc77d..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_TIMECTRL_BITDEF_H__ -#define __RTL8712_TIMECTRL_BITDEF_H__ - -/*TSFTR*/ -/*SLOT*/ -/*USTIME*/ - -/*TUBASE*/ -#define _TUBASE_MSK 0x07FF - -/*SIFS_CCK*/ -#define _SIFS_CCK_TRX_MSK 0xFF00 -#define _SIFS_CCK_TRX_SHT 0x8 -#define _SIFS_CCK_CTX_MSK 0x00FF -#define _SIFS_CCK_CTX_SHT 0 - -/*SIFS_OFDM*/ -#define _SIFS_OFDM_TRX_MSK 0xFF00 -#define _SIFS_OFDM_TRX_SHT 0x8 -#define _SIFS_OFDM_CTX_MSK 0x00FF -#define _SIFS_OFDM_CTX_SHT 0 - -/*PIFS*/ -/*ACKTO*/ -/*EIFS*/ -/*BCNITV*/ -/*ATIMWND*/ - -/*DRVERLYINT*/ -#define _ENSWBCN BIT(15) -#define _DRVERLY_TU_MSK 0x0FF0 -#define _DRVERLY_TU_SHT 4 -#define _DRVERLY_US_MSK 0x000F -#define _DRVERLY_US_SHT 0 - -/*BCNDMATIM*/ -#define _BCNDMATIM_MSK 0x03FF - -/*BCNERRTH*/ -/*MLT*/ - -#endif /* __RTL8712_TIMECTRL_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h deleted file mode 100644 index b51603f1b880044a3ba7b6423b8877030d185374..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL8712_TIMECTRL_REGDEF_H__ -#define __RTL8712_TIMECTRL_REGDEF_H__ - -#define TSFTR (RTL8712_TIMECTRL_ + 0x00) -#define USTIME (RTL8712_TIMECTRL_ + 0x08) -#define SLOT (RTL8712_TIMECTRL_ + 0x09) -#define TUBASE (RTL8712_TIMECTRL_ + 0x0A) -#define SIFS_CCK (RTL8712_TIMECTRL_ + 0x0C) -#define SIFS_OFDM (RTL8712_TIMECTRL_ + 0x0E) -#define PIFS (RTL8712_TIMECTRL_ + 0x10) -#define ACKTO (RTL8712_TIMECTRL_ + 0x11) -#define EIFS (RTL8712_TIMECTRL_ + 0x12) -#define BCNITV (RTL8712_TIMECTRL_ + 0x14) -#define ATIMWND (RTL8712_TIMECTRL_ + 0x16) -#define DRVERLYINT (RTL8712_TIMECTRL_ + 0x18) -#define BCNDMATIM (RTL8712_TIMECTRL_ + 0x1A) -#define BCNERRTH (RTL8712_TIMECTRL_ + 0x1C) -#define MLT (RTL8712_TIMECTRL_ + 0x1D) - -#endif /* __RTL8712_TIMECTRL_REGDEF_H__ */ diff --git a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h b/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h deleted file mode 100644 index ea164e48234766798d11c1bf2d0e89397d4c286c..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_WMAC_BITDEF_H__ -#define __RTL8712_WMAC_BITDEF_H__ - -/*NAVCTRL*/ -#define _NAV_UPPER_EN BIT(18) -#define _NAV_MTO_EN BIT(17) -#define _NAV_UPPER BIT(16) -#define _NAV_MTO_MSK 0xFF00 -#define _NAV_MTO_SHT 8 -#define _RTSRST_MSK 0x00FF -#define _RTSRST_SHT 0 - -/*BWOPMODE*/ -#define _20MHZBW BIT(2) - -/*BACAMCMD*/ -#define _BACAM_POLL BIT(31) -#define _BACAM_RST BIT(17) -#define _BACAM_RW BIT(16) -#define _BACAM_ADDR_MSK 0x0000007F -#define _BACAM_ADDR_SHT 0 - -/*LBDLY*/ -#define _LBDLY_MSK 0x1F - -/*FWDLY*/ -#define _FWDLY_MSK 0x0F - -/*RXERR_RPT*/ -#define _RXERR_RPT_SEL_MSK 0xF0000000 -#define _RXERR_RPT_SEL_SHT 28 -#define _RPT_CNT_MSK 0x000FFFFF -#define _RPT_CNT_SHT 0 - -#endif /*__RTL8712_WMAC_BITDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h b/drivers/staging/rtl8712/rtl8712_wmac_regdef.h deleted file mode 100644 index dfe3e9fbed4313ff370c4c924c9742533ef91ab6..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_WMAC_REGDEF_H__ -#define __RTL8712_WMAC_REGDEF_H__ - -#define NAVCTRL (RTL8712_WMAC_ + 0x00) -#define BWOPMODE (RTL8712_WMAC_ + 0x03) -#define BACAMCMD (RTL8712_WMAC_ + 0x04) -#define BACAMCONTENT (RTL8712_WMAC_ + 0x08) -#define LBDLY (RTL8712_WMAC_ + 0x10) -#define FWDLY (RTL8712_WMAC_ + 0x11) -#define HWPC_RX_CTRL (RTL8712_WMAC_ + 0x18) -#define MQ (RTL8712_WMAC_ + 0x20) -#define MA (RTL8712_WMAC_ + 0x22) -#define MS (RTL8712_WMAC_ + 0x24) -#define CLM_RESULT (RTL8712_WMAC_ + 0x27) -#define NHM_RPI_CNT (RTL8712_WMAC_ + 0x28) -#define RXERR_RPT (RTL8712_WMAC_ + 0x30) -#define NAV_PROT_LEN (RTL8712_WMAC_ + 0x34) -#define CFEND_TH (RTL8712_WMAC_ + 0x36) -#define AMPDU_MIN_SPACE (RTL8712_WMAC_ + 0x37) -#define TXOP_STALL_CTRL (RTL8712_WMAC_ + 0x38) - -#endif /*__RTL8712_WMAC_REGDEF_H__*/ - diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c deleted file mode 100644 index 12f2fdb1b3cbcc7c984e9eb2643e0972eed79184..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ /dev/null @@ -1,732 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl8712_xmit.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL8712_XMIT_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wifi.h" -#include "osdep_intf.h" -#include "usb_ops.h" - -static void dump_xframe(struct _adapter *padapter, - struct xmit_frame *pxmitframe); -static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz); - -sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag) -{ - phw_txqueue->ac_tag = ac_tag; - switch (ac_tag) { - case BE_QUEUE_INX: - phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ; - break; - case BK_QUEUE_INX: - phw_txqueue->ff_hwaddr = RTL8712_DMA_BKQ; - break; - case VI_QUEUE_INX: - phw_txqueue->ff_hwaddr = RTL8712_DMA_VIQ; - break; - case VO_QUEUE_INX: - phw_txqueue->ff_hwaddr = RTL8712_DMA_VOQ; - break; - case BMC_QUEUE_INX: - phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ; - break; - } - return _SUCCESS; -} - -int r8712_txframes_sta_ac_pending(struct _adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - int priority = pattrib->priority; - - psta = pattrib->psta; - switch (priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - break; - } - return ptxservq->qcnt; -} - -static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe) -{ - u32 addr = 0; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct _adapter *padapter = pxmitframe->padapter; - struct dvobj_priv *pdvobj = &padapter->dvobjpriv; - - if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { - addr = RTL8712_DMA_H2CCMD; - } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { - addr = RTL8712_DMA_MGTQ; - } else if (pdvobj->nr_endpoint == 6) { - switch (pattrib->priority) { - case 0: - case 3: - addr = RTL8712_DMA_BEQ; - break; - case 1: - case 2: - addr = RTL8712_DMA_BKQ; - break; - case 4: - case 5: - addr = RTL8712_DMA_VIQ; - break; - case 6: - case 7: - addr = RTL8712_DMA_VOQ; - break; - case 0x10: - case 0x11: - case 0x12: - case 0x13: - addr = RTL8712_DMA_H2CCMD; - break; - default: - addr = RTL8712_DMA_BEQ; - break; - } - } else if (pdvobj->nr_endpoint == 4) { - switch (pattrib->qsel) { - case 0: - case 3: - case 1: - case 2: - addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/ - break; - case 4: - case 5: - case 6: - case 7: - addr = RTL8712_DMA_VOQ;/*RTL8712_EP_HI;*/ - break; - case 0x10: - case 0x11: - case 0x12: - case 0x13: - addr = RTL8712_DMA_H2CCMD; - break; - default: - addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/ - break; - } - } - return addr; -} - -static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, - struct hw_xmit *phwxmit, struct tx_servq *ptxservq, - struct __queue *pframe_queue) -{ - struct list_head *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - - xmitframe_phead = &pframe_queue->queue; - xmitframe_plist = xmitframe_phead->next; - if (!end_of_queue_search(xmitframe_phead, xmitframe_plist)) { - pxmitframe = container_of(xmitframe_plist, - struct xmit_frame, list); - list_del_init(&pxmitframe->list); - ptxservq->qcnt--; - phwxmit->txcmdcnt++; - } - return pxmitframe; -} - -static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv, - struct hw_xmit *phwxmit_i, sint entry) -{ - unsigned long irqL0; - struct list_head *sta_plist, *sta_phead; - struct hw_xmit *phwxmit; - struct tx_servq *ptxservq = NULL; - struct __queue *pframe_queue = NULL; - struct xmit_frame *pxmitframe = NULL; - int i, inx[4]; - int j, acirp_cnt[4]; - - /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/ - inx[0] = 0; acirp_cnt[0] = pxmitpriv->voq_cnt; - inx[1] = 1; acirp_cnt[1] = pxmitpriv->viq_cnt; - inx[2] = 2; acirp_cnt[2] = pxmitpriv->beq_cnt; - inx[3] = 3; acirp_cnt[3] = pxmitpriv->bkq_cnt; - for (i = 0; i < 4; i++) { - for (j = i + 1; j < 4; j++) { - if (acirp_cnt[j] < acirp_cnt[i]) { - swap(acirp_cnt[i], acirp_cnt[j]); - swap(inx[i], inx[j]); - } - } - } - spin_lock_irqsave(&pxmitpriv->lock, irqL0); - for (i = 0; i < entry; i++) { - phwxmit = phwxmit_i + inx[i]; - sta_phead = &phwxmit->sta_queue->queue; - sta_plist = sta_phead->next; - while (!end_of_queue_search(sta_phead, sta_plist)) { - ptxservq = container_of(sta_plist, struct tx_servq, tx_pending); - pframe_queue = &ptxservq->sta_pending; - pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, - pframe_queue); - if (pxmitframe) { - phwxmit->accnt--; - goto exit_dequeue_xframe_ex; - } - sta_plist = sta_plist->next; - /*Remove sta node when there are no pending packets.*/ - if (list_empty(&pframe_queue->queue)) { - /* must be done after sta_plist->next - * and before break - */ - list_del_init(&ptxservq->tx_pending); - } - } - } -exit_dequeue_xframe_ex: - spin_unlock_irqrestore(&pxmitpriv->lock, irqL0); - return pxmitframe; -} - -void r8712_do_queue_select(struct _adapter *padapter, struct pkt_attrib *pattrib) -{ - unsigned int qsel = 0; - struct dvobj_priv *pdvobj = &padapter->dvobjpriv; - - if (pdvobj->nr_endpoint == 6) { - qsel = (unsigned int)pattrib->priority; - } else if (pdvobj->nr_endpoint == 4) { - qsel = (unsigned int)pattrib->priority; - if (qsel == 0 || qsel == 3) - qsel = 3; - else if (qsel == 1 || qsel == 2) - qsel = 1; - else if (qsel == 4 || qsel == 5) - qsel = 5; - else if (qsel == 6 || qsel == 7) - qsel = 7; - else - qsel = 3; - } - pattrib->qsel = qsel; -} - -#ifdef CONFIG_R8712_TX_AGGR -void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) -{ - struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; - - /* Fill up TxCmd Descriptor according as USB FW Tx Aggregation info.*/ - /* dw0 */ - ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff); - ptx_desc->txdw0 |= - cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & - 0x00ff0000); - ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - - /* dw1 */ - ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); -} - -void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) -{ - struct xmit_frame *pxmitframe = (struct xmit_frame *) - pxmitbuf->priv_data; - struct _adapter *padapter = pxmitframe->padapter; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) - (pxmitbuf->pbuf + TXDESC_SIZE); - - /* Fill up Cmd Header for USB FW Tx Aggregation.*/ - /* dw0 */ - pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | - (pcmdpriv->cmd_seq << 24)); - pcmdpriv->cmd_seq++; -} - -void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) -{ - struct _adapter *padapter = pxmitframe->padapter; - struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; - int last_txcmdsz = 0; - int padding_sz = 0; - - /* 802.3->802.11 converter */ - r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); - /* free skb struct */ - r8712_xmit_complete(padapter, pxmitframe); - if (pxmitframe->attrib.ether_type != 0x0806) { - if ((pxmitframe->attrib.ether_type != 0x888e) && - (pxmitframe->attrib.dhcp_pkt != 1)) { - r8712_issue_addbareq_cmd(padapter, pxmitframe->attrib.priority); - } - } - pxmitframe->last[0] = 1; - update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), pxmitframe->attrib.last_txcmdsz); - /*padding zero */ - last_txcmdsz = pxmitframe->attrib.last_txcmdsz; - padding_sz = (8 - (last_txcmdsz % 8)); - if ((last_txcmdsz % 8) != 0) { - int i; - - for (i = 0; i < padding_sz; i++) - *(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz + - i) = 0; - } - /* Add the new mpdu's length */ - ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) | - ((ptx_desc->txdw0 & 0x0000ffff) + - ((TXDESC_SIZE + last_txcmdsz + padding_sz) & - 0x0000ffff))); -} - -void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) -{ - /* linux complete context doesn't need to protect */ - pxmitframe->pxmitbuf = pxmitbuf; - pxmitbuf->priv_data = pxmitframe; - pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; - /* buffer addr assoc */ - pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ; - /*RTL8712_DMA_H2CCMD */ - r8712_construct_txaggr_cmd_desc(pxmitbuf); - r8712_construct_txaggr_cmd_hdr(pxmitbuf); - r8712_append_mpdu_unit(pxmitbuf, pxmitframe); - pxmitbuf->aggr_nr = 1; -} - -u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, struct xmit_frame *pxmitframe) -{ - pxmitframe->pxmitbuf = pxmitbuf; - pxmitbuf->priv_data = pxmitframe; - pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; - /* buffer addr assoc */ - pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + - (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); - r8712_append_mpdu_unit(pxmitbuf, pxmitframe); - r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, - pxmitframe); - pxmitbuf->aggr_nr++; - - return TXDESC_SIZE + - (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); -} - -void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) -{ - struct _adapter *padapter = pxmitframe->padapter; - struct dvobj_priv *pdvobj = &padapter->dvobjpriv; - struct tx_desc *ptxdesc = pxmitbuf->pbuf; - struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) - (pxmitbuf->pbuf + TXDESC_SIZE); - u16 total_length = (u16)(ptxdesc->txdw0 & 0xffff); - - /* use 1st xmitframe as media */ - xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); - pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) & - 0x0000ffff) | (pcmd_hdr->cmd_dw0 & - 0xffff0000)); - - /* urb length in cmd_dw1 */ - pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff) | - ((total_length + TXDESC_SIZE) << 16)); - pxmitframe->last[0] = 1; - pxmitframe->bpending[0] = false; - pxmitframe->mem_addr = pxmitbuf->pbuf; - - if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) == 0) || - ((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % - 0x40) == 0))) { - ptxdesc->txdw0 |= cpu_to_le32 - (((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) & - 0x00ff0000); - /*32 bytes for TX Desc + 8 bytes pending*/ - } else { - ptxdesc->txdw0 |= cpu_to_le32 - (((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & - 0x00ff0000); - /*default = 32 bytes for TX Desc*/ - } - r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, total_length + TXDESC_SIZE, - (u8 *)pxmitframe); -} - -#endif - -static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) -{ - uint qsel; - struct _adapter *padapter = pxmitframe->padapter; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct tx_desc *ptxdesc = (struct tx_desc *)pmem; - struct dvobj_priv *pdvobj = &padapter->dvobjpriv; -#ifdef CONFIG_R8712_TX_AGGR - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; -#endif - u8 blnSetTxDescOffset; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct tx_desc txdesc_mp; - - memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc)); - memset(ptxdesc, 0, sizeof(struct tx_desc)); - /* offset 0 */ - ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff); - if (pdvobj->ishighspeed) { - if (((sz + TXDESC_SIZE) % 512) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } else { - if (((sz + TXDESC_SIZE) % 64) == 0) - blnSetTxDescOffset = 1; - else - blnSetTxDescOffset = 0; - } - if (blnSetTxDescOffset) { - /* 32 bytes for TX Desc + 8 bytes pending */ - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ + 8) << - OFFSET_SHT) & 0x00ff0000); - } else { - /* default = 32 bytes for TX Desc */ - ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << - OFFSET_SHT) & 0x00ff0000); - } - ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - /* offset 4 */ - ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x1f); - -#ifdef CONFIG_R8712_TX_AGGR - /* dirty workaround, need to check if it is aggr cmd. */ - if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) { - ptxdesc->txdw0 |= cpu_to_le32 - ((0x3 << TYPE_SHT) & TYPE_MSK); - qsel = (uint)(pattrib->qsel & 0x0000001f); - if (qsel == 2) - qsel = 0; - ptxdesc->txdw1 |= cpu_to_le32 - ((qsel << QSEL_SHT) & 0x00001f00); - ptxdesc->txdw2 = cpu_to_le32 - ((qsel << RTS_RC_SHT) & 0x001f0000); - ptxdesc->txdw6 |= cpu_to_le32 - ((0x5 << RSVD6_SHT) & RSVD6_MSK); - } else { - ptxdesc->txdw0 |= cpu_to_le32 - ((0x3 << TYPE_SHT) & TYPE_MSK); - ptxdesc->txdw1 |= cpu_to_le32 - ((0x13 << QSEL_SHT) & 0x00001f00); - qsel = (uint)(pattrib->qsel & 0x0000001f); - if (qsel == 2) - qsel = 0; - ptxdesc->txdw2 = cpu_to_le32 - ((qsel << RTS_RC_SHT) & 0x0001f000); - ptxdesc->txdw7 |= cpu_to_le32 - (pcmdpriv->cmd_seq << 24); - pcmdpriv->cmd_seq++; - } - pattrib->qsel = 0x13; -#else - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); -#endif - if (!pqospriv->qos_option) - ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/ - if ((pattrib->encrypt > 0) && !pattrib->bswenc) { - switch (pattrib->encrypt) { /*SEC_TYPE*/ - case _WEP40_: - case _WEP104_: - ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) & - 0x00c00000); - /*KEY_ID when WEP is used;*/ - ptxdesc->txdw1 |= - cpu_to_le32((psecuritypriv->PrivacyKeyIndex << 17) & - 0x00060000); - break; - case _TKIP_: - case _TKIP_WTMIC_: - ptxdesc->txdw1 |= cpu_to_le32((0x02 << 22) & - 0x00c00000); - break; - case _AES_: - ptxdesc->txdw1 |= cpu_to_le32((0x03 << 22) & - 0x00c00000); - break; - case _NO_PRIVACY_: - default: - break; - } - } - /*offset 8*/ - if (bmcst) - ptxdesc->txdw2 |= cpu_to_le32(BMC); - - /*offset 12*/ - /* f/w will increase the seqnum by itself, driver pass the - * correct priority to fw. - * fw will check the correct priority for increasing the - * seqnum per tid. about usb using 4-endpoint, qsel points out - * the correct mapping between AC&Endpoint, - * the purpose is that correct mapping lets the MAC release - * the AC Queue list correctly. - */ - ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & - 0x0fff0000); - if ((pattrib->ether_type != 0x888e) && - (pattrib->ether_type != 0x0806) && - (pattrib->dhcp_pkt != 1)) { - /*Not EAP & ARP type data packet*/ - if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ - if (!phtpriv->ampdu_enable) - ptxdesc->txdw2 |= cpu_to_le32(BK); - } - } else { - /* EAP data packet and ARP packet. - * Use the 1M data rate to send the EAP/ARP packet. - * This will maybe make the handshake smooth. - */ - /*driver uses data rate*/ - ptxdesc->txdw4 = cpu_to_le32(0x80000000); - ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/*1M*/ - } - if (pattrib->pctrl == 1) { /* mp tx packets */ - struct tx_desc *ptxdesc_mp; - - ptxdesc_mp = &txdesc_mp; - /* offset 8 */ - ptxdesc->txdw2 = ptxdesc_mp->txdw2; - if (bmcst) - ptxdesc->txdw2 |= cpu_to_le32(BMC); - ptxdesc->txdw2 |= cpu_to_le32(BK); - /* offset 16 */ - ptxdesc->txdw4 = ptxdesc_mp->txdw4; - /* offset 20 */ - ptxdesc->txdw5 = ptxdesc_mp->txdw5; - pattrib->pctrl = 0;/* reset to zero; */ - } - } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { - /* offset 4 */ - /* CAM_ID(MAC_ID), default=5; */ - ptxdesc->txdw1 |= cpu_to_le32((0x05) & 0x1f); - qsel = (uint)(pattrib->qsel & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */ - /* offset 8 */ - if (bmcst) - ptxdesc->txdw2 |= cpu_to_le32(BMC); - /* offset 12 */ - /* f/w will increase the seqnum by itself, driver pass the - * correct priority to fw. - * fw will check the correct priority for increasing the seqnum - * per tid. about usb using 4-endpoint, qsel points out the - * correct mapping between AC&Endpoint, - * the purpose is that correct mapping let the MAC releases - * the AC Queue list correctly. - */ - ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & - 0x0fff0000); - /* offset 16 */ - ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/ - /* offset 20 */ - ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/* gtest 1M */ - } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { - /* offset 4 */ - qsel = 0x13; - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - } else { - /* offset 4 */ - qsel = (uint)(pattrib->priority & 0x0000001f); - ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); - /*offset 8*/ - /*offset 12*/ - ptxdesc->txdw3 = cpu_to_le32((pattrib->seqnum << SEQ_SHT) & - 0x0fff0000); - /*offset 16*/ - ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/ - /*offset 20*/ - ptxdesc->txdw5 = cpu_to_le32(0x001f9600);/*gtest*/ - } -} - -int r8712_xmitframe_complete(struct _adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - struct hw_xmit *phwxmits; - sint hwentry; - struct xmit_frame *pxmitframe = NULL; -#ifdef CONFIG_R8712_TX_AGGR - struct xmit_frame *p2ndxmitframe = NULL; -#else - int res = _SUCCESS; -#endif - - phwxmits = pxmitpriv->hwxmits; - hwentry = pxmitpriv->hwxmit_entry; - if (!pxmitbuf) { - pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); - if (!pxmitbuf) - return false; -#ifdef CONFIG_R8712_TX_AGGR - pxmitbuf->aggr_nr = 0; -#endif - } - /* 1st frame dequeued */ - pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); - /* need to remember the 1st frame */ - if (pxmitframe) { -#ifdef CONFIG_R8712_TX_AGGR - /* 1. dequeue 2nd frame - * 2. aggr if 2nd xframe is dequeued, else dump directly - */ - if (AGGR_NR_HIGH_BOUND > 1) - p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); - if (pxmitframe->frame_tag != DATA_FRAMETAG) { - r8712_free_xmitbuf(pxmitpriv, pxmitbuf); - return false; - } - if (p2ndxmitframe) - if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) { - r8712_free_xmitbuf(pxmitpriv, pxmitbuf); - return false; - } - r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe); - if (p2ndxmitframe) { - u16 total_length; - - total_length = r8712_xmitframe_aggr_next(pxmitbuf, p2ndxmitframe); - do { - p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); - if (p2ndxmitframe) - total_length = - r8712_xmitframe_aggr_next(pxmitbuf, p2ndxmitframe); - else - break; - } while (total_length <= 0x1800 && - pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND); - } - if (pxmitbuf->aggr_nr > 0) - r8712_dump_aggr_xframe(pxmitbuf, pxmitframe); - -#else - - xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - if (pxmitframe->attrib.priority <= 15) - res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, - pxmitframe); - /* always return ndis_packet after - * r8712_xmitframe_coalesce - */ - r8712_xmit_complete(padapter, pxmitframe); - } - if (res == _SUCCESS) - dump_xframe(padapter, pxmitframe); - else - r8712_free_xmitframe_ex(pxmitpriv, pxmitframe); -#endif - - } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */ - r8712_free_xmitbuf(pxmitpriv, pxmitbuf); - return false; - } - return true; -} - -static void dump_xframe(struct _adapter *padapter, - struct xmit_frame *pxmitframe) -{ - int t, sz, w_sz; - u8 *mem_addr; - u32 ff_hwaddr; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - if (pxmitframe->attrib.ether_type != 0x0806) { - if (pxmitframe->attrib.ether_type != 0x888e) - r8712_issue_addbareq_cmd(padapter, pattrib->priority); - } - mem_addr = pxmitframe->buf_addr; - for (t = 0; t < pattrib->nr_frags; t++) { - if (t != (pattrib->nr_frags - 1)) { - sz = pxmitpriv->frag_len; - sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : - pattrib->icv_len); - pxmitframe->last[t] = 0; - } else { - sz = pattrib->last_txcmdsz; - pxmitframe->last[t] = 1; - } - update_txdesc(pxmitframe, (uint *)mem_addr, sz); - w_sz = sz + TXDESC_SIZE; - pxmitframe->mem_addr = mem_addr; - pxmitframe->bpending[t] = false; - ff_hwaddr = get_ff_hwaddr(pxmitframe); -#ifdef CONFIG_R8712_TX_AGGR - r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz, - (unsigned char *)pxmitframe); -#else - r8712_write_port(padapter, ff_hwaddr, w_sz, - (unsigned char *)pxmitframe); -#endif - mem_addr += w_sz; - mem_addr = (u8 *)RND4(((addr_t)(mem_addr))); - } -} - -void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) -{ - int res; - - res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); - pxmitframe->pkt = NULL; - if (res == _SUCCESS) - dump_xframe(padapter, pxmitframe); -} - -int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) -{ - if (r8712_xmit_classifier(padapter, pxmitframe)) { - pxmitframe->pkt = NULL; - return _FAIL; - } - return _SUCCESS; -} diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h deleted file mode 100644 index 5cd651a0de75a900d1abadb9b1b987afd70e9d11..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl8712_xmit.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL8712_XMIT_H_ -#define _RTL8712_XMIT_H_ - -#define HWXMIT_ENTRY 4 - -#define VO_QUEUE_INX 0 -#define VI_QUEUE_INX 1 -#define BE_QUEUE_INX 2 -#define BK_QUEUE_INX 3 -#define TS_QUEUE_INX 4 -#define MGT_QUEUE_INX 5 -#define BMC_QUEUE_INX 6 -#define BCN_QUEUE_INX 7 - -#define HW_QUEUE_ENTRY 8 - -#define TXDESC_SIZE 32 -#define TXDESC_OFFSET TXDESC_SIZE - -#define NR_AMSDU_XMITFRAME 8 -#define NR_TXAGG_XMITFRAME 8 - -#define MAX_AMSDU_XMITBUF_SZ 8704 -#define MAX_TXAGG_XMITBUF_SZ 16384 /*16k*/ - -#define tx_cmd tx_desc - -/* - *defined for TX DESC Operation - */ - -#define MAX_TID (15) - -/*OFFSET 0*/ -#define OFFSET_SZ (0) -#define OFFSET_SHT (16) -#define OWN BIT(31) -#define FSG BIT(27) -#define LSG BIT(26) -#define TYPE_SHT (24) -#define TYPE_MSK (0x03000000) - -/*OFFSET 4*/ -#define PKT_OFFSET_SZ (0) -#define QSEL_SHT (8) -#define HWPC BIT(31) - -/*OFFSET 8*/ -#define BMC BIT(7) -#define BK BIT(30) -#define AGG_EN BIT(29) -#define RTS_RC_SHT (16) - -/*OFFSET 12*/ -#define SEQ_SHT (16) - -/*OFFSET 16*/ -#define TXBW BIT(18) - -/*OFFSET 20*/ -#define DISFB BIT(15) -#define RSVD6_MSK (0x00E00000) -#define RSVD6_SHT (21) - -struct tx_desc { - /*DWORD 0*/ - __le32 txdw0; - __le32 txdw1; - __le32 txdw2; - __le32 txdw3; - __le32 txdw4; - __le32 txdw5; - __le32 txdw6; - __le32 txdw7; -}; - -union txdesc { - struct tx_desc txdesc; - unsigned int value[TXDESC_SIZE >> 2]; -}; - -int r8712_xmitframe_complete(struct _adapter *padapter, - struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); -void r8712_do_queue_select(struct _adapter *padapter, - struct pkt_attrib *pattrib); - -#ifdef CONFIG_R8712_TX_AGGR -void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe); -void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe); -#endif - -#endif diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c deleted file mode 100644 index ffeb91dd28c4385733fefa097b4ab91d096483d9..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ /dev/null @@ -1,750 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_cmd.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_CMD_C_ - -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kref.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/usb.h> -#include <linux/usb/ch9.h> -#include <linux/circ_buf.h> -#include <linux/uaccess.h> -#include <asm/byteorder.h> -#include <linux/atomic.h> -#include <linux/semaphore.h> -#include <linux/rtnetlink.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "mlme_osdep.h" - -/* - * Caller and the r8712_cmd_thread can protect cmd_q by spin_lock. - * No irqsave is necessary. - */ - -int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv) -{ - init_completion(&pcmdpriv->cmd_queue_comp); - init_completion(&pcmdpriv->terminate_cmdthread_comp); - - _init_queue(&(pcmdpriv->cmd_queue)); - - /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ - pcmdpriv->cmd_seq = 1; - pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ, - GFP_ATOMIC); - if (!pcmdpriv->cmd_allocated_buf) - return -ENOMEM; - pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - - ((addr_t)(pcmdpriv->cmd_allocated_buf) & - (CMDBUFF_ALIGN_SZ - 1)); - pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC); - if (!pcmdpriv->rsp_allocated_buf) { - kfree(pcmdpriv->cmd_allocated_buf); - pcmdpriv->cmd_allocated_buf = NULL; - return -ENOMEM; - } - pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - - ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3); - pcmdpriv->cmd_issued_cnt = 0; - pcmdpriv->cmd_done_cnt = 0; - pcmdpriv->rsp_cnt = 0; - return 0; -} - -int r8712_init_evt_priv(struct evt_priv *pevtpriv) -{ - /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ - pevtpriv->event_seq = 0; - pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC); - - if (!pevtpriv->evt_allocated_buf) - return -ENOMEM; - pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 - - ((addr_t)(pevtpriv->evt_allocated_buf) & 3); - pevtpriv->evt_done_cnt = 0; - return 0; -} - -void r8712_free_evt_priv(struct evt_priv *pevtpriv) -{ - kfree(pevtpriv->evt_allocated_buf); -} - -void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv) -{ - if (pcmdpriv) { - kfree(pcmdpriv->cmd_allocated_buf); - kfree(pcmdpriv->rsp_allocated_buf); - } -} - -/* - * Calling Context: - * - * r8712_enqueue_cmd can only be called between kernel thread, - * since only spin_lock is used. - * - * ISR/Call-Back functions can't call this sub-function. - * - */ - -void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) -{ - struct __queue *queue; - unsigned long irqL; - - if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) - return; - if (!obj) - return; - queue = &pcmdpriv->cmd_queue; - spin_lock_irqsave(&queue->lock, irqL); - list_add_tail(&obj->list, &queue->queue); - spin_unlock_irqrestore(&queue->lock, irqL); - complete(&pcmdpriv->cmd_queue_comp); -} - -struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue) -{ - unsigned long irqL; - struct cmd_obj *obj; - - spin_lock_irqsave(&queue->lock, irqL); - obj = list_first_entry_or_null(&queue->queue, - struct cmd_obj, list); - if (obj) - list_del_init(&obj->list); - spin_unlock_irqrestore(&queue->lock, irqL); - return obj; -} - -void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj) -{ - unsigned long irqL; - struct __queue *queue; - - if (!obj) - return; - if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag) - return; - queue = &pcmdpriv->cmd_queue; - spin_lock_irqsave(&queue->lock, irqL); - list_add_tail(&obj->list, &queue->queue); - spin_unlock_irqrestore(&queue->lock, irqL); - complete(&pcmdpriv->cmd_queue_comp); -} - -void r8712_free_cmd_obj(struct cmd_obj *pcmd) -{ - if ((pcmd->cmdcode != _JoinBss_CMD_) && - (pcmd->cmdcode != _CreateBss_CMD_)) - kfree(pcmd->parmbuf); - if (pcmd->rsp) { - if (pcmd->rspsz != 0) - kfree(pcmd->rsp); - } - kfree(pcmd); -} - -u8 r8712_sitesurvey_cmd(struct _adapter *padapter, - struct ndis_802_11_ssid *pssid) - __must_hold(&padapter->mlmepriv.lock) -{ - struct cmd_obj *ph2c; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return _FAIL; - psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC); - if (!psurveyPara) { - kfree(ph2c); - return _FAIL; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, - GEN_CMD_CODE(_SiteSurvey)); - psurveyPara->bsslimit = cpu_to_le32(48); - psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode); - psurveyPara->ss_ssidlen = 0; - memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1); - if (pssid && pssid->SsidLength) { - int len = min_t(int, pssid->SsidLength, IW_ESSID_MAX_SIZE); - - memcpy(psurveyPara->ss_ssid, pssid->Ssid, len); - psurveyPara->ss_ssidlen = cpu_to_le32(len); - } - set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - r8712_enqueue_cmd(pcmdpriv, ph2c); - mod_timer(&pmlmepriv->scan_to_timer, - jiffies + msecs_to_jiffies(SCANNING_TIMEOUT)); - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY); - complete(&padapter->rx_filter_ready); - return _SUCCESS; -} - -int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset) -{ - struct cmd_obj *ph2c; - struct setdatarate_parm *pbsetdataratepara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return -ENOMEM; - pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC); - if (!pbsetdataratepara) { - kfree(ph2c); - return -ENOMEM; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, - GEN_CMD_CODE(_SetDataRate)); - pbsetdataratepara->mac_id = 5; - memcpy(pbsetdataratepara->datarates, rateset, NumRates); - r8712_enqueue_cmd(pcmdpriv, ph2c); - return 0; -} - -void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan) -{ - struct cmd_obj *ph2c; - struct SetChannelPlan_param *psetchplanpara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC); - if (!psetchplanpara) { - kfree(ph2c); - return; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara, GEN_CMD_CODE(_SetChannelPlan)); - psetchplanpara->ChannelPlan = chplan; - r8712_enqueue_cmd(pcmdpriv, ph2c); -} - -int r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val) -{ - struct cmd_obj *ph2c; - struct writeRF_parm *pwriterfparm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return -ENOMEM; - pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC); - if (!pwriterfparm) { - kfree(ph2c); - return -ENOMEM; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg)); - pwriterfparm->offset = offset; - pwriterfparm->value = val; - r8712_enqueue_cmd(pcmdpriv, ph2c); - return 0; -} - -int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval) -{ - struct cmd_obj *ph2c; - struct readRF_parm *prdrfparm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return -ENOMEM; - prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC); - if (!prdrfparm) { - kfree(ph2c); - return -ENOMEM; - } - INIT_LIST_HEAD(&ph2c->list); - ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg); - ph2c->parmbuf = (unsigned char *)prdrfparm; - ph2c->cmdsz = sizeof(struct readRF_parm); - ph2c->rsp = pval; - ph2c->rspsz = sizeof(struct readRF_rsp); - prdrfparm->offset = offset; - r8712_enqueue_cmd(pcmdpriv, ph2c); - return 0; -} - -void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter, - struct cmd_obj *pcmd) -{ - kfree(pcmd->parmbuf); - kfree(pcmd); - padapter->mppriv.workparam.bcompleted = true; -} - -void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd) -{ - kfree(pcmd->parmbuf); - kfree(pcmd); - - padapter->mppriv.workparam.bcompleted = true; -} - -int r8712_createbss_cmd(struct _adapter *padapter) -{ - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct wlan_bssid_ex *pdev_network = - &padapter->registrypriv.dev_network; - - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); - pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) - return -ENOMEM; - INIT_LIST_HEAD(&pcmd->list); - pcmd->cmdcode = _CreateBss_CMD_; - pcmd->parmbuf = (unsigned char *)pdev_network; - pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - /* notes: translate IELength & Length after assign to cmdsz; */ - pdev_network->Length = pcmd->cmdsz; - pdev_network->IELength = pdev_network->IELength; - pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength; - r8712_enqueue_cmd(pcmdpriv, pcmd); - return 0; -} - -int r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) -{ - struct wlan_bssid_ex *psecnetwork; - struct cmd_obj *pcmd; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = - pnetwork->network.InfrastructureMode; - - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); - pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) - return -ENOMEM; - - /* for hidden ap to set fw_state here */ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) != - true) { - switch (ndis_network_mode) { - case Ndis802_11IBSS: - pmlmepriv->fw_state |= WIFI_ADHOC_STATE; - break; - case Ndis802_11Infrastructure: - pmlmepriv->fw_state |= WIFI_STATION_STATE; - break; - case Ndis802_11APMode: - case Ndis802_11AutoUnknown: - case Ndis802_11InfrastructureMax: - break; - } - } - psecnetwork = &psecuritypriv->sec_bss; - memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork)); - psecuritypriv->authenticator_ie[0] = (unsigned char) - psecnetwork->IELength; - if ((psecnetwork->IELength - 12) < (256 - 1)) - memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], - psecnetwork->IELength - 12); - else - memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1)); - psecnetwork->IELength = 0; - /* - * If the driver wants to use the bssid to create the connection. - * If not, we copy the connecting AP's MAC address to it so that - * the driver just has the bssid information for PMKIDList searching. - */ - if (!pmlmepriv->assoc_by_bssid) - ether_addr_copy(&pmlmepriv->assoc_bssid[0], - &pnetwork->network.MacAddress[0]); - psecnetwork->IELength = r8712_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], pnetwork->network.IELength); - pqospriv->qos_option = 0; - if (pregistrypriv->wmm_enable) { - u32 tmp_len; - - tmp_len = r8712_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], pnetwork->network.IELength, - psecnetwork->IELength); - if (psecnetwork->IELength != tmp_len) { - psecnetwork->IELength = tmp_len; - pqospriv->qos_option = 1; /* WMM IE in beacon */ - } else { - pqospriv->qos_option = 0; /* no WMM IE in beacon */ - } - } - if (pregistrypriv->ht_enable) { - /* - * For WEP mode, we will use the bg mode to do the connection - * to avoid some IOT issues, especially for Realtek 8192u - * SoftAP. - */ - if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) && - (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) { - /* restructure_ht_ie */ - r8712_restructure_ht_ie(padapter, - &pnetwork->network.IEs[0], - &psecnetwork->IEs[0], - pnetwork->network.IELength, - &psecnetwork->IELength); - } - } - psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength; - if (psecnetwork->IELength < 255) - memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], - psecnetwork->IELength); - else - memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], - 255); - /* get cmdsz before endian conversion */ - pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork); -#ifdef __BIG_ENDIAN - /* wlan_network endian conversion */ - psecnetwork->Length = cpu_to_le32(psecnetwork->Length); - psecnetwork->Ssid.SsidLength = cpu_to_le32(psecnetwork->Ssid.SsidLength); - psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy); - psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi); - psecnetwork->NetworkTypeInUse = cpu_to_le32(psecnetwork->NetworkTypeInUse); - psecnetwork->Configuration.ATIMWindow = cpu_to_le32(psecnetwork->Configuration.ATIMWindow); - psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(psecnetwork->Configuration.BeaconPeriod); - psecnetwork->Configuration.DSConfig = cpu_to_le32(psecnetwork->Configuration.DSConfig); - psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(psecnetwork->Configuration.FHConfig.DwellTime); - psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopPattern); - psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopSet); - psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(psecnetwork->Configuration.FHConfig.Length); - psecnetwork->Configuration.Length = cpu_to_le32(psecnetwork->Configuration.Length); - psecnetwork->InfrastructureMode = cpu_to_le32(psecnetwork->InfrastructureMode); - psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength); -#endif - INIT_LIST_HEAD(&pcmd->list); - pcmd->cmdcode = _JoinBss_CMD_; - pcmd->parmbuf = (unsigned char *)psecnetwork; - pcmd->rsp = NULL; - pcmd->rspsz = 0; - r8712_enqueue_cmd(pcmdpriv, pcmd); - return 0; -} - -void r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */ -{ - struct cmd_obj *pdisconnect_cmd; - struct disconnect_parm *pdisconnect; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC); - if (!pdisconnect_cmd) - return; - pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC); - if (!pdisconnect) { - kfree(pdisconnect_cmd); - return; - } - init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect, _DisConnect_CMD_); - r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd); -} - -void r8712_setopmode_cmd(struct _adapter *padapter, - enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) -{ - struct cmd_obj *ph2c; - struct setopmode_parm *psetop; - - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC); - if (!psetop) { - kfree(ph2c); - return; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); - psetop->mode = (u8)networktype; - r8712_enqueue_cmd(pcmdpriv, ph2c); -} - -void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key) -{ - struct cmd_obj *ph2c; - struct set_stakey_parm *psetstakey_para; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct set_stakey_rsp *psetstakey_rsp = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct sta_info *sta = (struct sta_info *)psta; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC); - if (!psetstakey_para) { - kfree(ph2c); - return; - } - psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC); - if (!psetstakey_rsp) { - kfree(ph2c); - kfree(psetstakey_para); - return; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *)psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - ether_addr_copy(psetstakey_para->addr, sta->hwaddr); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - psetstakey_para->algorithm = (unsigned char) - psecuritypriv->PrivacyAlgrthm; - else - GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false); - if (unicast_key) - memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16); - else - memcpy(&psetstakey_para->key, - &psecuritypriv->XGrpKey[psecuritypriv->XGrpKeyid - 1].skey, - 16); - r8712_enqueue_cmd(pcmdpriv, ph2c); -} - -void r8712_setMacAddr_cmd(struct _adapter *padapter, const u8 *mac_addr) -{ - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_obj *ph2c; - struct SetMacAddr_param *psetMacAddr_para; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC); - if (!psetMacAddr_para) { - kfree(ph2c); - return; - } - init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para, _SetMacAddress_CMD_); - ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr); - r8712_enqueue_cmd(pcmdpriv, ph2c); -} - -void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid) -{ - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct cmd_obj *ph2c; - struct addBaReq_parm *paddbareq_parm; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC); - if (!paddbareq_parm) { - kfree(ph2c); - return; - } - paddbareq_parm->tid = tid; - init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq)); - r8712_enqueue_cmd_ex(pcmdpriv, ph2c); -} - -void r8712_wdg_wk_cmd(struct _adapter *padapter) -{ - struct cmd_obj *ph2c; - struct drvint_cmd_parm *pdrvintcmd_param; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC); - if (!pdrvintcmd_param) { - kfree(ph2c); - return; - } - pdrvintcmd_param->i_cid = WDG_WK_CID; - pdrvintcmd_param->sz = 0; - pdrvintcmd_param->pbuf = NULL; - init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_); - r8712_enqueue_cmd_ex(pcmdpriv, ph2c); -} - -void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) - clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - r8712_free_cmd_obj(pcmd); -} - -void r8712_disassoc_cmd_callback(struct _adapter *padapter, - struct cmd_obj *pcmd) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) { - spin_lock_irqsave(&pmlmepriv->lock, irqL); - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - return; - } - r8712_free_cmd_obj(pcmd); -} - -void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pcmd->res != H2C_SUCCESS) - mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); - r8712_free_cmd_obj(pcmd); -} - -void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) -{ - unsigned long irqL; - struct sta_info *psta = NULL; - struct wlan_network *pwlan = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf; - struct wlan_network *tgt_network = &(pmlmepriv->cur_network); - - if (pcmd->res != H2C_SUCCESS) - mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1)); - del_timer(&pmlmepriv->assoc_timer); -#ifdef __BIG_ENDIAN - /* endian_convert */ - pnetwork->Length = le32_to_cpu(pnetwork->Length); - pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength); - pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy); - pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi); - pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse); - pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->Configuration.ATIMWindow); - pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->Configuration.DSConfig); - pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime); - pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern); - pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet); - pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->Configuration.FHConfig.Length); - pnetwork->Configuration.Length = le32_to_cpu(pnetwork->Configuration.Length); - pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->InfrastructureMode); - pnetwork->IELength = le32_to_cpu(pnetwork->IELength); -#endif - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if ((pmlmepriv->fw_state) & WIFI_AP_STATE) { - psta = r8712_get_stainfo(&padapter->stapriv, pnetwork->MacAddress); - if (!psta) { - psta = r8712_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress); - if (!psta) - goto createbss_cmd_fail; - } - r8712_indicate_connect(padapter); - } else { - pwlan = _r8712_alloc_network(pmlmepriv); - if (!pwlan) { - pwlan = r8712_get_oldest_wlan_network(&pmlmepriv->scanned_queue); - if (!pwlan) - goto createbss_cmd_fail; - pwlan->last_scanned = jiffies; - } else { - list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue); - } - pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork); - memcpy(&(pwlan->network), pnetwork, pnetwork->Length); - pwlan->fixed = true; - memcpy(&tgt_network->network, pnetwork, (r8712_get_wlan_bssid_ex_sz(pnetwork))); - if (pmlmepriv->fw_state & _FW_UNDER_LINKING) - pmlmepriv->fw_state ^= _FW_UNDER_LINKING; - /* - * we will set _FW_LINKED when there is one more sat to - * join us (stassoc_event_callback) - */ - } -createbss_cmd_fail: - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - r8712_free_cmd_obj(pcmd); -} - -void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp); - struct sta_info *psta = r8712_get_stainfo(pstapriv, psetstakey_rsp->addr); - - if (!psta) - goto exit; - psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/ -exit: - r8712_free_cmd_obj(pcmd); -} - -void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, - struct cmd_obj *pcmd) -{ - unsigned long irqL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf); - struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp); - struct sta_info *psta = r8712_get_stainfo(pstapriv, passocsta_parm->addr); - - if (!psta) - return; - psta->aid = psta->mac_id = passocsta_rsp->cam_id; - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) - pmlmepriv->fw_state ^= _FW_UNDER_LINKING; - set_fwstate(pmlmepriv, _FW_LINKED); - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - r8712_free_cmd_obj(pcmd); -} - -void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, u32 tryPktCnt, - u32 tryPktInterval, u32 firstStageTO) -{ - struct cmd_obj *ph2c; - struct DisconnectCtrlEx_param *param; - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - - ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); - if (!ph2c) - return; - param = kzalloc(sizeof(*param), GFP_ATOMIC); - if (!param) { - kfree(ph2c); - return; - } - - param->EnableDrvCtrl = (unsigned char)enableDrvCtrl; - param->TryPktCnt = (unsigned char)tryPktCnt; - param->TryPktInterval = (unsigned char)tryPktInterval; - param->FirstStageTO = (unsigned int)firstStageTO; - - init_h2fwcmd_w_parm_no_rsp(ph2c, param, GEN_CMD_CODE(_DisconnectCtrlEx)); - r8712_enqueue_cmd(pcmdpriv, ph2c); -} diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h deleted file mode 100644 index 268844af57f006e9a21156cf1b3f50ebcec93b05..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_cmd.h +++ /dev/null @@ -1,750 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_CMD_H_ -#define __RTL871X_CMD_H_ - -#include "wlan_bssdef.h" -#include "rtl871x_rf.h" -#define C2H_MEM_SZ (16*1024) - -#include "osdep_service.h" -#include "ieee80211.h" - -#define FREE_CMDOBJ_SZ 128 -#define MAX_CMDSZ 512 -#define MAX_RSPSZ 512 -#define MAX_EVTSZ 1024 -#define CMDBUFF_ALIGN_SZ 512 - -struct cmd_obj { - u16 cmdcode; - u8 res; - u8 *parmbuf; - u32 cmdsz; - u8 *rsp; - u32 rspsz; - struct list_head list; -}; - -struct cmd_priv { - struct completion cmd_queue_comp; - struct completion terminate_cmdthread_comp; - struct __queue cmd_queue; - u8 cmd_seq; - u8 *cmd_buf; /*shall be non-paged, and 4 bytes aligned*/ - u8 *cmd_allocated_buf; - u8 *rsp_buf; /*shall be non-paged, and 4 bytes aligned*/ - u8 *rsp_allocated_buf; - u32 cmd_issued_cnt; - u32 cmd_done_cnt; - u32 rsp_cnt; - struct _adapter *padapter; -}; - -struct evt_obj { - u16 evtcode; - u8 res; - u8 *parmbuf; - u32 evtsz; - struct list_head list; -}; - -struct evt_priv { - struct __queue evt_queue; - u8 event_seq; - u8 *evt_buf; /*shall be non-paged, and 4 bytes aligned*/ - u8 *evt_allocated_buf; - u32 evt_done_cnt; -}; - -#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \ -do {\ - INIT_LIST_HEAD(&pcmd->list);\ - pcmd->cmdcode = code;\ - pcmd->parmbuf = (u8 *)(pparm);\ - pcmd->cmdsz = sizeof(*pparm);\ - pcmd->rsp = NULL;\ - pcmd->rspsz = 0;\ -} while (0) - -void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj); -void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj); -struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue); -void r8712_free_cmd_obj(struct cmd_obj *pcmd); -int r8712_cmd_thread(void *context); -int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv); -void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv); -int r8712_init_evt_priv(struct evt_priv *pevtpriv); -void r8712_free_evt_priv(struct evt_priv *pevtpriv); - -enum rtl871x_drvint_cid { - NONE_WK_CID, - WDG_WK_CID, - MAX_WK_CID -}; - -enum RFINTFS { - SWSI, - HWSI, - HWPI, -}; - -/* - * Caller Mode: Infra, Ad-HoC(C) - * Notes: To enter USB suspend mode - * Command Mode - */ -struct usb_suspend_parm { - u32 action; /* 1: sleep, 0:resume */ -}; - -/* - * Caller Mode: Infra, Ad-HoC(C) - * Notes: To disconnect the current associated BSS - * Command Mode - */ -struct disconnect_parm { - u32 rsvd; -}; - -/* - * Caller Mode: AP, Ad-HoC, Infra - * Notes: To set the NIC mode of RTL8711 - * Command Mode - * The definition of mode: - * - * #define IW_MODE_AUTO 0 // Let the driver decides which AP to join - * #define IW_MODE_ADHOC 1 // Single cell network (Ad-Hoc Clients) - * #define IW_MODE_INFRA 2 // Multi cell network, roaming, .. - * #define IW_MODE_MASTER 3 // Synchronisation master or AP - * #define IW_MODE_REPEAT 4 // Wireless Repeater (forwarder) - * #define IW_MODE_SECOND 5 // Secondary master/repeater (backup) - * #define IW_MODE_MONITOR 6 // Passive monitor (listen only) - */ -struct setopmode_parm { - u8 mode; - u8 rsvd[3]; -}; - -/* - * Caller Mode: AP, Ad-HoC, Infra - * Notes: To ask RTL8711 performing site-survey - * Command-Event Mode - */ -struct sitesurvey_parm { - __le32 passive_mode; /*active: 1, passive: 0 */ - __le32 bsslimit; /* 1 ~ 48 */ - __le32 ss_ssidlen; - u8 ss_ssid[IW_ESSID_MAX_SIZE + 1]; -}; - -/* - * Caller Mode: Any - * Notes: To set the auth type of RTL8711. open/shared/802.1x - * Command Mode - */ -struct setauth_parm { - u8 mode; /*0: legacy open, 1: legacy shared 2: 802.1x*/ - u8 _1x; /*0: PSK, 1: TLS*/ - u8 rsvd[2]; -}; - -/* - * Caller Mode: Infra - * a. algorithm: wep40, wep104, tkip & aes - * b. keytype: grp key/unicast key - * c. key contents - * - * when shared key ==> keyid is the camid - * when 802.1x ==> keyid [0:1] ==> grp key - * when 802.1x ==> keyid > 2 ==> unicast key - */ -struct setkey_parm { - u8 algorithm; /* encryption algorithm, could be none, wep40, - * TKIP, CCMP, wep104 - */ - u8 keyid; - u8 grpkey; /* 1: this is the grpkey for 802.1x. - * 0: this is the unicast key for 802.1x - */ - u8 key[16]; /* this could be 40 or 104 */ -}; - -/* - * When in AP or Ad-Hoc mode, this is used to - * allocate an sw/hw entry for a newly associated sta. - * Command - * when shared key ==> algorithm/keyid - */ -struct set_stakey_parm { - u8 addr[ETH_ALEN]; - u8 algorithm; - u8 key[16]; -}; - -struct set_stakey_rsp { - u8 addr[ETH_ALEN]; - u8 keyid; - u8 rsvd; -}; - -struct SetMacAddr_param { - u8 MacAddr[ETH_ALEN]; -}; - -/* - * Caller Ad-Hoc/AP - * - * Command -Rsp(AID == CAMID) mode - * - * This is to force fw to add an sta_data entry per driver's request. - * - * FW will write an cam entry associated with it. - * - */ -struct set_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -struct set_assocsta_rsp { - u8 cam_id; - u8 rsvd[3]; -}; - -/* - * Caller Ad-Hoc/AP - * - * Command mode - * - * This is to force fw to del an sta_data entry per driver's request - * - * FW will invalidate the cam entry associated with it. - * - */ -struct del_assocsta_parm { - u8 addr[ETH_ALEN]; -}; - -/* - * Caller Mode: AP/Ad-HoC(M) - * - * Notes: To notify fw that given staid has changed its power state - * - * Command Mode - * - */ -struct setstapwrstate_parm { - u8 staid; - u8 status; - u8 hwaddr[6]; -}; - -/* - * Caller Mode: Any - * - * Notes: To setup the basic rate of RTL8711 - * - * Command Mode - * - */ -struct setbasicrate_parm { - u8 basicrates[NumRates]; -}; - -/* - * Caller Mode: Any - * - * Notes: To read the current basic rate - * - * Command-Rsp Mode - * - */ -struct getbasicrate_parm { - u32 rsvd; -}; - -struct getbasicrate_rsp { - u8 basicrates[NumRates]; -}; - -/* - * Caller Mode: Any - * - * Notes: To setup the data rate of RTL8711 - * - * Command Mode - * - */ -struct setdatarate_parm { - u8 mac_id; - u8 datarates[NumRates]; -}; - -enum _RT_CHANNEL_DOMAIN { - RT_CHANNEL_DOMAIN_FCC = 0, - RT_CHANNEL_DOMAIN_IC = 1, - RT_CHANNEL_DOMAIN_ETSI = 2, - RT_CHANNEL_DOMAIN_SPAIN = 3, - RT_CHANNEL_DOMAIN_FRANCE = 4, - RT_CHANNEL_DOMAIN_MKK = 5, - RT_CHANNEL_DOMAIN_MKK1 = 6, - RT_CHANNEL_DOMAIN_ISRAEL = 7, - RT_CHANNEL_DOMAIN_TELEC = 8, - - /* Be compatible with old channel plan. No good! */ - RT_CHANNEL_DOMAIN_MIC = 9, - RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 10, - RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 11, - RT_CHANNEL_DOMAIN_TELEC_NETGEAR = 12, - - RT_CHANNEL_DOMAIN_NCC = 13, - RT_CHANNEL_DOMAIN_5G = 14, - RT_CHANNEL_DOMAIN_5G_40M = 15, - /*===== Add new channel plan above this line===============*/ - RT_CHANNEL_DOMAIN_MAX, -}; - -struct SetChannelPlan_param { - enum _RT_CHANNEL_DOMAIN ChannelPlan; -}; - -/* - * Caller Mode: Any - * - * Notes: To read the current data rate - * - * Command-Rsp Mode - * - */ -struct getdatarate_parm { - u32 rsvd; - -}; - -struct getdatarate_rsp { - u8 datarates[NumRates]; -}; - -/* - * Caller Mode: Any - * AP: AP can use the info for the contents of beacon frame - * Infra: STA can use the info when sitesurveying - * Ad-HoC(M): Like AP - * Ad-HoC(C): Like STA - * - * - * Notes: To set the phy capability of the NIC - * - * Command Mode - * - */ - -/* - * Caller Mode: Any - * - * Notes: To set the channel/modem/band - * This command will be used when channel/modem/band is changed. - * - * Command Mode - * - */ -/* - * Caller Mode: Any - * - * Notes: To get the current setting of channel/modem/band - * - * Command-Rsp Mode - * - */ -struct getphy_rsp { - u8 rfchannel; - u8 modem; -}; - -struct readBB_parm { - u8 offset; -}; - -struct readBB_rsp { - u8 value; -}; - -struct readTSSI_parm { - u8 offset; -}; - -struct readTSSI_rsp { - u8 value; -}; - -struct writeBB_parm { - u8 offset; - u8 value; -}; - -struct writePTM_parm { - u8 type; -}; - -struct readRF_parm { - u8 offset; -}; - -struct readRF_rsp { - u32 value; -}; - -struct writeRF_parm { - u32 offset; - u32 value; -}; - -struct setrfintfs_parm { - u8 rfintfs; -}; - -struct getrfintfs_parm { - u8 rfintfs; -}; - -/* - * Notes: This command is used for H2C/C2H loopback testing - * - * mac[0] == 0 - * ==> CMD mode, return H2C_SUCCESS. - * The following condition must be true under CMD mode - * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0; - * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7; - * s2 == (b1 << 8 | b0); - * - * mac[0] == 1 - * ==> CMD_RSP mode, return H2C_SUCCESS_RSP - * - * The rsp layout shall be: - * rsp: parm: - * mac[0] = mac[5]; - * mac[1] = mac[4]; - * mac[2] = mac[3]; - * mac[3] = mac[2]; - * mac[4] = mac[1]; - * mac[5] = mac[0]; - * s0 = s1; - * s1 = swap16(s0); - * w0 = swap32(w1); - * b0 = b1 - * s2 = s0 + s1 - * b1 = b0 - * w1 = w0 - * - * mac[0] == 2 - * ==> CMD_EVENT mode, return H2C_SUCCESS - * The event layout shall be: - * event: parm: - * mac[0] = mac[5]; - * mac[1] = mac[4]; - * mac[2] = event's sequence number, starting from 1 to parm's marc[3] - * mac[3] = mac[2]; - * mac[4] = mac[1]; - * mac[5] = mac[0]; - * s0 = swap16(s0) - event.mac[2]; - * s1 = s1 + event.mac[2]; - * w0 = swap32(w0); - * b0 = b1 - * s2 = s0 + event.mac[2] - * b1 = b0 - * w1 = swap32(w1) - event.mac[2]; - * - * parm->mac[3] is the total event counts that host requested. - * - * - * event will be the same with the cmd's param. - * - */ - -/* CMD param Formart for DRV INTERNAL CMD HDL*/ -struct drvint_cmd_parm { - int i_cid; /*internal cmd id*/ - int sz; /* buf sz*/ - unsigned char *pbuf; -}; - -/*------------------- Below are used for RF/BB tuning ---------------------*/ - -struct setantenna_parm { - u8 tx_antset; - u8 rx_antset; - u8 tx_antenna; - u8 rx_antenna; -}; - -struct enrateadaptive_parm { - u32 en; -}; - -struct settxagctbl_parm { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct gettxagctbl_parm { - u32 rsvd; -}; - -struct gettxagctbl_rsp { - u32 txagc[MAX_RATES_LENGTH]; -}; - -struct setagcctrl_parm { - u32 agcctrl; /* 0: pure hw, 1: fw */ -}; - -struct setssup_parm { - u32 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct getssup_parm { - u32 rsvd; -}; - -struct getssup_rsp { - u8 ss_ForceUp[MAX_RATES_LENGTH]; -}; - -struct setssdlevel_parm { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct getssdlevel_parm { - u32 rsvd; -}; - -struct getssdlevel_rsp { - u8 ss_DLevel[MAX_RATES_LENGTH]; -}; - -struct setssulevel_parm { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct getssulevel_parm { - u32 rsvd; -}; - -struct getssulevel_rsp { - u8 ss_ULevel[MAX_RATES_LENGTH]; -}; - -struct setcountjudge_parm { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct getcountjudge_parm { - u32 rsvd; -}; - -struct getcountjudge_rsp { - u8 count_judge[MAX_RATES_LENGTH]; -}; - -struct setpwrmode_parm { - u8 mode; - u8 flag_low_traffic_en; - u8 flag_lpnav_en; - u8 flag_rf_low_snr_en; - u8 flag_dps_en; /* 1: dps, 0: 32k */ - u8 bcn_rx_en; - u8 bcn_pass_cnt; /* fw report one beacon information to - * driver when it receives bcn_pass_cnt - * beacons. - */ - u8 bcn_to; /* beacon TO (ms). ¡§=0¡¨ no limit.*/ - u16 bcn_itv; - u8 app_itv; /* only for VOIP mode. */ - u8 awake_bcn_itv; - u8 smart_ps; - u8 bcn_pass_time; /* unit: 100ms */ -}; - -struct setatim_parm { - u8 op; /*0: add, 1:del*/ - u8 txid; /* id of dest station.*/ -}; - -struct setratable_parm { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -struct getratable_parm { - uint rsvd; -}; - -struct getratable_rsp { - u8 ss_ForceUp[NumRates]; - u8 ss_ULevel[NumRates]; - u8 ss_DLevel[NumRates]; - u8 count_judge[NumRates]; -}; - -/*to get TX,RX retry count*/ -struct gettxretrycnt_parm { - unsigned int rsvd; -}; - -struct gettxretrycnt_rsp { - unsigned long tx_retrycnt; -}; - -struct getrxretrycnt_parm { - unsigned int rsvd; -}; - -struct getrxretrycnt_rsp { - unsigned long rx_retrycnt; -}; - -/*to get BCNOK,BCNERR count*/ -struct getbcnokcnt_parm { - unsigned int rsvd; -}; - -struct getbcnokcnt_rsp { - unsigned long bcnokcnt; -}; - -struct getbcnerrcnt_parm { - unsigned int rsvd; -}; - -struct getbcnerrcnt_rsp { - unsigned long bcnerrcnt; -}; - -/* to get current TX power level*/ -struct getcurtxpwrlevel_parm { - unsigned int rsvd; -}; - -struct getcurtxpwrlevel_rsp { - unsigned short tx_power; -}; - -/*dynamic on/off DIG*/ -struct setdig_parm { - unsigned char dig_on; /* 1:on , 0:off */ -}; - -/*dynamic on/off RA*/ -struct setra_parm { - unsigned char ra_on; /* 1:on , 0:off */ -}; - -struct setprobereqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct setassocreqextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct setproberspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct setassocrspextraie_parm { - unsigned char e_id; - unsigned char ie_len; - unsigned char ie[]; -}; - -struct addBaReq_parm { - unsigned int tid; -}; - -/*H2C Handler index: 46 */ -struct SetChannel_parm { - u32 curr_ch; -}; - -/*H2C Handler index: 61 */ -struct DisconnectCtrlEx_param { - /* MAXTIME = (2 * FirstStageTO) + (TryPktCnt * TryPktInterval) */ - unsigned char EnableDrvCtrl; - unsigned char TryPktCnt; - unsigned char TryPktInterval; /* Unit: ms */ - unsigned char rsvd; - unsigned int FirstStageTO; /* Unit: ms */ -}; - -#define GEN_CMD_CODE(cmd) cmd ## _CMD_ - -/* - * Result: - * 0x00: success - * 0x01: success, and check Response. - * 0x02: cmd ignored due to duplicated sequence number - * 0x03: cmd dropped due to invalid cmd code - * 0x04: reserved. - */ - -#define H2C_RSP_OFFSET 512 -#define H2C_SUCCESS 0x00 -#define H2C_SUCCESS_RSP 0x01 -#define H2C_DUPLICATED 0x02 -#define H2C_DROPPED 0x03 -#define H2C_PARAMETERS_ERROR 0x04 -#define H2C_REJECTED 0x05 -#define H2C_CMD_OVERFLOW 0x06 -#define H2C_RESERVED 0x07 - -void r8712_setMacAddr_cmd(struct _adapter *padapter, const u8 *mac_addr); -u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct ndis_802_11_ssid *pssid); -int r8712_createbss_cmd(struct _adapter *padapter); -void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key); -int r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork); -void r8712_disassoc_cmd(struct _adapter *padapter); -void r8712_setopmode_cmd(struct _adapter *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype); -int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset); -void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan); -int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval); -int r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val); -void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid); -void r8712_wdg_wk_cmd(struct _adapter *padapter); -void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_disassoc_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd); -void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, u32 tryPktCnt, - u32 tryPktInterval, u32 firstStageTO); - -struct _cmd_callback { - u32 cmd_code; - void (*callback)(struct _adapter *padapter, struct cmd_obj *cmd); -}; - -#include "rtl8712_cmd.h" - -#endif /* _CMD_H_ */ - diff --git a/drivers/staging/rtl8712/rtl871x_debug.h b/drivers/staging/rtl8712/rtl871x_debug.h deleted file mode 100644 index 69c631af2a2acf687e09f3e0beb8149087e8b78a..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_debug.h +++ /dev/null @@ -1,130 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_DEBUG_H__ -#define __RTL871X_DEBUG_H__ - -#include "osdep_service.h" -#include "drv_types.h" - -#define _drv_emerg_ 1 -#define _drv_alert_ 2 -#define _drv_crit_ 3 -#define _drv_err_ 4 -#define _drv_warning_ 5 -#define _drv_notice_ 6 -#define _drv_info_ 7 -#define _drv_dump_ 8 -#define _drv_debug_ 9 - -#define _module_rtl871x_xmit_c_ BIT(0) -#define _module_xmit_osdep_c_ BIT(1) -#define _module_rtl871x_recv_c_ BIT(2) -#define _module_recv_osdep_c_ BIT(3) -#define _module_rtl871x_mlme_c_ BIT(4) -#define _module_mlme_osdep_c_ BIT(5) -#define _module_rtl871x_sta_mgt_c_ BIT(6) -#define _module_rtl871x_cmd_c_ BIT(7) -#define _module_cmd_osdep_c_ BIT(8) -#define _module_rtl871x_io_c_ BIT(9) -#define _module_io_osdep_c_ BIT(10) -#define _module_os_intfs_c_ BIT(11) -#define _module_rtl871x_security_c_ BIT(12) -#define _module_rtl871x_eeprom_c_ BIT(13) -#define _module_hal_init_c_ BIT(14) -#define _module_hci_hal_init_c_ BIT(15) -#define _module_rtl871x_ioctl_c_ BIT(16) -#define _module_rtl871x_ioctl_set_c_ BIT(17) -#define _module_rtl871x_pwrctrl_c_ BIT(19) -#define _module_hci_intfs_c_ BIT(20) -#define _module_hci_ops_c_ BIT(21) -#define _module_osdep_service_c_ BIT(22) -#define _module_rtl871x_mp_ioctl_c_ BIT(23) -#define _module_hci_ops_os_c_ BIT(24) -#define _module_rtl871x_ioctl_os_c BIT(25) -#define _module_rtl8712_cmd_c_ BIT(26) -#define _module_rtl871x_mp_c_ BIT(27) -#define _module_rtl8712_xmit_c_ BIT(28) -#define _module_rtl8712_efuse_c_ BIT(29) -#define _module_rtl8712_recv_c_ BIT(30) -#define _module_rtl8712_led_c_ BIT(31) - -#undef _MODULE_DEFINE_ - -#if defined _RTL871X_XMIT_C_ - #define _MODULE_DEFINE_ _module_rtl871x_xmit_c_ -#elif defined _XMIT_OSDEP_C_ - #define _MODULE_DEFINE_ _module_xmit_osdep_c_ -#elif defined _RTL871X_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl871x_recv_c_ -#elif defined _RECV_OSDEP_C_ - #define _MODULE_DEFINE_ _module_recv_osdep_c_ -#elif defined _RTL871X_MLME_C_ - #define _MODULE_DEFINE_ _module_rtl871x_mlme_c_ -#elif defined _MLME_OSDEP_C_ - #define _MODULE_DEFINE_ _module_mlme_osdep_c_ -#elif defined _RTL871X_STA_MGT_C_ - #define _MODULE_DEFINE_ _module_rtl871x_sta_mgt_c_ -#elif defined _RTL871X_CMD_C_ - #define _MODULE_DEFINE_ _module_rtl871x_cmd_c_ -#elif defined _CMD_OSDEP_C_ - #define _MODULE_DEFINE_ _module_cmd_osdep_c_ -#elif defined _RTL871X_IO_C_ - #define _MODULE_DEFINE_ _module_rtl871x_io_c_ -#elif defined _IO_OSDEP_C_ - #define _MODULE_DEFINE_ _module_io_osdep_c_ -#elif defined _OS_INTFS_C_ - #define _MODULE_DEFINE_ _module_os_intfs_c_ -#elif defined _RTL871X_SECURITY_C_ - #define _MODULE_DEFINE_ _module_rtl871x_security_c_ -#elif defined _RTL871X_EEPROM_C_ - #define _MODULE_DEFINE_ _module_rtl871x_eeprom_c_ -#elif defined _HAL_INIT_C_ - #define _MODULE_DEFINE_ _module_hal_init_c_ -#elif defined _HCI_HAL_INIT_C_ - #define _MODULE_DEFINE_ _module_hci_hal_init_c_ -#elif defined _RTL871X_IOCTL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_c_ -#elif defined _RTL871X_IOCTL_SET_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_set_c_ -#elif defined _RTL871X_PWRCTRL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_pwrctrl_c_ -#elif defined _HCI_INTF_C_ - #define _MODULE_DEFINE_ _module_hci_intfs_c_ -#elif defined _HCI_OPS_C_ - #define _MODULE_DEFINE_ _module_hci_ops_c_ -#elif defined _OSDEP_HCI_INTF_C_ - #define _MODULE_DEFINE_ _module_hci_intfs_c_ -#elif defined _OSDEP_SERVICE_C_ - #define _MODULE_DEFINE_ _module_osdep_service_c_ -#elif defined _RTL871X_MP_IOCTL_C_ - #define _MODULE_DEFINE_ _module_rtl871x_mp_ioctl_c_ -#elif defined _HCI_OPS_OS_C_ - #define _MODULE_DEFINE_ _module_hci_ops_os_c_ -#elif defined _RTL871X_IOCTL_LINUX_C_ - #define _MODULE_DEFINE_ _module_rtl871x_ioctl_os_c -#elif defined _RTL871X_MP_C_ - #define _MODULE_DEFINE_ _module_rtl871x_mp_c_ -#elif defined _RTL8712_CMD_C_ - #define _MODULE_DEFINE_ _module_rtl8712_cmd_c_ -#elif defined _RTL8712_XMIT_C_ - #define _MODULE_DEFINE_ _module_rtl8712_xmit_c_ -#elif defined _RTL8712_EFUSE_C_ - #define _MODULE_DEFINE_ _module_rtl8712_efuse_c_ -#elif defined _RTL8712_RECV_C_ - #define _MODULE_DEFINE_ _module_rtl8712_recv_c_ -#else - #undef _MODULE_DEFINE_ -#endif - -#endif /*__RTL871X_DEBUG_H__*/ diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.c b/drivers/staging/rtl8712/rtl871x_eeprom.c deleted file mode 100644 index 221bf92e1b1c3f3a2f00faf4be9b24d6708c380b..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_eeprom.c +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_eeprom.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_EEPROM_C_ - -#include "osdep_service.h" -#include "drv_types.h" - -static void up_clk(struct _adapter *padapter, u16 *x) -{ - *x = *x | _EESK; - r8712_write8(padapter, EE_9346CR, (u8)*x); - udelay(CLOCK_RATE); -} - -static void down_clk(struct _adapter *padapter, u16 *x) -{ - *x = *x & ~_EESK; - r8712_write8(padapter, EE_9346CR, (u8)*x); - udelay(CLOCK_RATE); -} - -static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count) -{ - u16 x, mask; - - if (padapter->surprise_removed) - goto out; - mask = 0x01 << (count - 1); - x = r8712_read8(padapter, EE_9346CR); - x &= ~(_EEDO | _EEDI); - do { - x &= ~_EEDI; - if (data & mask) - x |= _EEDI; - if (padapter->surprise_removed) - goto out; - r8712_write8(padapter, EE_9346CR, (u8)x); - udelay(CLOCK_RATE); - up_clk(padapter, &x); - down_clk(padapter, &x); - mask >>= 1; - } while (mask); - if (padapter->surprise_removed) - goto out; - x &= ~_EEDI; - r8712_write8(padapter, EE_9346CR, (u8)x); -out:; -} - -static u16 shift_in_bits(struct _adapter *padapter) -{ - u16 x, d = 0, i; - - if (padapter->surprise_removed) - goto out; - x = r8712_read8(padapter, EE_9346CR); - x &= ~(_EEDO | _EEDI); - d = 0; - for (i = 0; i < 16; i++) { - d <<= 1; - up_clk(padapter, &x); - if (padapter->surprise_removed) - goto out; - x = r8712_read8(padapter, EE_9346CR); - x &= ~(_EEDI); - if (x & _EEDO) - d |= 1; - down_clk(padapter, &x); - } -out: - return d; -} - -static void standby(struct _adapter *padapter) -{ - u8 x; - - x = r8712_read8(padapter, EE_9346CR); - x &= ~(_EECS | _EESK); - r8712_write8(padapter, EE_9346CR, x); - udelay(CLOCK_RATE); - x |= _EECS; - r8712_write8(padapter, EE_9346CR, x); - udelay(CLOCK_RATE); -} - -static u16 wait_eeprom_cmd_done(struct _adapter *padapter) -{ - u8 x; - u16 i; - - standby(padapter); - for (i = 0; i < 200; i++) { - x = r8712_read8(padapter, EE_9346CR); - if (x & _EEDO) - return true; - udelay(CLOCK_RATE); - } - return false; -} - -static void eeprom_clean(struct _adapter *padapter) -{ - u16 x; - - if (padapter->surprise_removed) - return; - x = r8712_read8(padapter, EE_9346CR); - if (padapter->surprise_removed) - return; - x &= ~(_EECS | _EEDI); - r8712_write8(padapter, EE_9346CR, (u8)x); - if (padapter->surprise_removed) - return; - up_clk(padapter, &x); - if (padapter->surprise_removed) - return; - down_clk(padapter, &x); -} - -void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data) -{ - u8 x; - u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new; - - tmp8_ori = r8712_read8(padapter, 0x102502f1); - tmp8_new = tmp8_ori & 0xf7; - if (tmp8_ori != tmp8_new) - r8712_write8(padapter, 0x102502f1, tmp8_new); - tmp8_clk_ori = r8712_read8(padapter, 0x10250003); - tmp8_clk_new = tmp8_clk_ori | 0x20; - if (tmp8_clk_new != tmp8_clk_ori) - r8712_write8(padapter, 0x10250003, tmp8_clk_new); - x = r8712_read8(padapter, EE_9346CR); - x &= ~(_EEDI | _EEDO | _EESK | _EEM0); - x |= _EEM1 | _EECS; - r8712_write8(padapter, EE_9346CR, x); - shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5); - if (padapter->eeprom_address_size == 8) /*CF+ and SDIO*/ - shift_out_bits(padapter, 0, 6); - else /* USB */ - shift_out_bits(padapter, 0, 4); - standby(padapter); - /* Erase this particular word. Write the erase opcode and register - * number in that order. The opcode is 3bits in length; reg is 6 - * bits long. - */ - standby(padapter); - /* write the new word to the EEPROM - * send the write opcode the EEPORM - */ - shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3); - /* select which word in the EEPROM that we are writing to. */ - shift_out_bits(padapter, reg, padapter->eeprom_address_size); - /* write the data to the selected EEPROM word. */ - shift_out_bits(padapter, data, 16); - if (wait_eeprom_cmd_done(padapter)) { - standby(padapter); - shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5); - shift_out_bits(padapter, reg, 4); - eeprom_clean(padapter); - } - if (tmp8_clk_new != tmp8_clk_ori) - r8712_write8(padapter, 0x10250003, tmp8_clk_ori); - if (tmp8_new != tmp8_ori) - r8712_write8(padapter, 0x102502f1, tmp8_ori); -} - -u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg) /*ReadEEprom*/ -{ - u16 x; - u16 data = 0; - u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new; - - tmp8_ori = r8712_read8(padapter, 0x102502f1); - tmp8_new = tmp8_ori & 0xf7; - if (tmp8_ori != tmp8_new) - r8712_write8(padapter, 0x102502f1, tmp8_new); - tmp8_clk_ori = r8712_read8(padapter, 0x10250003); - tmp8_clk_new = tmp8_clk_ori | 0x20; - if (tmp8_clk_new != tmp8_clk_ori) - r8712_write8(padapter, 0x10250003, tmp8_clk_new); - if (padapter->surprise_removed) - goto out; - /* select EEPROM, reset bits, set _EECS */ - x = r8712_read8(padapter, EE_9346CR); - if (padapter->surprise_removed) - goto out; - x &= ~(_EEDI | _EEDO | _EESK | _EEM0); - x |= _EEM1 | _EECS; - r8712_write8(padapter, EE_9346CR, (unsigned char)x); - /* write the read opcode and register number in that order - * The opcode is 3bits in length, reg is 6 bits long - */ - shift_out_bits(padapter, EEPROM_READ_OPCODE, 3); - shift_out_bits(padapter, reg, padapter->eeprom_address_size); - /* Now read the data (16 bits) in from the selected EEPROM word */ - data = shift_in_bits(padapter); - eeprom_clean(padapter); -out: - if (tmp8_clk_new != tmp8_clk_ori) - r8712_write8(padapter, 0x10250003, tmp8_clk_ori); - if (tmp8_new != tmp8_ori) - r8712_write8(padapter, 0x102502f1, tmp8_ori); - return data; -} diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.h b/drivers/staging/rtl8712/rtl871x_eeprom.h deleted file mode 100644 index 7bdeb2aaa0259b83165365f114f7d2f4588adb9f..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_eeprom.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTL871X_EEPROM_H__ -#define __RTL871X_EEPROM_H__ - -#include "osdep_service.h" - -#define RTL8712_EEPROM_ID 0x8712 -#define EEPROM_MAX_SIZE 256 -#define CLOCK_RATE 50 /*100us*/ - -/*- EEPROM opcodes*/ -#define EEPROM_READ_OPCODE 06 -#define EEPROM_WRITE_OPCODE 05 -#define EEPROM_ERASE_OPCODE 07 -#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable*/ -#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable*/ - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_ALPHA 0x1 -#define EEPROM_CID_Senao 0x3 -#define EEPROM_CID_NetCore 0x5 -#define EEPROM_CID_CAMEO 0X8 -#define EEPROM_CID_SITECOM 0x9 -#define EEPROM_CID_COREGA 0xB -#define EEPROM_CID_EDIMAX_BELKIN 0xC -#define EEPROM_CID_SERCOMM_BELKIN 0xE -#define EEPROM_CID_CAMEO1 0xF -#define EEPROM_CID_WNC_COREGA 0x12 -#define EEPROM_CID_CLEVO 0x13 -#define EEPROM_CID_WHQL 0xFE - -enum RT_CUSTOMER_ID { - RT_CID_DEFAULT = 0, - RT_CID_8187_ALPHA0 = 1, - RT_CID_8187_SERCOMM_PS = 2, - RT_CID_8187_HW_LED = 3, - RT_CID_8187_NETGEAR = 4, - RT_CID_WHQL = 5, - RT_CID_819x_CAMEO = 6, - RT_CID_819x_RUNTOP = 7, - RT_CID_819x_Senao = 8, - RT_CID_TOSHIBA = 9, - RT_CID_819x_Netcore = 10, - RT_CID_Nettronix = 11, - RT_CID_DLINK = 12, - RT_CID_PRONET = 13, - RT_CID_COREGA = 14, - RT_CID_819x_ALPHA = 15, - RT_CID_819x_Sitecom = 16, - RT_CID_CCX = 17, - RT_CID_819x_Lenovo = 18, - RT_CID_819x_QMI = 19, - RT_CID_819x_Edimax_Belkin = 20, - RT_CID_819x_Sercomm_Belkin = 21, - RT_CID_819x_CAMEO1 = 22, - RT_CID_819x_MSI = 23, - RT_CID_819x_Acer = 24, - RT_CID_819x_AzWave_ASUS = 25, - RT_CID_819x_AzWave = 26, - RT_CID_819x_WNC_COREGA = 27, - RT_CID_819x_CLEVO = 28, -}; - -struct eeprom_priv { - u8 bautoload_fail_flag; - u8 bempty; - u8 sys_config; - u8 mac_addr[6]; - u8 config0; - u16 channel_plan; - u8 country_string[3]; - u8 tx_power_b[15]; - u8 tx_power_g[15]; - u8 tx_power_a[201]; - u8 efuse_eeprom_data[EEPROM_MAX_SIZE]; - enum RT_CUSTOMER_ID CustomerID; -}; - -void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data); -u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg); - -#endif /*__RTL871X_EEPROM_H__*/ - diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h deleted file mode 100644 index 0cc780cf4341807ba2bafc768057400eff15f1ea..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_event.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871x_EVENT_H_ -#define _RTL871x_EVENT_H_ - -#include "osdep_service.h" - -#include "wlan_bssdef.h" -#include <linux/semaphore.h> -#include <linux/sem.h> - -/* - * Used to report a bss has been scanned - */ -struct survey_event { - struct wlan_bssid_ex bss; -}; - -/* - * Used to report that the requested site survey has been done. - * bss_cnt indicates the number of bss that has been reported. - */ -struct surveydone_event { - unsigned int bss_cnt; - -}; - -/* - * Used to report the link result of joining the given bss - * join_res: - * -1: authentication fail - * -2: association fail - * > 0: TID - */ -struct joinbss_event { - struct wlan_network network; -}; - -/* - * Used to report a given STA has joinned the created BSS. - * It is used in AP/Ad-HoC(M) mode. - */ -struct stassoc_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; - __le32 cam_id; -}; - -struct stadel_event { - unsigned char macaddr[6]; - unsigned char rsvd[2]; -}; - -struct addba_event { - unsigned int tid; -}; - -#define GEN_EVT_CODE(event) event ## _EVT_ - -struct fwevent { - u32 parmsize; - void (*event_callback)(struct _adapter *dev, u8 *pbuf); -}; - -#define C2HEVENT_SZ 32 -struct event_node { - unsigned char *node; - unsigned char evt_code; - unsigned short evt_sz; - /*volatile*/ int *caller_ff_tail; - int caller_ff_sz; -}; - -struct c2hevent_queue { - /*volatile*/ int head; - /*volatile*/ int tail; - struct event_node nodes[C2HEVENT_SZ]; - unsigned char seq; -}; - -#define NETWORK_QUEUE_SZ 4 - -struct network_queue { - /*volatile*/ int head; - /*volatile*/ int tail; - struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ]; -}; - -struct ADDBA_Req_Report_parm { - unsigned char MacAddress[ETH_ALEN]; - unsigned short StartSeqNum; - unsigned char tid; -}; - -#include "rtl8712_event.h" - -#endif /* _WLANEVENT_H_ */ - diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h deleted file mode 100644 index ebd78665775dd02862b9d20af703b0b0e67435be..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ht.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871X_HT_H_ -#define _RTL871X_HT_H_ - -#include "osdep_service.h" -#include "wifi.h" - -struct ht_priv { - unsigned int ht_option; - unsigned int ampdu_enable;/*for enable Tx A-MPDU*/ - unsigned char baddbareq_issued[16]; - unsigned int tx_amsdu_enable;/*for enable Tx A-MSDU */ - unsigned int tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */ - unsigned int rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, - * updated when join_callback. - */ - struct ieee80211_ht_cap ht_cap; -}; - -#endif /*_RTL871X_HT_H_ */ - diff --git a/drivers/staging/rtl8712/rtl871x_io.c b/drivers/staging/rtl8712/rtl871x_io.c deleted file mode 100644 index 20e080e284dd43dc4abb26e5fbf4c21634aa6642..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_io.c +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_io.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -/* - * - * The purpose of rtl871x_io.c - * - * a. provides the API - * b. provides the protocol engine - * c. provides the software interface between caller and the hardware interface - * - * For r8712u, both sync/async operations are provided. - * - * Only sync read/write_mem operations are provided. - * - */ - -#define _RTL871X_IO_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "rtl871x_io.h" -#include "osdep_intf.h" -#include "usb_ops.h" - -static uint _init_intf_hdl(struct _adapter *padapter, - struct intf_hdl *pintf_hdl) -{ - struct intf_priv *pintf_priv; - void (*set_intf_option)(u32 *poption) = NULL; - void (*set_intf_funs)(struct intf_hdl *pintf_hdl); - void (*set_intf_ops)(struct _io_ops *pops); - uint (*init_intf_priv)(struct intf_priv *pintfpriv); - - set_intf_option = &(r8712_usb_set_intf_option); - set_intf_funs = &(r8712_usb_set_intf_funs); - set_intf_ops = &r8712_usb_set_intf_ops; - init_intf_priv = &r8712_usb_init_intf_priv; - pintf_priv = kmalloc(sizeof(*pintf_priv), GFP_ATOMIC); - pintf_hdl->pintfpriv = pintf_priv; - if (!pintf_priv) - goto _init_intf_hdl_fail; - pintf_hdl->adapter = (u8 *)padapter; - set_intf_option(&pintf_hdl->intf_option); - set_intf_funs(pintf_hdl); - set_intf_ops(&pintf_hdl->io_ops); - pintf_priv->intf_dev = (u8 *)&padapter->dvobjpriv; - if (init_intf_priv(pintf_priv) == _FAIL) - goto _init_intf_hdl_fail; - return _SUCCESS; -_init_intf_hdl_fail: - kfree(pintf_priv); - return _FAIL; -} - -static void _unload_intf_hdl(struct intf_priv *pintfpriv) -{ - void (*unload_intf_priv)(struct intf_priv *pintfpriv); - - unload_intf_priv = &r8712_usb_unload_intf_priv; - unload_intf_priv(pintfpriv); - kfree(pintfpriv); -} - -static uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl) -{ - struct _adapter *adapter = (struct _adapter *)dev; - - pintfhdl->intf_option = 0; - pintfhdl->adapter = dev; - pintfhdl->intf_dev = (u8 *)&adapter->dvobjpriv; - if (!_init_intf_hdl(adapter, pintfhdl)) - goto register_intf_hdl_fail; - return _SUCCESS; -register_intf_hdl_fail: - return false; -} - -static void unregister_intf_hdl(struct intf_hdl *pintfhdl) -{ - _unload_intf_hdl(pintfhdl->pintfpriv); - memset((u8 *)pintfhdl, 0, sizeof(struct intf_hdl)); -} - -uint r8712_alloc_io_queue(struct _adapter *adapter) -{ - u32 i; - struct io_queue *pio_queue; - struct io_req *pio_req; - - pio_queue = kmalloc(sizeof(*pio_queue), GFP_ATOMIC); - if (!pio_queue) - goto alloc_io_queue_fail; - INIT_LIST_HEAD(&pio_queue->free_ioreqs); - INIT_LIST_HEAD(&pio_queue->processing); - INIT_LIST_HEAD(&pio_queue->pending); - spin_lock_init(&pio_queue->lock); - pio_queue->pallocated_free_ioreqs_buf = kzalloc(NUM_IOREQ * - (sizeof(struct io_req)) + 4, - GFP_ATOMIC); - if ((pio_queue->pallocated_free_ioreqs_buf) == NULL) - goto alloc_io_queue_fail; - pio_queue->free_ioreqs_buf = pio_queue->pallocated_free_ioreqs_buf + 4 - - ((addr_t)(pio_queue->pallocated_free_ioreqs_buf) - & 3); - pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf); - for (i = 0; i < NUM_IOREQ; i++) { - INIT_LIST_HEAD(&pio_req->list); - list_add_tail(&pio_req->list, &pio_queue->free_ioreqs); - pio_req++; - } - if ((register_intf_hdl((u8 *)adapter, &pio_queue->intf)) == _FAIL) - goto alloc_io_queue_fail; - adapter->pio_queue = pio_queue; - return _SUCCESS; -alloc_io_queue_fail: - if (pio_queue) { - kfree(pio_queue->pallocated_free_ioreqs_buf); - kfree(pio_queue); - } - adapter->pio_queue = NULL; - return _FAIL; -} - -void r8712_free_io_queue(struct _adapter *adapter) -{ - struct io_queue *pio_queue = adapter->pio_queue; - - if (pio_queue) { - kfree(pio_queue->pallocated_free_ioreqs_buf); - adapter->pio_queue = NULL; - unregister_intf_hdl(&pio_queue->intf); - kfree(pio_queue); - } -} diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h deleted file mode 100644 index f09d50a29b82c6df740ea57ca2ea9725b7c51a3d..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ /dev/null @@ -1,236 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871X_IO_H_ -#define _RTL871X_IO_H_ - -#include "osdep_service.h" -#include "osdep_intf.h" - -#define NUM_IOREQ 8 - -#define MAX_PROT_SZ (64-16) - -#define _IOREADY 0 -#define _IO_WAIT_COMPLETE 1 -#define _IO_WAIT_RSP 2 - -/* IO COMMAND TYPE */ -#define _IOSZ_MASK_ (0x7F) -#define _IO_WRITE_ BIT(7) -#define _IO_FIXED_ BIT(8) -#define _IO_BURST_ BIT(9) -#define _IO_BYTE_ BIT(10) -#define _IO_HW_ BIT(11) -#define _IO_WORD_ BIT(12) -#define _IO_SYNC_ BIT(13) -#define _IO_CMDMASK_ (0x1F80) - -/* - * For prompt mode accessing, caller shall free io_req - * Otherwise, io_handler will free io_req - */ -/* IO STATUS TYPE */ -#define _IO_ERR_ BIT(2) -#define _IO_SUCCESS_ BIT(1) -#define _IO_DONE_ BIT(0) -#define IO_RD32 (_IO_SYNC_ | _IO_WORD_) -#define IO_RD16 (_IO_SYNC_ | _IO_HW_) -#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_) -#define IO_RD32_ASYNC (_IO_WORD_) -#define IO_RD16_ASYNC (_IO_HW_) -#define IO_RD8_ASYNC (_IO_BYTE_) -#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_) -#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_) -#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_) -#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_) -#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_) -#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_) -/* - * Only Sync. burst accessing is provided. - */ -#define IO_WR_BURST(x) (IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | \ - ((x) & _IOSZ_MASK_)) -#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_)) -/*below is for the intf_option bit definition...*/ -#define _INTF_ASYNC_ BIT(0) /*support async io*/ -struct intf_priv; -struct intf_hdl; -struct io_queue; -struct _io_ops { - uint (*_sdbus_read_bytes_to_membuf)(struct intf_priv *pintfpriv, - u32 addr, u32 cnt, u8 *pbuf); - uint (*_sdbus_read_blocks_to_membuf)(struct intf_priv *pintfpriv, - u32 addr, u32 cnt, u8 *pbuf); - u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr); - u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr); - u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr); - uint (*_sdbus_write_blocks_from_membuf)(struct intf_priv *pintfpriv, - u32 addr, u32 cnt, u8 *pbuf, - u8 async); - uint (*_sdbus_write_bytes_from_membuf)(struct intf_priv *pintfpriv, - u32 addr, u32 cnt, u8 *pbuf); - u8 (*_cmd52r)(struct intf_priv *pintfpriv, u32 addr); - void (*_cmd52w)(struct intf_priv *pintfpriv, u32 addr, u8 val8); - u8 (*_cmdfunc152r)(struct intf_priv *pintfpriv, u32 addr); - void (*_cmdfunc152w)(struct intf_priv *pintfpriv, u32 addr, u8 val8); - void (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val); - void (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val); - void (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val); - void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, - u8 *pmem); - void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, - u8 *pmem); - void (*_sync_irp_protocol_rw)(struct io_queue *pio_q); - u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, - u8 *pmem); - u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, - u8 *pmem); -}; - -struct io_req { - struct list_head list; - u32 addr; - /*volatile*/ u32 val; - u32 command; - u32 status; - u8 *pbuf; - void (*_async_io_callback)(struct _adapter *padapter, - struct io_req *pio_req, u8 *cnxt); - u8 *cnxt; -}; - -struct intf_hdl { - u32 intf_option; - u8 *adapter; - u8 *intf_dev; - struct intf_priv *pintfpriv; - void (*intf_hdl_init)(u8 *priv); - void (*intf_hdl_unload)(u8 *priv); - void (*intf_hdl_open)(u8 *priv); - void (*intf_hdl_close)(u8 *priv); - struct _io_ops io_ops; -}; - -struct reg_protocol_rd { -#ifdef __LITTLE_ENDIAN - /* DW1 */ - u32 NumOfTrans:4; - u32 Reserved1:4; - u32 Reserved2:24; - /* DW2 */ - u32 ByteCount:7; - u32 WriteEnable:1; /*0:read, 1:write*/ - u32 FixOrContinuous:1; /*0:continuous, 1: Fix*/ - u32 BurstMode:1; - u32 Byte1Access:1; - u32 Byte2Access:1; - u32 Byte4Access:1; - u32 Reserved3:3; - u32 Reserved4:16; - /*DW3*/ - u32 BusAddress; - /*DW4*/ -#else -/*DW1*/ - u32 Reserved1:4; - u32 NumOfTrans:4; - u32 Reserved2:24; - /*DW2*/ - u32 WriteEnable:1; - u32 ByteCount:7; - u32 Reserved3:3; - u32 Byte4Access:1; - u32 Byte2Access:1; - u32 Byte1Access:1; - u32 BurstMode:1; - u32 FixOrContinuous:1; - u32 Reserved4:16; - /*DW3*/ - u32 BusAddress; - /*DW4*/ -#endif -}; - -struct reg_protocol_wt { -#ifdef __LITTLE_ENDIAN - /*DW1*/ - u32 NumOfTrans:4; - u32 Reserved1:4; - u32 Reserved2:24; - /*DW2*/ - u32 ByteCount:7; - u32 WriteEnable:1; /*0:read, 1:write*/ - u32 FixOrContinuous:1; /*0:continuous, 1: Fix*/ - u32 BurstMode:1; - u32 Byte1Access:1; - u32 Byte2Access:1; - u32 Byte4Access:1; - u32 Reserved3:3; - u32 Reserved4:16; - /*DW3*/ - u32 BusAddress; - /*DW4*/ - u32 Value; -#else - /*DW1*/ - u32 Reserved1:4; - u32 NumOfTrans:4; - u32 Reserved2:24; - /*DW2*/ - u32 WriteEnable:1; - u32 ByteCount:7; - u32 Reserved3:3; - u32 Byte4Access:1; - u32 Byte2Access:1; - u32 Byte1Access:1; - u32 BurstMode:1; - u32 FixOrContinuous:1; - u32 Reserved4:16; - /*DW3*/ - u32 BusAddress; - /*DW4*/ - u32 Value; -#endif -}; - -/* - * Below is the data structure used by _io_handler - */ - -struct io_queue { - spinlock_t lock; - struct list_head free_ioreqs; - /*The io_req list that will be served in the single protocol r/w.*/ - struct list_head pending; - struct list_head processing; - u8 *free_ioreqs_buf; /* 4-byte aligned */ - u8 *pallocated_free_ioreqs_buf; - struct intf_hdl intf; -}; - -u8 r8712_read8(struct _adapter *adapter, u32 addr); -u16 r8712_read16(struct _adapter *adapter, u32 addr); -u32 r8712_read32(struct _adapter *adapter, u32 addr); -void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -void r8712_write8(struct _adapter *adapter, u32 addr, u8 val); -void r8712_write16(struct _adapter *adapter, u32 addr, u16 val); -void r8712_write32(struct _adapter *adapter, u32 addr, u32 val); -void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); -/*ioreq */ -uint r8712_alloc_io_queue(struct _adapter *adapter); -void r8712_free_io_queue(struct _adapter *adapter); - -#endif /*_RTL871X_IO_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_ioctl.h b/drivers/staging/rtl8712/rtl871x_ioctl.h deleted file mode 100644 index d6332a8c7f4f71d7823d7d9a622028c213fe5f49..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ioctl.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IOCTL_H -#define __IOCTL_H - -#include "osdep_service.h" -#include "drv_types.h" - -#ifndef OID_802_11_CAPABILITY - #define OID_802_11_CAPABILITY 0x0d010122 -#endif - -#ifndef OID_802_11_PMKID - #define OID_802_11_PMKID 0x0d010123 -#endif - -/* For DDK-defined OIDs*/ -#define OID_NDIS_SEG1 0x00010100 -#define OID_NDIS_SEG2 0x00010200 -#define OID_NDIS_SEG3 0x00020100 -#define OID_NDIS_SEG4 0x01010100 -#define OID_NDIS_SEG5 0x01020100 -#define OID_NDIS_SEG6 0x01020200 -#define OID_NDIS_SEG7 0xFD010100 -#define OID_NDIS_SEG8 0x0D010100 -#define OID_NDIS_SEG9 0x0D010200 -#define OID_NDIS_SEG10 0x0D020200 -#define SZ_OID_NDIS_SEG1 23 -#define SZ_OID_NDIS_SEG2 3 -#define SZ_OID_NDIS_SEG3 6 -#define SZ_OID_NDIS_SEG4 6 -#define SZ_OID_NDIS_SEG5 4 -#define SZ_OID_NDIS_SEG6 8 -#define SZ_OID_NDIS_SEG7 7 -#define SZ_OID_NDIS_SEG8 36 -#define SZ_OID_NDIS_SEG9 24 -#define SZ_OID_NDIS_SEG10 19 - -/* For Realtek-defined OIDs*/ -#define OID_MP_SEG1 0xFF871100 -#define OID_MP_SEG2 0xFF818000 -#define OID_MP_SEG3 0xFF818700 -#define OID_MP_SEG4 0xFF011100 - -enum oid_type { - QUERY_OID, - SET_OID -}; - -struct oid_funs_node { - unsigned int oid_start; /*the starting number for OID*/ - unsigned int oid_end; /*the ending number for OID*/ - struct oid_obj_priv *node_array; - unsigned int array_sz; /*the size of node_array*/ - int query_counter; /*count the number of query hits for this segment*/ - int set_counter; /*count the number of set hits for this segment*/ -}; - -struct oid_par_priv { - void *adapter_context; - uint oid; - void *information_buf; - unsigned long information_buf_len; - unsigned long *bytes_rw; - unsigned long *bytes_needed; - enum oid_type type_of_oid; - unsigned int dbg; -}; - -struct oid_obj_priv { - unsigned char dbg; /* 0: without OID debug message - * 1: with OID debug message - */ - uint (*oidfuns)(struct oid_par_priv *poid_par_priv); -}; - -uint oid_null_function(struct oid_par_priv *poid_par_priv); - -extern struct iw_handler_def r871x_handlers_def; - -uint drv_query_info(struct net_device *MiniportAdapterContext, - uint Oid, - void *InformationBuffer, - u32 InformationBufferLength, - u32 *BytesWritten, - u32 *BytesNeeded); - -uint drv_set_info(struct net_device *MiniportAdapterContext, - uint Oid, - void *InformationBuffer, - u32 InformationBufferLength, - u32 *BytesRead, - u32 *BytesNeeded); - -#endif diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c deleted file mode 100644 index 0653aa27b1fa29ca4f3ecfe34da3321d7eabc510..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ /dev/null @@ -1,2275 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_ioctl_linux.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_IOCTL_LINUX_C_ -#define _RTL871X_MP_IOCTL_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wlan_bssdef.h" -#include "rtl871x_debug.h" -#include "wifi.h" -#include "rtl871x_mlme.h" -#include "rtl871x_ioctl.h" -#include "rtl871x_ioctl_set.h" -#include "rtl871x_mp_ioctl.h" -#include "mlme_osdep.h" -#include <linux/wireless.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/semaphore.h> -#include <net/iw_handler.h> -#include <linux/if_arp.h> -#include <linux/etherdevice.h> - -#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E) - -#define SCAN_ITEM_SIZE 768 -#define MAX_CUSTOM_LEN 64 -#define RATE_COUNT 4 - -static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000, - 6000000, 9000000, 12000000, 18000000, - 24000000, 36000000, 48000000, 54000000}; - -static const long ieee80211_wlan_frequencies[] = { - 2412, 2417, 2422, 2427, - 2432, 2437, 2442, 2447, - 2452, 2457, 2462, 2467, - 2472, 2484 -}; - -void r8712_indicate_wx_assoc_event(struct _adapter *padapter) -{ - union iwreq_data wrqu; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN); - wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); -} - -void r8712_indicate_wx_disassoc_event(struct _adapter *padapter) -{ - union iwreq_data wrqu; - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - eth_zero_addr(wrqu.ap_addr.sa_data); - wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL); -} - -static inline void handle_pairwise_key(struct sta_info *psta, - struct ieee_param *param, - struct _adapter *padapter) -{ - /* pairwise key */ - memcpy(psta->x_UncstKey.skey, param->u.crypt.key, - (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len)); - if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */ - memcpy(psta->tkiptxmickey. skey, - ¶m->u.crypt.key[16], 8); - memcpy(psta->tkiprxmickey. skey, - ¶m->u.crypt.key[24], 8); - padapter->securitypriv. busetkipkey = false; - mod_timer(&padapter->securitypriv.tkip_timer, - jiffies + msecs_to_jiffies(50)); - } - r8712_setstakey_cmd(padapter, (unsigned char *)psta, true); -} - -static inline void handle_group_key(struct ieee_param *param, - struct _adapter *padapter) -{ - union Keytype *gk = padapter->securitypriv.XGrpKey; - union Keytype *gtk = padapter->securitypriv.XGrptxmickey; - union Keytype *grk = padapter->securitypriv.XGrprxmickey; - - if (param->u.crypt.idx > 0 && - param->u.crypt.idx < 3) { - /* group key idx is 1 or 2 */ - memcpy(gk[param->u.crypt.idx - 1].skey, - param->u.crypt.key, - (param->u.crypt.key_len > 16 ? 16 : - param->u.crypt.key_len)); - memcpy(gtk[param->u.crypt.idx - 1].skey, - ¶m->u.crypt.key[16], 8); - memcpy(grk[param->u.crypt.idx - 1].skey, - ¶m->u.crypt.key[24], 8); - padapter->securitypriv.binstallGrpkey = true; - r8712_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx); - if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) { - if (padapter->registrypriv.power_mgnt != padapter->pwrctrlpriv.pwr_mode) - mod_timer(&padapter->mlmepriv.dhcp_timer, - jiffies + msecs_to_jiffies(60000)); - } - } -} - -static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info, - struct wlan_network *pnetwork, - struct iw_event *iwe, - char *start, char *stop) -{ - /* parsing WPA/WPA2 IE */ - u8 buf[MAX_WPA_IE_LEN]; - u8 wpa_ie[255], rsn_ie[255]; - u16 wpa_len = 0, rsn_len = 0; - int n, i; - - r8712_get_sec_ie(pnetwork->network.IEs, - pnetwork->network.IELength, rsn_ie, &rsn_len, - wpa_ie, &wpa_len); - if (wpa_len > 0) { - memset(buf, 0, MAX_WPA_IE_LEN); - n = sprintf(buf, "wpa_ie="); - for (i = 0; i < wpa_len; i++) { - n += scnprintf(buf + n, MAX_WPA_IE_LEN - n, - "%02x", wpa_ie[i]); - if (n == MAX_WPA_IE_LEN - 1) - break; - } - memset(iwe, 0, sizeof(*iwe)); - iwe->cmd = IWEVCUSTOM; - iwe->u.data.length = (u16)strlen(buf); - start = iwe_stream_add_point(info, start, stop, iwe, buf); - memset(iwe, 0, sizeof(*iwe)); - iwe->cmd = IWEVGENIE; - iwe->u.data.length = (u16)wpa_len; - start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie); - } - if (rsn_len > 0) { - memset(buf, 0, MAX_WPA_IE_LEN); - n = sprintf(buf, "rsn_ie="); - for (i = 0; i < rsn_len; i++) { - n += scnprintf(buf + n, MAX_WPA_IE_LEN - n, - "%02x", rsn_ie[i]); - if (n == MAX_WPA_IE_LEN - 1) - break; - } - memset(iwe, 0, sizeof(*iwe)); - iwe->cmd = IWEVCUSTOM; - iwe->u.data.length = strlen(buf); - start = iwe_stream_add_point(info, start, stop, iwe, buf); - memset(iwe, 0, sizeof(*iwe)); - iwe->cmd = IWEVGENIE; - iwe->u.data.length = rsn_len; - start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie); - } - - return start; -} - -static noinline_for_stack char *translate_scan_wps(struct iw_request_info *info, - struct wlan_network *pnetwork, - struct iw_event *iwe, - char *start, char *stop) -{ - /* parsing WPS IE */ - u8 wps_ie[512]; - uint wps_ielen; - - if (r8712_get_wps_ie(pnetwork->network.IEs, pnetwork->network.IELength, wps_ie, &wps_ielen)) { - if (wps_ielen > 2) { - iwe->cmd = IWEVGENIE; - iwe->u.data.length = (u16)wps_ielen; - start = iwe_stream_add_point(info, start, stop, iwe, wps_ie); - } - } - - return start; -} - -static char *translate_scan(struct _adapter *padapter, - struct iw_request_info *info, - struct wlan_network *pnetwork, - char *start, char *stop) -{ - struct iw_event iwe; - char *current_val; - s8 *p; - u32 i = 0, ht_ielen = 0; - u16 cap, ht_cap = false; - u8 rssi; - - if ((pnetwork->network.Configuration.DSConfig < 1) || - (pnetwork->network.Configuration.DSConfig > 14)) { - if (pnetwork->network.Configuration.DSConfig < 1) - pnetwork->network.Configuration.DSConfig = 1; - else - pnetwork->network.Configuration.DSConfig = 14; - } - /* AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - /* Add the ESSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, - pnetwork->network.Ssid.Ssid); - /* parsing HT_CAP_IE */ - p = r8712_get_ie(&pnetwork->network.IEs[12], WLAN_EID_HT_CAPABILITY, - &ht_ielen, pnetwork->network.IELength - 12); - if (p && ht_ielen > 0) - ht_cap = true; - /* Add the protocol name */ - iwe.cmd = SIOCGIWNAME; - if (r8712_is_cckratesonly_included(pnetwork->network.rates)) { - if (ht_cap) - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn"); - else - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b"); - } else if (r8712_is_cckrates_included(pnetwork->network.rates)) { - if (ht_cap) - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn"); - else - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg"); - } else { - if (ht_cap) - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn"); - else - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g"); - } - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs), 2); - le16_to_cpus(&cap); - if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_ESS)) { - if (cap & WLAN_CAPABILITY_ESS) - iwe.u.mode = (u32)IW_MODE_MASTER; - else - iwe.u.mode = (u32)IW_MODE_ADHOC; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); - } - /* Add frequency/channel */ - iwe.cmd = SIOCGIWFREQ; - { - /* check legal index */ - u8 dsconfig = pnetwork->network.Configuration.DSConfig; - - if (dsconfig >= 1 && dsconfig <= sizeof(ieee80211_wlan_frequencies) / sizeof(long)) - iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[dsconfig - 1] * 100000); - else - iwe.u.freq.m = 0; - } - iwe.u.freq.e = (s16)1; - iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig; - start = iwe_stream_add_event(info, start, stop, &iwe, - IW_EV_FREQ_LEN); - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (cap & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED | IW_ENCODE_NOKEY); - else - iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED); - iwe.u.data.length = (u16)0; - start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); - /*Add basic and extended rates */ - current_val = start + iwe_stream_lcp_len(info); - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = 0; - i = 0; - while (pnetwork->network.rates[i] != 0) { - /* Bit rate given in 500 kb/s units */ - iwe.u.bitrate.value = (pnetwork->network.rates[i++] & 0x7F) * 500000; - current_val = iwe_stream_add_value(info, start, current_val, stop, &iwe, - IW_EV_PARAM_LEN); - } - /* Check if we added any event */ - if ((current_val - start) > iwe_stream_lcp_len(info)) - start = current_val; - - start = translate_scan_wpa(info, pnetwork, &iwe, start, stop); - - start = translate_scan_wps(info, pnetwork, &iwe, start, stop); - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi); - /* we only update signal_level (signal strength) that is rssi. */ - iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID); - iwe.u.qual.level = rssi; /* signal strength */ - iwe.u.qual.qual = 0; /* signal quality */ - iwe.u.qual.noise = 0; /* noise level */ - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); - /* how to translate rssi to ?% */ - return start; -} - -static int wpa_set_auth_algs(struct net_device *dev, u32 value) -{ - struct _adapter *padapter = netdev_priv(dev); - int ret = 0; - - if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) { - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeAutoSwitch; - padapter->securitypriv.AuthAlgrthm = 3; - } else if (value & AUTH_ALG_SHARED_KEY) { - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared; - padapter->securitypriv.AuthAlgrthm = 1; - } else if (value & AUTH_ALG_OPEN_SYSTEM) { - if (padapter->securitypriv.ndisauthtype < - Ndis802_11AuthModeWPAPSK) { - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeOpen; - padapter->securitypriv.AuthAlgrthm = 0; - } - } else { - ret = -EINVAL; - } - return ret; -} - -static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, - u32 param_len) -{ - int ret = 0; - u32 wep_key_idx, wep_key_len = 0; - struct NDIS_802_11_WEP *pwep = NULL; - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - param->u.crypt.err = 0; - param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; - if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) + - param->u.crypt.key_len) - return -EINVAL; - if (!is_broadcast_ether_addr(param->sta_addr)) - return -EINVAL; - - if (param->u.crypt.idx >= WEP_KEYS) { - /* for large key indices, set the default (0) */ - param->u.crypt.idx = 0; - } - if (strcmp(param->u.crypt.alg, "WEP") == 0) { - netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__); - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - padapter->securitypriv.PrivacyAlgrthm = _WEP40_; - padapter->securitypriv.XGrpPrivacy = _WEP40_; - wep_key_idx = param->u.crypt.idx; - wep_key_len = param->u.crypt.key_len; - if (wep_key_idx >= WEP_KEYS) - wep_key_idx = 0; - if (wep_key_len <= 0) - return -EINVAL; - - wep_key_len = wep_key_len <= 5 ? 5 : 13; - pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC); - if (!pwep) - return -ENOMEM; - pwep->KeyLength = wep_key_len; - pwep->Length = wep_key_len + - offsetof(struct NDIS_802_11_WEP, KeyMaterial); - if (wep_key_len == 13) { - padapter->securitypriv.PrivacyAlgrthm = _WEP104_; - padapter->securitypriv.XGrpPrivacy = _WEP104_; - } - pwep->KeyIndex = wep_key_idx; - pwep->KeyIndex |= 0x80000000; - memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); - if (param->u.crypt.set_tx) { - if (r8712_set_802_11_add_wep(padapter, pwep)) - ret = -EOPNOTSUPP; - } else { - /* don't update "psecuritypriv->PrivacyAlgrthm" and - * "psecuritypriv->PrivacyKeyIndex=keyid", but can - * r8712_set_key to fw/cam - */ - if (wep_key_idx >= WEP_KEYS) { - ret = -EOPNOTSUPP; - goto exit; - } - memcpy(&psecuritypriv->DefKey[wep_key_idx].skey[0], - pwep->KeyMaterial, - pwep->KeyLength); - psecuritypriv->DefKeylen[wep_key_idx] = - pwep->KeyLength; - r8712_set_key(padapter, psecuritypriv, wep_key_idx); - } - goto exit; - } - if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */ - struct sta_info *psta, *pbcmc_sta; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *spriv = &padapter->securitypriv; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | - WIFI_MP_STATE)) { /* sta mode */ - psta = r8712_get_stainfo(pstapriv, - get_bssid(pmlmepriv)); - if (psta) { - psta->ieee8021x_blocked = false; - if (spriv->ndisencryptstatus == - Ndis802_11Encryption2Enabled || - spriv->ndisencryptstatus == - Ndis802_11Encryption3Enabled) - psta->XPrivacy = spriv->PrivacyAlgrthm; - if (param->u.crypt.set_tx == 1) - handle_pairwise_key(psta, param, - padapter); - else /* group key */ - handle_group_key(param, padapter); - } - pbcmc_sta = r8712_get_bcmc_stainfo(padapter); - if (pbcmc_sta) { - pbcmc_sta->ieee8021x_blocked = false; - if (spriv->ndisencryptstatus == - Ndis802_11Encryption2Enabled || - spriv->ndisencryptstatus == - Ndis802_11Encryption3Enabled) - pbcmc_sta->XPrivacy = - spriv->PrivacyAlgrthm; - } - } - } -exit: - kfree(pwep); - return ret; -} - -static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie, - unsigned short ielen) -{ - u8 *buf = NULL; - int group_cipher = 0, pairwise_cipher = 0; - int ret = 0; - - if (ielen > MAX_WPA_IE_LEN || !pie) - return -EINVAL; - if (ielen) { - buf = kmemdup(pie, ielen, GFP_ATOMIC); - if (!buf) - return -ENOMEM; - if (ielen < RSN_HEADER_LEN) { - ret = -EINVAL; - goto exit; - } - if (r8712_parse_wpa_ie(buf, ielen, &group_cipher, - &pairwise_cipher) == 0) { - padapter->securitypriv.AuthAlgrthm = 2; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPAPSK; - } - if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher, - &pairwise_cipher) == 0) { - padapter->securitypriv.AuthAlgrthm = 2; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPA2PSK; - } - switch (group_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.XGrpPrivacy = _WEP40_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.XGrpPrivacy = _TKIP_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.XGrpPrivacy = _AES_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.XGrpPrivacy = _WEP104_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - } - switch (pairwise_cipher) { - case WPA_CIPHER_NONE: - padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled; - break; - case WPA_CIPHER_WEP40: - padapter->securitypriv.PrivacyAlgrthm = _WEP40_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - case WPA_CIPHER_TKIP: - padapter->securitypriv.PrivacyAlgrthm = _TKIP_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled; - break; - case WPA_CIPHER_CCMP: - padapter->securitypriv.PrivacyAlgrthm = _AES_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled; - break; - case WPA_CIPHER_WEP104: - padapter->securitypriv.PrivacyAlgrthm = _WEP104_; - padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled; - break; - } - padapter->securitypriv.wps_phase = false; - {/* set wps_ie */ - u16 cnt = 0; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - while (cnt < ielen) { - eid = buf[cnt]; - - if ((eid == WLAN_EID_VENDOR_SPECIFIC) && - (!memcmp(&buf[cnt + 2], wps_oui, 4))) { - netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n"); - padapter->securitypriv.wps_ie_len = - ((buf[cnt + 1] + 2) < - (MAX_WPA_IE_LEN << 2)) ? - (buf[cnt + 1] + 2) : - (MAX_WPA_IE_LEN << 2); - memcpy(padapter->securitypriv.wps_ie, - &buf[cnt], - padapter->securitypriv.wps_ie_len); - padapter->securitypriv.wps_phase = - true; - netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n"); - cnt += buf[cnt + 1] + 2; - break; - } - - cnt += buf[cnt + 1] + 2; - } - } - } -exit: - kfree(buf); - return ret; -} - -static int r8711_wx_get_name(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - u32 ht_ielen = 0; - char *p; - u8 ht_cap = false; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - u8 *prates; - - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == true) { - /* parsing HT_CAP_IE */ - p = r8712_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY, - &ht_ielen, pcur_bss->IELength - 12); - if (p && ht_ielen > 0) - ht_cap = true; - prates = pcur_bss->rates; - if (r8712_is_cckratesonly_included(prates)) { - if (ht_cap) - snprintf(wrqu->name, IFNAMSIZ, - "IEEE 802.11bn"); - else - snprintf(wrqu->name, IFNAMSIZ, - "IEEE 802.11b"); - } else if (r8712_is_cckrates_included(prates)) { - if (ht_cap) - snprintf(wrqu->name, IFNAMSIZ, - "IEEE 802.11bgn"); - else - snprintf(wrqu->name, IFNAMSIZ, - "IEEE 802.11bg"); - } else { - if (ht_cap) - snprintf(wrqu->name, IFNAMSIZ, - "IEEE 802.11gn"); - else - snprintf(wrqu->name, IFNAMSIZ, - "IEEE 802.11g"); - } - } else { - snprintf(wrqu->name, IFNAMSIZ, "unassociated"); - } - return 0; -} - -static const long frequency_list[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, - 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980, - 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, - 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, - 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805, - 5825 -}; - -static int r8711_wx_set_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct iw_freq *fwrq = &wrqu->freq; - int rc = 0; - -/* If setting by frequency, convert to a channel */ - if ((fwrq->e == 1) && (fwrq->m >= 241200000) && (fwrq->m <= 248700000)) { - int f = fwrq->m / 100000; - int c = 0; - - while ((c < 14) && (f != frequency_list[c])) - c++; - fwrq->e = 0; - fwrq->m = c + 1; - } - /* Setting by channel number */ - if ((fwrq->m > 14) || (fwrq->e > 0)) { - rc = -EOPNOTSUPP; - } else { - int channel = fwrq->m; - - if ((channel < 1) || (channel > 14)) { - rc = -EINVAL; - } else { - /* Yes ! We can set it !!! */ - padapter->registrypriv.channel = channel; - } - } - return rc; -} - -static int r8711_wx_get_freq(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - - if (!check_fwstate(pmlmepriv, _FW_LINKED)) - return -ENOLINK; - - wrqu->freq.m = ieee80211_wlan_frequencies[ - pcur_bss->Configuration.DSConfig - 1] * 100000; - wrqu->freq.e = 1; - wrqu->freq.i = pcur_bss->Configuration.DSConfig; - - return 0; -} - -static int r8711_wx_set_mode(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct _adapter *padapter = netdev_priv(dev); - enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType; - - switch (wrqu->mode) { - case IW_MODE_AUTO: - networkType = Ndis802_11AutoUnknown; - break; - case IW_MODE_ADHOC: - networkType = Ndis802_11IBSS; - break; - case IW_MODE_MASTER: - networkType = Ndis802_11APMode; - break; - case IW_MODE_INFRA: - networkType = Ndis802_11Infrastructure; - break; - default: - return -EINVAL; - } - if (Ndis802_11APMode == networkType) - r8712_setopmode_cmd(padapter, networkType); - else - r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown); - - r8712_set_802_11_infrastructure_mode(padapter, networkType); - return 0; -} - -static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - wrqu->mode = IW_MODE_INFRA; - else if (check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)) - wrqu->mode = IW_MODE_ADHOC; - else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - wrqu->mode = IW_MODE_MASTER; - else - wrqu->mode = IW_MODE_AUTO; - return 0; -} - -static int r871x_wx_set_pmkid(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct iw_pmksa *pPMK = (struct iw_pmksa *) extra; - struct RT_PMKID_LIST *pl = psecuritypriv->PMKIDList; - u8 strZeroMacAddress[ETH_ALEN] = {0x00}; - u8 strIssueBssid[ETH_ALEN] = {0x00}; - u8 j, blInserted = false; - int intReturn = false; - -/* - * There are the BSSID information in the bssid.sa_data array. - * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear - * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the - * wpa_supplicant wants to add a PMKID/BSSID to driver. - * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to - * remove a PMKID/BSSID from driver. - */ - if (!pPMK) - return -EINVAL; - memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN); - switch (pPMK->cmd) { - case IW_PMKSA_ADD: - if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN)) - return intReturn; - intReturn = true; - blInserted = false; - /* overwrite PMKID */ - for (j = 0; j < NUM_PMKID_CACHE; j++) { - if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) { - /* BSSID is matched, the same AP => rewrite - * with new PMKID. - */ - netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n", - __func__); - memcpy(pl[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); - pl[j].bUsed = true; - psecuritypriv->PMKIDIndex = j + 1; - blInserted = true; - break; - } - } - if (!blInserted) { - /* Find a new entry */ - netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n", - __func__, psecuritypriv->PMKIDIndex); - memcpy(pl[psecuritypriv->PMKIDIndex].Bssid, - strIssueBssid, ETH_ALEN); - memcpy(pl[psecuritypriv->PMKIDIndex].PMKID, - pPMK->pmkid, IW_PMKID_LEN); - pl[psecuritypriv->PMKIDIndex].bUsed = true; - psecuritypriv->PMKIDIndex++; - if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE) - psecuritypriv->PMKIDIndex = 0; - } - break; - case IW_PMKSA_REMOVE: - intReturn = true; - for (j = 0; j < NUM_PMKID_CACHE; j++) { - if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) { - /* BSSID is matched, the same AP => Remove - * this PMKID information and reset it. - */ - eth_zero_addr(pl[j].Bssid); - pl[j].bUsed = false; - break; - } - } - break; - case IW_PMKSA_FLUSH: - memset(psecuritypriv->PMKIDList, 0, - sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE); - psecuritypriv->PMKIDIndex = 0; - intReturn = true; - break; - default: - netdev_info(dev, "r8712u: %s: unknown Command\n", __func__); - intReturn = false; - break; - } - return intReturn; -} - -static int r8711_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->sens.value = 0; - wrqu->sens.fixed = 0; /* no auto select */ - wrqu->sens.disabled = 1; - return 0; -} - -static int r8711_wx_get_range(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - u16 val; - int i; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - /* Let's try to keep this struct in the same order as in - * linux/include/wireless.h - */ - - /* TODO: See what values we can set, and remove the ones we can't - * set, or fill them with some default data. - */ - /* ~5 Mb/s real (802.11b) */ - range->throughput = 5 * 1000 * 1000; - /* TODO: 8711 sensitivity ? */ - /* signal level threshold range */ - /* percent values between 0 and 100. */ - range->max_qual.qual = 100; - range->max_qual.level = 100; - range->max_qual.noise = 100; - range->max_qual.updated = 7; /* Updated all three */ - range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ - range->avg_qual.level = 0x100 - 78; - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - range->num_bitrates = RATE_COUNT; - for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) - range->bitrate[i] = rtl8180_rates[i]; - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - range->pm_capa = 0; - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; - range->num_channels = 14; - for (i = 0, val = 0; i < 14; i++) { - /* Include only legal frequencies for some countries */ - range->freq[val].i = i + 1; - range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; - range->freq[val].e = 1; - val++; - if (val == IW_MAX_FREQUENCIES) - break; - } - range->num_frequency = val; - range->enc_capa = IW_ENC_CAPA_WPA | - IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | - IW_ENC_CAPA_CIPHER_CCMP; - return 0; -} - -static int r8711_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -static int r871x_wx_set_priv(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra) -{ - int ret = 0, len = 0; - char *ext; - struct _adapter *padapter = netdev_priv(dev); - struct iw_point *dwrq = (struct iw_point *)awrq; - - len = dwrq->length; - ext = strndup_user(dwrq->pointer, len); - if (IS_ERR(ext)) - return PTR_ERR(ext); - - if (!strcasecmp(ext, "RSSI")) { - /*Return received signal strength indicator in -db for */ - /* current AP */ - /*<ssid> Rssi xx */ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct wlan_network *pcur_network = &pmlmepriv->cur_network; - /*static u8 xxxx; */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - sprintf(ext, "%s rssi %d", - pcur_network->network.Ssid.Ssid, - /*(xxxx=xxxx+10) */ - ((padapter->recvpriv.fw_rssi) >> 1) - 95 - /*pcur_network->network.Rssi */ - ); - } else { - sprintf(ext, "OK"); - } - } else if (!strcasecmp(ext, "LINKSPEED")) { - /*Return link speed in MBPS */ - /*LinkSpeed xx */ - union iwreq_data wrqd; - int ret_inner; - int mbps; - - ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra); - if (ret_inner != 0) - mbps = 0; - else - mbps = wrqd.bitrate.value / 1000000; - sprintf(ext, "LINKSPEED %d", mbps); - } else if (!strcasecmp(ext, "MACADDR")) { - /*Return mac address of the station */ - /* Macaddr = xx:xx:xx:xx:xx:xx */ - sprintf(ext, "MACADDR = %pM", dev->dev_addr); - } else if (!strcasecmp(ext, "SCAN-ACTIVE")) { - /*Set scan type to active */ - /*OK if successful */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->passive_mode = 1; - sprintf(ext, "OK"); - } else if (!strcasecmp(ext, "SCAN-PASSIVE")) { - /*Set scan type to passive */ - /*OK if successful */ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->passive_mode = 0; - sprintf(ext, "OK"); - } else if (!strncmp(ext, "DCE-E", 5)) { - /*Set scan type to passive */ - /*OK if successful */ - r8712_disconnectCtrlEx_cmd(padapter - , 1 /*u32 enableDrvCtrl */ - , 5 /*u32 tryPktCnt */ - , 100 /*u32 tryPktInterval */ - , 5000 /*u32 firstStageTO */ - ); - sprintf(ext, "OK"); - } else if (!strncmp(ext, "DCE-D", 5)) { - /*Set scan type to passive */ - /*OK if successfu */ - r8712_disconnectCtrlEx_cmd(padapter - , 0 /*u32 enableDrvCtrl */ - , 5 /*u32 tryPktCnt */ - , 100 /*u32 tryPktInterval */ - , 5000 /*u32 firstStageTO */ - ); - sprintf(ext, "OK"); - } else { - netdev_info(dev, "r8712u: %s: unknown Command %s.\n", __func__, ext); - goto FREE_EXT; - } - if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (__u16)(strlen(ext) + 1)))) - ret = -EFAULT; - -FREE_EXT: - kfree(ext); - return ret; -} - -/* set bssid flow - * s1. set_802_11_infrastructure_mode() - * s2. set_802_11_authentication_mode() - * s3. set_802_11_encryption_mode() - * s4. set_802_11_bssid() - * - * This function intends to handle the Set AP command, which specifies the - * MAC# of a preferred Access Point. - * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl. - * - * For this operation to succeed, there is no need for the interface to be up. - * - */ -static int r8711_wx_set_wap(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *awrq, char *extra) -{ - int ret = -EINPROGRESS; - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct sockaddr *temp = (struct sockaddr *)awrq; - unsigned long irqL; - struct list_head *phead; - u8 *dst_bssid; - struct wlan_network *pnetwork = NULL; - enum NDIS_802_11_AUTHENTICATION_MODE authmode; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - return -EBUSY; - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - return ret; - if (temp->sa_family != ARPHRD_ETHER) - return -EINVAL; - authmode = padapter->securitypriv.ndisauthtype; - spin_lock_irqsave(&queue->lock, irqL); - phead = &queue->queue; - pmlmepriv->pscanned = phead->next; - while (1) { - if (end_of_queue_search(phead, pmlmepriv->pscanned)) - break; - pnetwork = container_of(pmlmepriv->pscanned, - struct wlan_network, list); - pmlmepriv->pscanned = pmlmepriv->pscanned->next; - dst_bssid = pnetwork->network.MacAddress; - if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) { - r8712_set_802_11_infrastructure_mode(padapter, - pnetwork->network.InfrastructureMode); - break; - } - } - spin_unlock_irqrestore(&queue->lock, irqL); - if (!ret) { - if (!r8712_set_802_11_authentication_mode(padapter, authmode)) { - ret = -ENOMEM; - } else { - if (!r8712_set_802_11_bssid(padapter, temp->sa_data)) - ret = -1; - } - } - return ret; -} - -static int r8711_wx_get_wap(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) - ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress); - else - eth_zero_addr(wrqu->ap_addr.sa_data); - return 0; -} - -static int r871x_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct _adapter *padapter = netdev_priv(dev); - struct iw_mlme *mlme = (struct iw_mlme *) extra; - - if (!mlme) - return -1; - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - if (!r8712_set_802_11_disassociate(padapter)) - ret = -1; - break; - case IW_MLME_DISASSOC: - if (!r8712_set_802_11_disassociate(padapter)) - ret = -1; - break; - default: - return -EOPNOTSUPP; - } - return ret; -} - -/* - * - * This function intends to handle the Set Scan command. - * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl. - * - * For this operation to succeed, the interface is brought Up beforehand. - * - */ -static int r8711_wx_set_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 status = true; - - if (padapter->driver_stopped) { - netdev_info(dev, "In %s: driver_stopped=%d\n", - __func__, padapter->driver_stopped); - return -1; - } - if (!padapter->bup) - return -ENETDOWN; - if (!padapter->hw_init_completed) - return -1; - if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) || - (pmlmepriv->sitesurveyctrl.traffic_busy)) - return 0; - if (wrqu->data.length == sizeof(struct iw_scan_req)) { - struct iw_scan_req *req = (struct iw_scan_req *)extra; - - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct ndis_802_11_ssid ssid; - unsigned long irqL; - u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE); - - memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid)); - memcpy(ssid.Ssid, req->essid, len); - ssid.SsidLength = len; - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | - _FW_UNDER_LINKING)) || - (pmlmepriv->sitesurveyctrl.traffic_busy)) { - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - status = false; - } else { - status = r8712_sitesurvey_cmd(padapter, &ssid); - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - } - } else { - status = r8712_set_802_11_bssid_list_scan(padapter); - } - if (!status) - return -1; - return 0; -} - -static int r8711_wx_get_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - unsigned long irqL; - struct list_head *plist, *phead; - char *ev = extra; - char *stop = ev + wrqu->data.length; - u32 ret = 0, cnt = 0; - - if (padapter->driver_stopped) - return -EINVAL; - while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) { - msleep(30); - cnt++; - if (cnt > 100) - break; - } - spin_lock_irqsave(&queue->lock, irqL); - phead = &queue->queue; - plist = phead->next; - while (1) { - if (end_of_queue_search(phead, plist)) - break; - if ((stop - ev) < SCAN_ITEM_SIZE) { - ret = -E2BIG; - break; - } - pnetwork = container_of(plist, struct wlan_network, list); - ev = translate_scan(padapter, a, pnetwork, ev, stop); - plist = plist->next; - } - spin_unlock_irqrestore(&queue->lock, irqL); - wrqu->data.length = ev - extra; - wrqu->data.flags = 0; - return ret; -} - -/* set ssid flow - * s1. set_802_11_infrastructure_mode() - * s2. set_802_11_authenticaion_mode() - * s3. set_802_11_encryption_mode() - * s4. set_802_11_ssid() - * - * This function intends to handle the Set ESSID command. - * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl. - * - * For this operation to succeed, there is no need for the interface to be Up. - * - */ -static int r8711_wx_set_essid(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - enum NDIS_802_11_AUTHENTICATION_MODE authmode; - struct ndis_802_11_ssid ndis_ssid; - u8 *dst_ssid, *src_ssid; - struct list_head *phead; - u32 len; - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - return -EBUSY; - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - return 0; - if (wrqu->essid.length > IW_ESSID_MAX_SIZE) - return -E2BIG; - authmode = padapter->securitypriv.ndisauthtype; - if (wrqu->essid.flags && wrqu->essid.length) { - len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? - wrqu->essid.length : IW_ESSID_MAX_SIZE; - memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid)); - ndis_ssid.SsidLength = len; - memcpy(ndis_ssid.Ssid, extra, len); - src_ssid = ndis_ssid.Ssid; - phead = &queue->queue; - pmlmepriv->pscanned = phead->next; - while (1) { - if (end_of_queue_search(phead, pmlmepriv->pscanned)) - break; - pnetwork = container_of(pmlmepriv->pscanned, - struct wlan_network, list); - pmlmepriv->pscanned = pmlmepriv->pscanned->next; - dst_ssid = pnetwork->network.Ssid.Ssid; - if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) - && (pnetwork->network.Ssid.SsidLength == - ndis_ssid.SsidLength)) { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network. - InfrastructureMode - != - padapter->mlmepriv. - cur_network.network. - InfrastructureMode) - continue; - } - - r8712_set_802_11_infrastructure_mode( - padapter, - pnetwork->network.InfrastructureMode); - break; - } - } - r8712_set_802_11_authentication_mode(padapter, authmode); - r8712_set_802_11_ssid(padapter, &ndis_ssid); - } - return -EINPROGRESS; -} - -static int r8711_wx_get_essid(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - u32 len, ret = 0; - - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - len = pcur_bss->Ssid.SsidLength; - wrqu->essid.length = len; - memcpy(extra, pcur_bss->Ssid.Ssid, len); - wrqu->essid.flags = 1; - } else { - ret = -ENOLINK; - } - return ret; -} - -static int r8711_wx_set_rate(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - u32 target_rate = wrqu->bitrate.value; - u32 fixed = wrqu->bitrate.fixed; - u32 ratevalue = 0; - u8 datarates[NumRates]; - u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; - int i; - - if (target_rate == -1) { - ratevalue = 11; - goto set_rate; - } - target_rate = target_rate / 100000; - switch (target_rate) { - case 10: - ratevalue = 0; - break; - case 20: - ratevalue = 1; - break; - case 55: - ratevalue = 2; - break; - case 60: - ratevalue = 3; - break; - case 90: - ratevalue = 4; - break; - case 110: - ratevalue = 5; - break; - case 120: - ratevalue = 6; - break; - case 180: - ratevalue = 7; - break; - case 240: - ratevalue = 8; - break; - case 360: - ratevalue = 9; - break; - case 480: - ratevalue = 10; - break; - case 540: - ratevalue = 11; - break; - default: - ratevalue = 11; - break; - } -set_rate: - for (i = 0; i < NumRates; i++) { - if (ratevalue == mpdatarate[i]) { - datarates[i] = mpdatarate[i]; - if (fixed == 0) - break; - } else { - datarates[i] = 0xff; - } - } - return r8712_setdatarate_cmd(padapter, datarates); -} - -static int r8711_wx_get_rate(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network; - struct ieee80211_ht_cap *pht_capie; - unsigned char rf_type = padapter->registrypriv.rf_config; - int i; - u8 *p; - u16 rate, max_rate = 0, ht_cap = false; - u32 ht_ielen = 0; - u8 bw_40MHz = 0, short_GI = 0; - u16 mcs_rate = 0; - - i = 0; - if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) - return -ENOLINK; - p = r8712_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY, &ht_ielen, - pcur_bss->IELength - 12); - if (p && ht_ielen > 0) { - ht_cap = true; - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate, &pht_capie->mcs, 2); - bw_40MHz = (le16_to_cpu(pht_capie->cap_info) & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; - short_GI = (le16_to_cpu(pht_capie->cap_info) & - (IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; - } - while ((pcur_bss->rates[i] != 0) && - (pcur_bss->rates[i] != 0xFF)) { - rate = pcur_bss->rates[i] & 0x7F; - if (rate > max_rate) - max_rate = rate; - wrqu->bitrate.fixed = 0; /* no auto select */ - wrqu->bitrate.value = rate * 500000; - i++; - } - if (ht_cap) { - if (mcs_rate & 0x8000 /* MCS15 */ - && - rf_type == RTL8712_RF_2T2R) - max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : - ((short_GI) ? 144 : 130); - else /* default MCS7 */ - max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : - ((short_GI) ? 72 : 65); - max_rate *= 2; /* Mbps/2 */ - } - wrqu->bitrate.value = max_rate * 500000; - return 0; -} - -static int r8711_wx_get_rts(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - - wrqu->rts.value = padapter->registrypriv.rts_thresh; - wrqu->rts.fixed = 0; /* no auto select */ - return 0; -} - -static int r8711_wx_set_frag(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - - if (wrqu->frag.disabled) { - padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD; - } else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) - return -EINVAL; - padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1; - } - return 0; -} - -static int r8711_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - - wrqu->frag.value = padapter->xmitpriv.frag_len; - wrqu->frag.fixed = 0; /* no auto select */ - return 0; -} - -static int r8711_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->retry.value = 7; - wrqu->retry.fixed = 0; /* no auto select */ - wrqu->retry.disabled = 1; - return 0; -} - -static int r8711_wx_set_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - u32 key; - u32 keyindex_provided; - struct NDIS_802_11_WEP wep; - enum NDIS_802_11_AUTHENTICATION_MODE authmode; - struct iw_point *erq = &wrqu->encoding; - struct _adapter *padapter = netdev_priv(dev); - - key = erq->flags & IW_ENCODE_INDEX; - memset(&wep, 0, sizeof(struct NDIS_802_11_WEP)); - if (erq->flags & IW_ENCODE_DISABLED) { - netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__); - padapter->securitypriv.ndisencryptstatus = - Ndis802_11EncryptionDisabled; - padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_; - padapter->securitypriv.AuthAlgrthm = 0; /* open system */ - authmode = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisauthtype = authmode; - return 0; - } - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - keyindex_provided = 1; - } else { - keyindex_provided = 0; - key = padapter->securitypriv.PrivacyKeyIndex; - } - /* set authentication mode */ - if (erq->flags & IW_ENCODE_OPEN) { - netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__); - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - padapter->securitypriv.AuthAlgrthm = 0; /* open system */ - padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_; - authmode = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisauthtype = authmode; - } else if (erq->flags & IW_ENCODE_RESTRICTED) { - netdev_info(dev, - "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__); - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - padapter->securitypriv.AuthAlgrthm = 1; /* shared system */ - padapter->securitypriv.PrivacyAlgrthm = _WEP40_; - padapter->securitypriv.XGrpPrivacy = _WEP40_; - authmode = Ndis802_11AuthModeShared; - padapter->securitypriv.ndisauthtype = authmode; - } else { - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption1Enabled; - padapter->securitypriv.AuthAlgrthm = 0; /* open system */ - padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_; - padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_; - authmode = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisauthtype = authmode; - } - wep.KeyIndex = key; - if (erq->length > 0) { - wep.KeyLength = erq->length <= 5 ? 5 : 13; - wep.Length = wep.KeyLength + - offsetof(struct NDIS_802_11_WEP, KeyMaterial); - } else { - wep.KeyLength = 0; - if (keyindex_provided == 1) { /* set key_id only, no given - * KeyMaterial(erq->length==0). - */ - padapter->securitypriv.PrivacyKeyIndex = key; - switch (padapter->securitypriv.DefKeylen[key]) { - case 5: - padapter->securitypriv.PrivacyAlgrthm = - _WEP40_; - break; - case 13: - padapter->securitypriv.PrivacyAlgrthm = - _WEP104_; - break; - default: - padapter->securitypriv.PrivacyAlgrthm = - _NO_PRIVACY_; - break; - } - return 0; - } - } - wep.KeyIndex |= 0x80000000; /* transmit key */ - memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); - if (r8712_set_802_11_add_wep(padapter, &wep)) - return -EOPNOTSUPP; - return 0; -} - -static int r8711_wx_get_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - uint key; - struct _adapter *padapter = netdev_priv(dev); - struct iw_point *erq = &wrqu->encoding; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - union Keytype *dk = padapter->securitypriv.DefKey; - - if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - } - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - } else { - key = padapter->securitypriv.PrivacyKeyIndex; - } - erq->flags = key + 1; - switch (padapter->securitypriv.ndisencryptstatus) { - case Ndis802_11EncryptionNotSupported: - case Ndis802_11EncryptionDisabled: - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - break; - case Ndis802_11Encryption1Enabled: - erq->length = padapter->securitypriv.DefKeylen[key]; - if (erq->length) { - memcpy(keybuf, dk[key].skey, - padapter->securitypriv.DefKeylen[key]); - erq->flags |= IW_ENCODE_ENABLED; - if (padapter->securitypriv.ndisauthtype == - Ndis802_11AuthModeOpen) - erq->flags |= IW_ENCODE_OPEN; - else if (padapter->securitypriv.ndisauthtype == - Ndis802_11AuthModeShared) - erq->flags |= IW_ENCODE_RESTRICTED; - } else { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - } - break; - case Ndis802_11Encryption2Enabled: - case Ndis802_11Encryption3Enabled: - erq->length = 16; - erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | - IW_ENCODE_NOKEY); - break; - default: - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - break; - } - return 0; -} - -static int r8711_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - wrqu->power.value = 0; - wrqu->power.fixed = 0; /* no auto select */ - wrqu->power.disabled = 1; - return 0; -} - -static int r871x_wx_set_gen_ie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - - return r871x_set_wpa_ie(padapter, extra, wrqu->data.length); -} - -static int r871x_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct iw_param *param = (struct iw_param *)&wrqu->param; - int paramid; - int paramval; - int ret = 0; - - paramid = param->flags & IW_AUTH_INDEX; - paramval = param->value; - switch (paramid) { - case IW_AUTH_WPA_VERSION: - break; - case IW_AUTH_CIPHER_PAIRWISE: - break; - case IW_AUTH_CIPHER_GROUP: - break; - case IW_AUTH_KEY_MGMT: - /* - * ??? does not use these parameters - */ - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - if (paramval) { - /* wpa_supplicant is enabling tkip countermeasure. */ - padapter->securitypriv.btkip_countermeasure = true; - } else { - /* wpa_supplicant is disabling tkip countermeasure. */ - padapter->securitypriv.btkip_countermeasure = false; - } - break; - case IW_AUTH_DROP_UNENCRYPTED: - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - if (padapter->securitypriv.ndisencryptstatus == - Ndis802_11Encryption1Enabled) { - /* it means init value, or using wep, - * ndisencryptstatus = - * Ndis802_11Encryption1Enabled, - * then it needn't reset it; - */ - break; - } - - if (paramval) { - padapter->securitypriv.ndisencryptstatus = - Ndis802_11EncryptionDisabled; - padapter->securitypriv.PrivacyAlgrthm = - _NO_PRIVACY_; - padapter->securitypriv.XGrpPrivacy = - _NO_PRIVACY_; - padapter->securitypriv.AuthAlgrthm = 0; - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeOpen; - } - break; - case IW_AUTH_80211_AUTH_ALG: - ret = wpa_set_auth_algs(dev, (u32)paramval); - break; - case IW_AUTH_WPA_ENABLED: - break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; - case IW_AUTH_PRIVACY_INVOKED: - break; - default: - return -EOPNOTSUPP; - } - - return ret; -} - -static int r871x_wx_set_enc_ext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_point *pencoding = &wrqu->encoding; - struct iw_encode_ext *pext = (struct iw_encode_ext *)extra; - struct ieee_param *param = NULL; - char *alg_name; - u32 param_len; - int ret = 0; - - switch (pext->alg) { - case IW_ENCODE_ALG_NONE: - alg_name = "none"; - break; - case IW_ENCODE_ALG_WEP: - alg_name = "WEP"; - break; - case IW_ENCODE_ALG_TKIP: - alg_name = "TKIP"; - break; - case IW_ENCODE_ALG_CCMP: - alg_name = "CCMP"; - break; - default: - return -EINVAL; - } - - param_len = sizeof(struct ieee_param) + pext->key_len; - param = kzalloc(param_len, GFP_ATOMIC); - if (!param) - return -ENOMEM; - param->cmd = IEEE_CMD_SET_ENCRYPTION; - eth_broadcast_addr(param->sta_addr); - strscpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN); - if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) - param->u.crypt.set_tx = 0; - if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - param->u.crypt.set_tx = 1; - param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1; - if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) - memcpy(param->u.crypt.seq, pext->rx_seq, 8); - if (pext->key_len) { - param->u.crypt.key_len = pext->key_len; - memcpy(param + 1, pext + 1, pext->key_len); - } - ret = wpa_set_encryption(dev, param, param_len); - kfree(param); - return ret; -} - -static int r871x_wx_get_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - if (extra) { - wrqu->data.length = 8; - wrqu->data.flags = 1; - memcpy(extra, "rtl_wifi", 8); - } - return 0; -} - -static int r8711_wx_read32(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct _adapter *padapter = netdev_priv(dev); - u32 addr; - u32 data32; - - get_user(addr, (u32 __user *)wrqu->data.pointer); - data32 = r8712_read32(padapter, addr); - put_user(data32, (u32 __user *)wrqu->data.pointer); - wrqu->data.length = (data32 & 0xffff0000) >> 16; - wrqu->data.flags = data32 & 0xffff; - get_user(addr, (u32 __user *)wrqu->data.pointer); - return 0; -} - -static int r8711_wx_write32(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct _adapter *padapter = netdev_priv(dev); - u32 addr; - u32 data32; - - get_user(addr, (u32 __user *)wrqu->data.pointer); - data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags; - r8712_write32(padapter, addr, data32); - return 0; -} - -static int dummy(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - return -EINVAL; -} - -static int r8711_drvext_hdl(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - return 0; -} - -static int r871x_mp_ioctl_hdl(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct iw_point *p = &wrqu->data; - struct oid_par_priv oid_par; - struct mp_ioctl_handler *phandler; - struct mp_ioctl_param *poidparam; - unsigned long BytesRead, BytesWritten, BytesNeeded; - u8 *pparmbuf, bset; - u16 len; - uint status; - int ret = 0; - - if ((!p->length) || (!p->pointer)) - return -EINVAL; - - bset = (u8)(p->flags & 0xFFFF); - len = p->length; - pparmbuf = memdup_user(p->pointer, len); - if (IS_ERR(pparmbuf)) - return PTR_ERR(pparmbuf); - - poidparam = (struct mp_ioctl_param *)pparmbuf; - if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) { - ret = -EINVAL; - goto _r871x_mp_ioctl_hdl_exit; - } - phandler = mp_ioctl_hdl + poidparam->subcode; - if ((phandler->paramsize != 0) && - (poidparam->len < phandler->paramsize)) { - ret = -EINVAL; - goto _r871x_mp_ioctl_hdl_exit; - } - if (phandler->oid == 0 && phandler->handler) { - status = phandler->handler(&oid_par); - } else if (phandler->handler) { - oid_par.adapter_context = padapter; - oid_par.oid = phandler->oid; - oid_par.information_buf = poidparam->data; - oid_par.information_buf_len = poidparam->len; - oid_par.dbg = 0; - BytesWritten = 0; - BytesNeeded = 0; - if (bset) { - oid_par.bytes_rw = &BytesRead; - oid_par.bytes_needed = &BytesNeeded; - oid_par.type_of_oid = SET_OID; - } else { - oid_par.bytes_rw = &BytesWritten; - oid_par.bytes_needed = &BytesNeeded; - oid_par.type_of_oid = QUERY_OID; - } - status = phandler->handler(&oid_par); - /* todo:check status, BytesNeeded, etc. */ - } else { - netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n", - __func__, poidparam->subcode, phandler->oid, - phandler->handler); - ret = -EFAULT; - goto _r871x_mp_ioctl_hdl_exit; - } - if (bset == 0x00) { /* query info */ - if (copy_to_user(p->pointer, pparmbuf, len)) - ret = -EFAULT; - } - if (status) { - ret = -EFAULT; - goto _r871x_mp_ioctl_hdl_exit; - } -_r871x_mp_ioctl_hdl_exit: - kfree(pparmbuf); - return ret; -} - -static int r871x_get_ap_info(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct iw_point *pdata = &wrqu->data; - struct wlan_network *pnetwork = NULL; - u32 cnt = 0, wpa_ielen; - unsigned long irqL; - struct list_head *plist, *phead; - unsigned char *pbuf; - u8 bssid[ETH_ALEN]; - char data[33]; - - if (padapter->driver_stopped || !pdata) - return -EINVAL; - while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | - _FW_UNDER_LINKING)) { - msleep(30); - cnt++; - if (cnt > 100) - break; - } - pdata->flags = 0; - if (pdata->length < 32) - return -EINVAL; - if (copy_from_user(data, pdata->pointer, 32)) - return -EINVAL; - data[32] = 0; - - spin_lock_irqsave(&pmlmepriv->scanned_queue.lock, irqL); - phead = &queue->queue; - plist = phead->next; - while (1) { - if (end_of_queue_search(phead, plist)) - break; - pnetwork = container_of(plist, struct wlan_network, list); - if (!mac_pton(data, bssid)) { - netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n", - (u8 *)data); - spin_unlock_irqrestore(&pmlmepriv->scanned_queue.lock, - irqL); - return -EINVAL; - } - netdev_info(dev, "r8712u: BSSID:%pM\n", bssid); - if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) { - /* BSSID match, then check if supporting wpa/wpa2 */ - pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12], - &wpa_ielen, pnetwork->network.IELength - 12); - if (pbuf && (wpa_ielen > 0)) { - pdata->flags = 1; - break; - } - pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12], - &wpa_ielen, pnetwork->network.IELength - 12); - if (pbuf && (wpa_ielen > 0)) { - pdata->flags = 2; - break; - } - } - plist = plist->next; - } - spin_unlock_irqrestore(&pmlmepriv->scanned_queue.lock, irqL); - if (pdata->length >= 34) { - if (copy_to_user((u8 __user *)pdata->pointer + 32, - (u8 *)&pdata->flags, 1)) - return -EINVAL; - } - return 0; -} - -static int r871x_set_pid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct iw_point *pdata = &wrqu->data; - - if (padapter->driver_stopped || !pdata) - return -EINVAL; - if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int))) - return -EINVAL; - return 0; -} - -static int r871x_set_chplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct _adapter *padapter = netdev_priv(dev); - struct iw_point *pdata = &wrqu->data; - int ch_plan = -1; - - if (padapter->driver_stopped || !pdata) { - ret = -EINVAL; - goto exit; - } - ch_plan = (int)*extra; - r8712_set_chplan_cmd(padapter, ch_plan); - -exit: - - return ret; -} - -static int r871x_wps_start(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct _adapter *padapter = netdev_priv(dev); - struct iw_point *pdata = &wrqu->data; - u32 u32wps_start = 0; - - if (padapter->driver_stopped || !pdata) - return -EINVAL; - if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4)) - return -EFAULT; - if (u32wps_start == 0) - u32wps_start = *extra; - if (u32wps_start == 1) /* WPS Start */ - padapter->ledpriv.LedControlHandler(padapter, - LED_CTL_START_WPS); - else if (u32wps_start == 2) /* WPS Stop because of wps success */ - padapter->ledpriv.LedControlHandler(padapter, - LED_CTL_STOP_WPS); - else if (u32wps_start == 3) /* WPS Stop because of wps fail */ - padapter->ledpriv.LedControlHandler(padapter, - LED_CTL_STOP_WPS_FAIL); - return 0; -} - -static int wpa_set_param(struct net_device *dev, u8 name, u32 value) -{ - struct _adapter *padapter = netdev_priv(dev); - - switch (name) { - case IEEE_PARAM_WPA_ENABLED: - padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */ - switch ((value) & 0xff) { - case 1: /* WPA */ - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPAPSK; /* WPA_PSK */ - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption2Enabled; - break; - case 2: /* WPA2 */ - padapter->securitypriv.ndisauthtype = - Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */ - padapter->securitypriv.ndisencryptstatus = - Ndis802_11Encryption3Enabled; - break; - } - break; - case IEEE_PARAM_TKIP_COUNTERMEASURES: - break; - case IEEE_PARAM_DROP_UNENCRYPTED: - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - break; - case IEEE_PARAM_PRIVACY_INVOKED: - break; - case IEEE_PARAM_AUTH_ALGS: - return wpa_set_auth_algs(dev, value); - case IEEE_PARAM_IEEE_802_1X: - break; - case IEEE_PARAM_WPAX_SELECT: - /* added for WPA2 mixed mode */ - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -static int wpa_mlme(struct net_device *dev, u32 command, u32 reason) -{ - struct _adapter *padapter = netdev_priv(dev); - - switch (command) { - case IEEE_MLME_STA_DEAUTH: - if (!r8712_set_802_11_disassociate(padapter)) - return -1; - break; - case IEEE_MLME_STA_DISASSOC: - if (!r8712_set_802_11_disassociate(padapter)) - return -1; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p) -{ - struct ieee_param *param; - int ret = 0; - struct _adapter *padapter = netdev_priv(dev); - - if (p->length < sizeof(struct ieee_param) || !p->pointer) - return -EINVAL; - param = memdup_user(p->pointer, p->length); - if (IS_ERR(param)) - return PTR_ERR(param); - switch (param->cmd) { - case IEEE_CMD_SET_WPA_PARAM: - ret = wpa_set_param(dev, param->u.wpa_param.name, - param->u.wpa_param.value); - break; - case IEEE_CMD_SET_WPA_IE: - ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data, - (u16)param->u.wpa_ie.len); - break; - case IEEE_CMD_SET_ENCRYPTION: - ret = wpa_set_encryption(dev, param, p->length); - break; - case IEEE_CMD_MLME: - ret = wpa_mlme(dev, param->u.mlme.command, - param->u.mlme.reason_code); - break; - default: - ret = -EOPNOTSUPP; - break; - } - if (ret == 0 && copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - kfree(param); - return ret; -} - -/* based on "driver_ipw" and for hostapd */ -int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct iwreq *wrq = (struct iwreq *)rq; - - switch (cmd) { - case RTL_IOCTL_WPA_SUPPLICANT: - return wpa_supplicant_ioctl(dev, &wrq->u.data); - default: - return -EOPNOTSUPP; - } - return 0; -} - -static iw_handler r8711_handlers[] = { - NULL, /* SIOCSIWCOMMIT */ - r8711_wx_get_name, /* SIOCGIWNAME */ - dummy, /* SIOCSIWNWID */ - dummy, /* SIOCGIWNWID */ - r8711_wx_set_freq, /* SIOCSIWFREQ */ - r8711_wx_get_freq, /* SIOCGIWFREQ */ - r8711_wx_set_mode, /* SIOCSIWMODE */ - r8711_wx_get_mode, /* SIOCGIWMODE */ - dummy, /* SIOCSIWSENS */ - r8711_wx_get_sens, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - r8711_wx_get_range, /* SIOCGIWRANGE */ - r871x_wx_set_priv, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - dummy, /* SIOCSIWSPY */ - dummy, /* SIOCGIWSPY */ - NULL, /* SIOCGIWTHRSPY */ - NULL, /* SIOCWIWTHRSPY */ - r8711_wx_set_wap, /* SIOCSIWAP */ - r8711_wx_get_wap, /* SIOCGIWAP */ - r871x_wx_set_mlme, /* request MLME operation; - * uses struct iw_mlme - */ - dummy, /* SIOCGIWAPLIST -- deprecated */ - r8711_wx_set_scan, /* SIOCSIWSCAN */ - r8711_wx_get_scan, /* SIOCGIWSCAN */ - r8711_wx_set_essid, /* SIOCSIWESSID */ - r8711_wx_get_essid, /* SIOCGIWESSID */ - dummy, /* SIOCSIWNICKN */ - r871x_wx_get_nick, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - r8711_wx_set_rate, /* SIOCSIWRATE */ - r8711_wx_get_rate, /* SIOCGIWRATE */ - dummy, /* SIOCSIWRTS */ - r8711_wx_get_rts, /* SIOCGIWRTS */ - r8711_wx_set_frag, /* SIOCSIWFRAG */ - r8711_wx_get_frag, /* SIOCGIWFRAG */ - dummy, /* SIOCSIWTXPOW */ - dummy, /* SIOCGIWTXPOW */ - dummy, /* SIOCSIWRETRY */ - r8711_wx_get_retry, /* SIOCGIWRETRY */ - r8711_wx_set_enc, /* SIOCSIWENCODE */ - r8711_wx_get_enc, /* SIOCGIWENCODE */ - dummy, /* SIOCSIWPOWER */ - r8711_wx_get_power, /* SIOCGIWPOWER */ - NULL, /*---hole---*/ - NULL, /*---hole---*/ - r871x_wx_set_gen_ie, /* SIOCSIWGENIE */ - NULL, /* SIOCGIWGENIE */ - r871x_wx_set_auth, /* SIOCSIWAUTH */ - NULL, /* SIOCGIWAUTH */ - r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ - NULL, /* SIOCGIWENCODEEXT */ - r871x_wx_set_pmkid, /* SIOCSIWPMKSA */ - NULL, /*---hole---*/ -}; - -static const struct iw_priv_args r8711_private_args[] = { - { - SIOCIWFIRSTPRIV + 0x0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32" - }, - { - SIOCIWFIRSTPRIV + 0x1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32" - }, - { - SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext" - }, - { - SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl" - }, - { - SIOCIWFIRSTPRIV + 0x4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" - }, - { - SIOCIWFIRSTPRIV + 0x5, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid" - }, - { - SIOCIWFIRSTPRIV + 0x6, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start" - }, - { - SIOCIWFIRSTPRIV + 0x7, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan" - } -}; - -static iw_handler r8711_private_handler[] = { - r8711_wx_read32, - r8711_wx_write32, - r8711_drvext_hdl, - r871x_mp_ioctl_hdl, - r871x_get_ap_info, /*for MM DTV platform*/ - r871x_set_pid, - r871x_wps_start, - r871x_set_chplan -}; - -static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev) -{ - struct _adapter *padapter = netdev_priv(dev); - struct iw_statistics *piwstats = &padapter->iwstats; - int tmp_level = 0; - int tmp_qual = 0; - int tmp_noise = 0; - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) { - piwstats->qual.qual = 0; - piwstats->qual.level = 0; - piwstats->qual.noise = 0; - } else { - /* show percentage, we need transfer dbm to original value. */ - tmp_level = padapter->recvpriv.fw_rssi; - tmp_qual = padapter->recvpriv.signal; - tmp_noise = padapter->recvpriv.noise; - piwstats->qual.level = tmp_level; - piwstats->qual.qual = tmp_qual; - piwstats->qual.noise = tmp_noise; - } - piwstats->qual.updated = IW_QUAL_ALL_UPDATED; - return &padapter->iwstats; -} - -struct iw_handler_def r871x_handlers_def = { - .standard = r8711_handlers, - .num_standard = ARRAY_SIZE(r8711_handlers), - .private = r8711_private_handler, - .private_args = (struct iw_priv_args *)r8711_private_args, - .num_private = ARRAY_SIZE(r8711_private_handler), - .num_private_args = sizeof(r8711_private_args) / - sizeof(struct iw_priv_args), - .get_wireless_stats = r871x_get_wireless_stats -}; diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c deleted file mode 100644 index 2b539335206aa1a259aeff51e55d0ed828b8ac19..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c +++ /dev/null @@ -1,519 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_ioctl_rtl.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_IOCTL_RTL_C_ - -#include <linux/rndis.h> -#include "osdep_service.h" -#include "drv_types.h" -#include "wlan_bssdef.h" -#include "wifi.h" -#include "rtl871x_ioctl.h" -#include "rtl871x_ioctl_set.h" -#include "rtl871x_ioctl_rtl.h" -#include "mp_custom_oid.h" -#include "rtl871x_mp.h" -#include "rtl871x_mp_ioctl.h" - -uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - padapter->recvpriv.rx_smallpacket_crcerr; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - padapter->recvpriv.rx_middlepacket_crcerr; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - padapter->recvpriv.rx_largepacket_crcerr; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - padapter->recvpriv.rx_pkts + - padapter->recvpriv.rx_drop; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(uint *)poid_par_priv->information_buf = - padapter->recvpriv.rx_icv_err; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - u32 preamblemode = 0; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - if (padapter->registrypriv.preamble == PREAMBLE_LONG) - preamblemode = 0; - else if (padapter->registrypriv.preamble == PREAMBLE_AUTO) - preamblemode = 1; - else if (padapter->registrypriv.preamble == PREAMBLE_SHORT) - preamblemode = 2; - *(u32 *)poid_par_priv->information_buf = preamblemode; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - struct eeprom_priv *peeprompriv = &padapter->eeprompriv; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - *(u16 *)poid_par_priv->information_buf = peeprompriv->channel_plan; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_set_channelplan_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - struct eeprom_priv *peeprompriv = &padapter->eeprompriv; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - peeprompriv->channel_plan = *(u16 *)poid_par_priv->information_buf; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - u32 preamblemode = 0; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - preamblemode = *(u32 *)poid_par_priv->information_buf; - if (preamblemode == 0) - padapter->registrypriv.preamble = PREAMBLE_LONG; - else if (preamblemode == 1) - padapter->registrypriv.preamble = PREAMBLE_AUTO; - else if (preamblemode == 2) - padapter->registrypriv.preamble = PREAMBLE_SHORT; - *(u32 *)poid_par_priv->information_buf = preamblemode; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_dedicate_probe_hdl(struct oid_par_priv - *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - padapter->xmitpriv.tx_bytes; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - padapter->recvpriv.rx_bytes; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv - *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct NDIS_802_11_CONFIGURATION *pnic_Config; - u32 channelnum; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (check_fwstate(pmlmepriv, _FW_LINKED) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) - pnic_Config = &pmlmepriv->cur_network.network.Configuration; - else - pnic_Config = &padapter->registrypriv.dev_network.Configuration; - channelnum = pnic_Config->DSConfig; - *(u32 *)poid_par_priv->information_buf = channelnum; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv - *poid_par_priv) -{ - u32 ulInfo = 0; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len >= sizeof(u32)) { - ulInfo |= 0x0100; /* WIRELESS_MODE_B */ - ulInfo |= 0x0200; /* WIRELESS_MODE_G */ - ulInfo |= 0x0400; /* WIRELESS_MODE_A */ - *(u32 *) poid_par_priv->information_buf = ulInfo; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv - *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv - *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv* - poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv* - poid_par_priv) -{ - uint status = RNDIS_STATUS_SUCCESS; - struct _adapter *Adapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */ - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len == - (sizeof(unsigned long) * 3)) { - if (r8712_setrfreg_cmd(Adapter, - *(unsigned char *)poid_par_priv->information_buf, - (unsigned long)(*((unsigned long *) - poid_par_priv->information_buf + 2)))) - status = RNDIS_STATUS_NOT_ACCEPTED; - } else { - status = RNDIS_STATUS_INVALID_LENGTH; - } - return status; -} - -uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv) -{ - uint status = RNDIS_STATUS_SUCCESS; - struct _adapter *Adapter = poid_par_priv->adapter_context; - - if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */ - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len == (sizeof(unsigned long) * - 3)) { - if (Adapter->mppriv.act_in_progress) { - status = RNDIS_STATUS_NOT_ACCEPTED; - } else { - /* init workparam */ - Adapter->mppriv.act_in_progress = true; - Adapter->mppriv.workparam.bcompleted = false; - Adapter->mppriv.workparam.act_type = MPT_READ_RF; - Adapter->mppriv.workparam.io_offset = *(unsigned long *) - poid_par_priv->information_buf; - Adapter->mppriv.workparam.io_value = 0xcccccccc; - - /* RegOffsetValue - The offset of RF register to read. - * RegDataWidth - The data width of RF register to read. - * RegDataValue - The value to read. - * RegOffsetValue = *((unsigned long *)InformationBuffer); - * RegDataWidth = *((unsigned long *)InformationBuffer+1); - * RegDataValue = *((unsigned long *)InformationBuffer+2); - */ - if (r8712_getrfreg_cmd(Adapter, - *(unsigned char *)poid_par_priv->information_buf, - (unsigned char *)&Adapter->mppriv.workparam.io_value - )) - status = RNDIS_STATUS_NOT_ACCEPTED; - } - } else { - status = RNDIS_STATUS_INVALID_LENGTH; - } - return status; -} - -enum _CONNECT_STATE_ { - CHECKINGSTATUS, - ASSOCIATED, - ADHOCMODE, - NOTASSOCIATED -}; - -uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *padapter = poid_par_priv->adapter_context; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u32 ulInfo; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - /* nStatus==0 CheckingStatus - * nStatus==1 Associated - * nStatus==2 AdHocMode - * nStatus==3 NotAssociated - */ - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - ulInfo = CHECKINGSTATUS; - else if (check_fwstate(pmlmepriv, _FW_LINKED)) - ulInfo = ASSOCIATED; - else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) - ulInfo = ADHOCMODE; - else - ulInfo = NOTASSOCIATED; - *(u32 *)poid_par_priv->information_buf = ulInfo; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h deleted file mode 100644 index 7c0b880ac68659859c86c336c2fe4773ba8eddd4..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871X_IOCTL_RTL_H -#define _RTL871X_IOCTL_RTL_H - -#include "osdep_service.h" -#include "drv_types.h" - -/*************** oid_rtl_seg_01_01 **************/ -uint oid_rt_get_signal_quality_hdl( - struct oid_par_priv *poid_par_priv);/*84*/ -uint oid_rt_get_small_packet_crc_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_middle_packet_crc_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_large_packet_crc_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_tx_retry_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_rx_retry_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_rx_total_packet_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_tx_beacon_ok_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_tx_beacon_err_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_rx_icv_err_hdl( - struct oid_par_priv *poid_par_priv);/*93*/ -uint oid_rt_set_encryption_algorithm_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_preamble_mode_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_ap_ip_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_channelplan_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_set_channelplan_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_set_preamble_mode_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_set_bcn_intvl_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_dedicate_probe_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_total_tx_bytes_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_total_rx_bytes_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_current_tx_power_level_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_enc_key_mismatch_count_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_enc_key_match_count_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_channel_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_hardware_radio_off_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_key_mismatch_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_supported_wireless_mode_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_channel_list_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_scan_in_progress_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_forced_data_rate_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_wireless_mode_for_scan_list_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_bss_wireless_mode_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_scan_with_magic_packet_hdl( - struct oid_par_priv *poid_par_priv); - -/************** oid_rtl_seg_01_03 section start **************/ -uint oid_rt_ap_get_associated_station_list_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_ap_switch_into_ap_mode_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_ap_supported_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_ap_set_passphrase_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_01_11 */ -uint oid_rt_pro_rf_write_registry_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_rf_read_registry_hdl( - struct oid_par_priv *poid_par_priv); -/*************** oid_rtl_seg_03_00 section start **************/ -uint oid_rt_get_connect_state_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_set_default_key_id_hdl( - struct oid_par_priv *poid_par_priv); - -#endif - diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c deleted file mode 100644 index 34c9a52b4c42a620d140f2df1e5e632b2d499741..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ /dev/null @@ -1,354 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_ioctl_set.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_IOCTL_SET_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "rtl871x_ioctl_set.h" -#include "usb_osintf.h" -#include "usb_ops.h" - -static u8 validate_ssid(struct ndis_802_11_ssid *ssid) -{ - u8 i; - - if (ssid->SsidLength > 32) - return false; - for (i = 0; i < ssid->SsidLength; i++) { - /* wifi, printable ascii code must be supported */ - if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) - return false; - } - return true; -} - -static u8 do_join(struct _adapter *padapter) -{ - struct list_head *plist, *phead; - u8 *pibss = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct __queue *queue = &(pmlmepriv->scanned_queue); - int ret; - - phead = &queue->queue; - plist = phead->next; - pmlmepriv->cur_network.join_res = -2; - pmlmepriv->fw_state |= _FW_UNDER_LINKING; - pmlmepriv->pscanned = plist; - pmlmepriv->to_join = true; - - /* adhoc mode will start with an empty queue, but skip checking */ - if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) && - list_empty(&queue->queue)) { - if (pmlmepriv->fw_state & _FW_UNDER_LINKING) - pmlmepriv->fw_state ^= _FW_UNDER_LINKING; - /* when set_ssid/set_bssid for do_join(), but scanning queue - * is empty we try to issue sitesurvey firstly - */ - if (!pmlmepriv->sitesurveyctrl.traffic_busy) - r8712_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid); - return true; - } - - ret = r8712_select_and_join_from_scan(pmlmepriv); - if (!ret) { - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT)); - } else { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - /* submit r8712_createbss_cmd to change to an - * ADHOC_MASTER pmlmepriv->lock has been - * acquired by caller... - */ - struct wlan_bssid_ex *pdev_network = - &padapter->registrypriv.dev_network; - pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE; - pibss = padapter->registrypriv.dev_network.MacAddress; - memcpy(&pdev_network->Ssid, - &pmlmepriv->assoc_ssid, - sizeof(struct ndis_802_11_ssid)); - r8712_update_registrypriv_dev_network(padapter); - r8712_generate_random_ibss(pibss); - if (r8712_createbss_cmd(padapter)) - return false; - pmlmepriv->to_join = false; - } else { - /* can't associate ; reset under-linking */ - if (pmlmepriv->fw_state & _FW_UNDER_LINKING) - pmlmepriv->fw_state ^= - _FW_UNDER_LINKING; - /* when set_ssid/set_bssid for do_join(), but - * there are no desired bss in scanning queue - * we try to issue sitesurvey first - */ - if (!pmlmepriv->sitesurveyctrl.traffic_busy) - r8712_sitesurvey_cmd(padapter, - &pmlmepriv->assoc_ssid); - } - } - return true; -} - -u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid) -{ - unsigned long irqL; - u8 status = true; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) { - status = false; - return status; - } - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | - _FW_UNDER_LINKING)) { - status = check_fwstate(pmlmepriv, _FW_UNDER_LINKING); - goto _Abort_Set_BSSID; - } - if (check_fwstate(pmlmepriv, - _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, - ETH_ALEN)) { - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - /* driver is in - * WIFI_ADHOC_MASTER_STATE - */ - goto _Abort_Set_BSSID; - } else { - r8712_disassoc_cmd(padapter); - if (check_fwstate(pmlmepriv, _FW_LINKED)) - r8712_ind_disconnect(padapter); - r8712_free_assoc_resources(padapter); - if ((check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE))) { - _clr_fwstate_(pmlmepriv, - WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } - } - memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); - pmlmepriv->assoc_by_bssid = true; - status = do_join(padapter); - goto done; -_Abort_Set_BSSID: -done: - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - return status; -} - -void r8712_set_802_11_ssid(struct _adapter *padapter, - struct ndis_802_11_ssid *ssid) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *pnetwork = &pmlmepriv->cur_network; - - if (!padapter->hw_init_completed) - return; - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) { - check_fwstate(pmlmepriv, _FW_UNDER_LINKING); - goto _Abort_Set_SSID; - } - if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) { - if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) && - (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, - ssid->SsidLength))) { - if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (!r8712_is_same_ibss(padapter, - pnetwork)) { - /* if in WIFI_ADHOC_MASTER_STATE or - * WIFI_ADHOC_STATE, create bss or - * rejoin again - */ - r8712_disassoc_cmd(padapter); - if (check_fwstate(pmlmepriv, - _FW_LINKED)) - r8712_ind_disconnect(padapter); - r8712_free_assoc_resources(padapter); - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, - WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, - WIFI_ADHOC_STATE); - } - } else { - /* driver is in - * WIFI_ADHOC_MASTER_STATE - */ - goto _Abort_Set_SSID; - } - } - } else { - r8712_disassoc_cmd(padapter); - if (check_fwstate(pmlmepriv, _FW_LINKED)) - r8712_ind_disconnect(padapter); - r8712_free_assoc_resources(padapter); - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_MASTER_STATE)) { - _clr_fwstate_(pmlmepriv, - WIFI_ADHOC_MASTER_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - } - } - } - if (padapter->securitypriv.btkip_countermeasure) - goto _Abort_Set_SSID; - if (!validate_ssid(ssid)) - goto _Abort_Set_SSID; - memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid)); - pmlmepriv->assoc_by_bssid = false; - do_join(padapter); - goto done; -_Abort_Set_SSID: -done: - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter, - enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - enum NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state = - &(cur_network->network.InfrastructureMode); - - if (*pold_state != networktype) { - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, _FW_LINKED) || - (*pold_state == Ndis802_11IBSS)) - r8712_disassoc_cmd(padapter); - if (check_fwstate(pmlmepriv, - _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) - r8712_free_assoc_resources(padapter); - if (check_fwstate(pmlmepriv, _FW_LINKED) || - (*pold_state == Ndis802_11Infrastructure) || - (*pold_state == Ndis802_11IBSS)) { - /* will clr Linked_state before this function, - * we must have checked whether issue dis-assoc_cmd or - * not - */ - r8712_ind_disconnect(padapter); - } - *pold_state = networktype; - /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE; - * WIFI_ADHOC_MASTER_STATE - */ - _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE | - WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE); - switch (networktype) { - case Ndis802_11IBSS: - set_fwstate(pmlmepriv, WIFI_ADHOC_STATE); - break; - case Ndis802_11Infrastructure: - set_fwstate(pmlmepriv, WIFI_STATION_STATE); - break; - case Ndis802_11APMode: - set_fwstate(pmlmepriv, WIFI_AP_STATE); - break; - case Ndis802_11AutoUnknown: - case Ndis802_11InfrastructureMax: - break; - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - } -} - -u8 r8712_set_802_11_disassociate(struct _adapter *padapter) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - r8712_disassoc_cmd(padapter); - r8712_ind_disconnect(padapter); - r8712_free_assoc_resources(padapter); - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - return true; -} - -u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter) -{ - struct mlme_priv *pmlmepriv = NULL; - unsigned long irqL; - u8 ret = true; - - if (!padapter) - return false; - pmlmepriv = &padapter->mlmepriv; - if (!padapter->hw_init_completed) - return false; - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) || - pmlmepriv->sitesurveyctrl.traffic_busy) { - /* Scan or linking is in progress, do nothing. */ - ret = (u8)check_fwstate(pmlmepriv, _FW_UNDER_SURVEY); - } else { - r8712_free_network_queue(padapter); - ret = r8712_sitesurvey_cmd(padapter, NULL); - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - return ret; -} - -u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter, - enum NDIS_802_11_AUTHENTICATION_MODE authmode) -{ - struct security_priv *psecuritypriv = &padapter->securitypriv; - u8 ret; - - psecuritypriv->ndisauthtype = authmode; - if (psecuritypriv->ndisauthtype > 3) - psecuritypriv->AuthAlgrthm = 2; /* 802.1x */ - if (r8712_set_auth(padapter, psecuritypriv)) - ret = false; - else - ret = true; - return ret; -} - -int r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep) -{ - sint keyid; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - keyid = wep->KeyIndex & 0x3fffffff; - if (keyid >= WEP_KEYS) - return -EINVAL; - switch (wep->KeyLength) { - case 5: - psecuritypriv->PrivacyAlgrthm = _WEP40_; - break; - case 13: - psecuritypriv->PrivacyAlgrthm = _WEP104_; - break; - default: - psecuritypriv->PrivacyAlgrthm = _NO_PRIVACY_; - break; - } - memcpy(psecuritypriv->DefKey[keyid].skey, &wep->KeyMaterial, - wep->KeyLength); - psecuritypriv->DefKeylen[keyid] = wep->KeyLength; - psecuritypriv->PrivacyKeyIndex = keyid; - return r8712_set_key(padapter, psecuritypriv, keyid); -} diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h deleted file mode 100644 index e2de820f61d985df11d28eaa434f81cd9274ccc7..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __IOCTL_SET_H -#define __IOCTL_SET_H - -#include "drv_types.h" - -typedef u8 NDIS_802_11_PMKID_VALUE[16]; - -struct BSSIDInfo { - unsigned char BSSID[6]; - NDIS_802_11_PMKID_VALUE PMKID; -}; - -u8 r8712_set_802_11_authentication_mode(struct _adapter *pdapter, - enum NDIS_802_11_AUTHENTICATION_MODE authmode); - -u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid); - -int r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep); - -u8 r8712_set_802_11_disassociate(struct _adapter *padapter); - -u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter); - -void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter, - enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype); - -void r8712_set_802_11_ssid(struct _adapter *padapter, - struct ndis_802_11_ssid *ssid); - -#endif - diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h deleted file mode 100644 index 2f0768132ad8fff5148d2b0626d6f04683518513..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_led.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL8712_LED_H -#define __RTL8712_LED_H - -#include "osdep_service.h" -#include "drv_types.h" - -/*=========================================================================== - * LED customization. - *=========================================================================== - */ -enum LED_CTL_MODE { - LED_CTL_POWER_ON = 1, - LED_CTL_LINK = 2, - LED_CTL_NO_LINK = 3, - LED_CTL_TX = 4, - LED_CTL_RX = 5, - LED_CTL_SITE_SURVEY = 6, - LED_CTL_POWER_OFF = 7, - LED_CTL_START_TO_LINK = 8, - LED_CTL_START_WPS = 9, - LED_CTL_STOP_WPS = 10, - LED_CTL_START_WPS_BOTTON = 11, - LED_CTL_STOP_WPS_FAIL = 12, - LED_CTL_STOP_WPS_FAIL_OVERLAP = 13, -}; - -#define IS_LED_WPS_BLINKING(_LED_871x) \ - (((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS \ - || ((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS_STOP \ - || ((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress) - -#define IS_LED_BLINKING(_LED_871x) \ - (((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress \ - || ((struct LED_871x *)_LED_871x)->bLedScanBlinkInProgress) - -enum LED_PIN_871x { - LED_PIN_GPIO0, - LED_PIN_LED0, - LED_PIN_LED1 -}; - -/*=========================================================================== - * LED customization. - *=========================================================================== - */ -enum LED_STRATEGY_871x { - SW_LED_MODE0, /* SW control 1 LED via GPIO0. It is default option. */ - SW_LED_MODE1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */ - SW_LED_MODE2, /* SW control 1 LED via GPIO0, - * custom for AzWave 8187 minicard. - */ - SW_LED_MODE3, /* SW control 1 LED via GPIO0, - * customized for Sercomm Printer Server case. - */ - SW_LED_MODE4, /*for Edimax / Belkin*/ - SW_LED_MODE5, /*for Sercomm / Belkin*/ - SW_LED_MODE6, /*for WNC / Corega*/ - HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different - * control modes, see MAC.CONFIG1 for details.) - */ -}; - -struct LED_871x { - struct _adapter *padapter; - enum LED_PIN_871x LedPin; /* Implementation for this SW led. */ - u32 CurrLedState; /* Current LED state. */ - u8 bLedOn; /* true if LED is ON */ - u8 bSWLedCtrl; - u8 bLedBlinkInProgress; /*true if blinking */ - u8 bLedNoLinkBlinkInProgress; - u8 bLedLinkBlinkInProgress; - u8 bLedStartToLinkBlinkInProgress; - u8 bLedScanBlinkInProgress; - u8 bLedWPSBlinkInProgress; - u32 BlinkTimes; /* No. times to toggle for blink.*/ - u32 BlinkingLedState; /* Next state for blinking, - * either LED_ON or OFF. - */ - - struct timer_list BlinkTimer; /* Timer object for led blinking.*/ - struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer */ -}; - -struct led_priv { - /* add for led control */ - struct LED_871x SwLed0; - struct LED_871x SwLed1; - enum LED_STRATEGY_871x LedStrategy; - u8 bRegUseLed; - void (*LedControlHandler)(struct _adapter *padapter, - enum LED_CTL_MODE LedAction); - /* add for led control */ -}; - -/*=========================================================================== - * Interface to manipulate LED objects. - *=========================================================================== - */ -void r8712_InitSwLeds(struct _adapter *padapter); -void r8712_DeInitSwLeds(struct _adapter *padapter); -void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction); -void r8712_flush_led_works(struct _adapter *padapter); - -#endif - diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c deleted file mode 100644 index 70c295e97068572e3717e516b29f2e3011902041..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ /dev/null @@ -1,1710 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_mlme.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_MLME_C_ - -#include <linux/etherdevice.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "xmit_osdep.h" -#include "mlme_osdep.h" -#include "sta_info.h" -#include "wifi.h" -#include "wlan_bssdef.h" - -static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len); - -int r8712_init_mlme_priv(struct _adapter *padapter) -{ - sint i; - u8 *pbuf; - struct wlan_network *pnetwork; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv)); - pmlmepriv->nic_hdl = (u8 *)padapter; - pmlmepriv->pscanned = NULL; - pmlmepriv->fw_state = 0; - pmlmepriv->cur_network.network.InfrastructureMode = - Ndis802_11AutoUnknown; - /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/ - pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */ - spin_lock_init(&(pmlmepriv->lock)); - spin_lock_init(&(pmlmepriv->lock2)); - _init_queue(&(pmlmepriv->free_bss_pool)); - _init_queue(&(pmlmepriv->scanned_queue)); - set_scanned_network_val(pmlmepriv, 0); - memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid)); - pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network), - GFP_ATOMIC); - if (!pbuf) - return -ENOMEM; - pmlmepriv->free_bss_buf = pbuf; - pnetwork = (struct wlan_network *)pbuf; - for (i = 0; i < MAX_BSS_CNT; i++) { - INIT_LIST_HEAD(&(pnetwork->list)); - list_add_tail(&(pnetwork->list), - &(pmlmepriv->free_bss_pool.queue)); - pnetwork++; - } - pmlmepriv->sitesurveyctrl.last_rx_pkts = 0; - pmlmepriv->sitesurveyctrl.last_tx_pkts = 0; - pmlmepriv->sitesurveyctrl.traffic_busy = false; - /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ - r8712_init_mlme_timer(padapter); - return 0; -} - -struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv) -{ - unsigned long irqL; - struct wlan_network *pnetwork; - struct __queue *free_queue = &pmlmepriv->free_bss_pool; - - spin_lock_irqsave(&free_queue->lock, irqL); - pnetwork = list_first_entry_or_null(&free_queue->queue, - struct wlan_network, list); - if (pnetwork) { - list_del_init(&pnetwork->list); - pnetwork->last_scanned = jiffies; - pmlmepriv->num_of_scanned++; - } - spin_unlock_irqrestore(&free_queue->lock, irqL); - return pnetwork; -} - -static void _free_network(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - u32 curr_time, delta_time; - unsigned long irqL; - struct __queue *free_queue = &(pmlmepriv->free_bss_pool); - - if (!pnetwork) - return; - if (pnetwork->fixed) - return; - curr_time = jiffies; - delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ; - if (delta_time < SCANQUEUE_LIFETIME) - return; - spin_lock_irqsave(&free_queue->lock, irqL); - list_del_init(&pnetwork->list); - list_add_tail(&pnetwork->list, &free_queue->queue); - pmlmepriv->num_of_scanned--; - spin_unlock_irqrestore(&free_queue->lock, irqL); -} - -static void free_network_nolock(struct mlme_priv *pmlmepriv, - struct wlan_network *pnetwork) -{ - struct __queue *free_queue = &pmlmepriv->free_bss_pool; - - if (!pnetwork) - return; - if (pnetwork->fixed) - return; - list_del_init(&pnetwork->list); - list_add_tail(&pnetwork->list, &free_queue->queue); - pmlmepriv->num_of_scanned--; -} - -/* return the wlan_network with the matching addr - * Shall be called under atomic context... - * to avoid possible racing condition... - */ -static struct wlan_network *r8712_find_network(struct __queue *scanned_queue, - u8 *addr) -{ - unsigned long irqL; - struct list_head *phead, *plist; - struct wlan_network *pnetwork = NULL; - - if (is_zero_ether_addr(addr)) - return NULL; - spin_lock_irqsave(&scanned_queue->lock, irqL); - phead = &scanned_queue->queue; - list_for_each(plist, phead) { - pnetwork = list_entry(plist, struct wlan_network, list); - if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN)) - break; - } - if (plist == phead) - pnetwork = NULL; - spin_unlock_irqrestore(&scanned_queue->lock, irqL); - return pnetwork; -} - -void r8712_free_network_queue(struct _adapter *padapter) -{ - unsigned long irqL; - struct list_head *phead, *plist; - struct wlan_network *pnetwork; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct __queue *scanned_queue = &pmlmepriv->scanned_queue; - - spin_lock_irqsave(&scanned_queue->lock, irqL); - phead = &scanned_queue->queue; - plist = phead->next; - while (!end_of_queue_search(phead, plist)) { - pnetwork = container_of(plist, struct wlan_network, list); - plist = plist->next; - _free_network(pmlmepriv, pnetwork); - } - spin_unlock_irqrestore(&scanned_queue->lock, irqL); -} - -sint r8712_if_up(struct _adapter *padapter) -{ - sint res; - - if (padapter->driver_stopped || padapter->surprise_removed || - !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) { - res = false; - } else { - res = true; - } - return res; -} - -void r8712_generate_random_ibss(u8 *pibss) -{ - u32 curtime = jiffies; - - pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */ - pibss[1] = 0x11; - pibss[2] = 0x87; - pibss[3] = (u8)(curtime & 0xff); - pibss[4] = (u8)((curtime >> 8) & 0xff); - pibss[5] = (u8)((curtime >> 16) & 0xff); -} - -uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) -{ - return sizeof(*bss) + bss->IELength - MAX_IE_SZ; -} - -u8 *r8712_get_capability_from_ie(u8 *ie) -{ - return ie + 8 + 2; -} - -void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv) -{ - kfree(pmlmepriv->free_bss_buf); -} - -static struct wlan_network *alloc_network(struct mlme_priv *pmlmepriv) -{ - return _r8712_alloc_network(pmlmepriv); -} - -int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork) -{ - int ret = true; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) && - (pnetwork->network.Privacy == cpu_to_le32(0))) - ret = false; - else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) && - (pnetwork->network.Privacy == cpu_to_le32(1))) - ret = false; - else - ret = true; - return ret; - -} - -static int is_same_network(struct wlan_bssid_ex *src, - struct wlan_bssid_ex *dst) -{ - u16 s_cap, d_cap; - - memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2); - memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2); - return (src->Ssid.SsidLength == dst->Ssid.SsidLength) && - (src->Configuration.DSConfig == - dst->Configuration.DSConfig) && - ((!memcmp(src->MacAddress, dst->MacAddress, - ETH_ALEN))) && - ((!memcmp(src->Ssid.Ssid, - dst->Ssid.Ssid, - src->Ssid.SsidLength))) && - ((s_cap & WLAN_CAPABILITY_IBSS) == - (d_cap & WLAN_CAPABILITY_IBSS)) && - ((s_cap & WLAN_CAPABILITY_ESS) == - (d_cap & WLAN_CAPABILITY_ESS)); - -} - -struct wlan_network *r8712_get_oldest_wlan_network( - struct __queue *scanned_queue) -{ - struct list_head *plist, *phead; - struct wlan_network *pwlan = NULL; - struct wlan_network *oldest = NULL; - - phead = &scanned_queue->queue; - plist = phead->next; - while (1) { - if (end_of_queue_search(phead, plist)) - break; - pwlan = container_of(plist, struct wlan_network, list); - if (!pwlan->fixed) { - if (!oldest || - time_after((unsigned long)oldest->last_scanned, - (unsigned long)pwlan->last_scanned)) - oldest = pwlan; - } - plist = plist->next; - } - return oldest; -} - -static void update_network(struct wlan_bssid_ex *dst, - struct wlan_bssid_ex *src, - struct _adapter *padapter) -{ - u32 last_evm = 0, tmpVal; - struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data; - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && - is_same_network(&(padapter->mlmepriv.cur_network.network), src)) { - if (padapter->recvpriv.signal_qual_data.total_num++ >= - PHY_LINKQUALITY_SLID_WIN_MAX) { - padapter->recvpriv.signal_qual_data.total_num = - PHY_LINKQUALITY_SLID_WIN_MAX; - last_evm = sqd->elements[sqd->index]; - padapter->recvpriv.signal_qual_data.total_val -= - last_evm; - } - padapter->recvpriv.signal_qual_data.total_val += src->Rssi; - - sqd->elements[sqd->index++] = src->Rssi; - if (padapter->recvpriv.signal_qual_data.index >= - PHY_LINKQUALITY_SLID_WIN_MAX) - padapter->recvpriv.signal_qual_data.index = 0; - /* <1> Showed on UI for user, in percentage. */ - tmpVal = padapter->recvpriv.signal_qual_data.total_val / - padapter->recvpriv.signal_qual_data.total_num; - padapter->recvpriv.signal = (u8)tmpVal; - - src->Rssi = padapter->recvpriv.signal; - } else { - src->Rssi = (src->Rssi + dst->Rssi) / 2; - } - memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src)); -} - -static void update_current_network(struct _adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) { - update_network(&(pmlmepriv->cur_network.network), - pnetwork, adapter); - r8712_update_protection(adapter, - (pmlmepriv->cur_network.network.IEs) + - sizeof(struct NDIS_802_11_FIXED_IEs), - pmlmepriv->cur_network.network.IELength); - } -} - -/* Caller must hold pmlmepriv->lock first */ -static void update_scanned_network(struct _adapter *adapter, - struct wlan_bssid_ex *target) -{ - struct list_head *plist, *phead; - - u32 bssid_ex_sz; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct __queue *queue = &pmlmepriv->scanned_queue; - struct wlan_network *pnetwork = NULL; - struct wlan_network *oldest = NULL; - - phead = &queue->queue; - plist = phead->next; - - while (1) { - if (end_of_queue_search(phead, plist)) - break; - - pnetwork = container_of(plist, struct wlan_network, list); - if (is_same_network(&pnetwork->network, target)) - break; - if ((oldest == ((struct wlan_network *)0)) || - time_after((unsigned long)oldest->last_scanned, - (unsigned long)pnetwork->last_scanned)) - oldest = pnetwork; - - plist = plist->next; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information - */ - if (end_of_queue_search(phead, plist)) { - if (list_empty(&pmlmepriv->free_bss_pool.queue)) { - /* If there are no more slots, expire the oldest */ - pnetwork = oldest; - target->Rssi = (pnetwork->network.Rssi + - target->Rssi) / 2; - memcpy(&pnetwork->network, target, - r8712_get_wlan_bssid_ex_sz(target)); - pnetwork->last_scanned = jiffies; - } else { - /* Otherwise just pull from the free list */ - /* update scan_time */ - pnetwork = alloc_network(pmlmepriv); - if (!pnetwork) - return; - bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target); - target->Length = bssid_ex_sz; - memcpy(&pnetwork->network, target, bssid_ex_sz); - list_add_tail(&pnetwork->list, &queue->queue); - } - } else { - /* we have an entry and we are going to update it. But - * this entry may be already expired. In this case we - * do the same as we found a new net and call the new_net - * handler - */ - update_network(&pnetwork->network, target, adapter); - pnetwork->last_scanned = jiffies; - } -} - -static void rtl8711_add_network(struct _adapter *adapter, - struct wlan_bssid_ex *pnetwork) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv); - struct __queue *queue = &pmlmepriv->scanned_queue; - - spin_lock_irqsave(&queue->lock, irqL); - update_current_network(adapter, pnetwork); - update_scanned_network(adapter, pnetwork); - spin_unlock_irqrestore(&queue->lock, irqL); -} - -/*select the desired network based on the capability of the (i)bss. - * check items: (1) security - * (2) network_type - * (3) WMM - * (4) HT - * (5) others - */ -static int is_desired_network(struct _adapter *adapter, - struct wlan_network *pnetwork) -{ - u8 wps_ie[512]; - uint wps_ielen; - int bselected = true; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - if (psecuritypriv->wps_phase) { - if (r8712_get_wps_ie(pnetwork->network.IEs, - pnetwork->network.IELength, wps_ie, - &wps_ielen)) - return true; - return false; - } - if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) && - (pnetwork->network.Privacy == 0)) - bselected = false; - if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) { - if (pnetwork->network.InfrastructureMode != - adapter->mlmepriv.cur_network.network.InfrastructureMode) - bselected = false; - } - return bselected; -} - -/* TODO: Perry : For Power Management */ -void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf) -{ -} - -void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - unsigned long flags; - u32 len; - struct wlan_bssid_ex *pnetwork; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - pnetwork = (struct wlan_bssid_ex *)pbuf; -#ifdef __BIG_ENDIAN - /* endian_convert */ - pnetwork->Length = le32_to_cpu(pnetwork->Length); - pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength); - pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy); - pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi); - pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse); - pnetwork->Configuration.ATIMWindow = - le32_to_cpu(pnetwork->Configuration.ATIMWindow); - pnetwork->Configuration.BeaconPeriod = - le32_to_cpu(pnetwork->Configuration.BeaconPeriod); - pnetwork->Configuration.DSConfig = - le32_to_cpu(pnetwork->Configuration.DSConfig); - pnetwork->Configuration.FHConfig.DwellTime = - le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime); - pnetwork->Configuration.FHConfig.HopPattern = - le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern); - pnetwork->Configuration.FHConfig.HopSet = - le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet); - pnetwork->Configuration.FHConfig.Length = - le32_to_cpu(pnetwork->Configuration.FHConfig.Length); - pnetwork->Configuration.Length = - le32_to_cpu(pnetwork->Configuration.Length); - pnetwork->InfrastructureMode = - le32_to_cpu(pnetwork->InfrastructureMode); - pnetwork->IELength = le32_to_cpu(pnetwork->IELength); -#endif - len = r8712_get_wlan_bssid_ex_sz(pnetwork); - if (len > sizeof(struct wlan_bssid_ex)) - return; - spin_lock_irqsave(&pmlmepriv->lock2, flags); - /* update IBSS_network 's timestamp */ - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress), - pnetwork->MacAddress, ETH_ALEN)) { - struct wlan_network *ibss_wlan = NULL; - - memcpy(pmlmepriv->cur_network.network.IEs, - pnetwork->IEs, 8); - ibss_wlan = r8712_find_network( - &pmlmepriv->scanned_queue, - pnetwork->MacAddress); - if (ibss_wlan) { - memcpy(ibss_wlan->network.IEs, - pnetwork->IEs, 8); - goto exit; - } - } - } - /* lock pmlmepriv->lock when you accessing network_q */ - if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - if (pnetwork->Ssid.Ssid[0] != 0) { - rtl8711_add_network(adapter, pnetwork); - } else { - pnetwork->Ssid.SsidLength = 8; - memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8); - rtl8711_add_network(adapter, pnetwork); - } - } -exit: - spin_unlock_irqrestore(&pmlmepriv->lock2, flags); -} - -void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - del_timer(&pmlmepriv->scan_to_timer); - - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - } - - if (pmlmepriv->to_join) { - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (!check_fwstate(pmlmepriv, _FW_LINKED)) { - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - - if (!r8712_select_and_join_from_scan(pmlmepriv)) { - mod_timer(&pmlmepriv->assoc_timer, jiffies + - msecs_to_jiffies(MAX_JOIN_TIMEOUT)); - } else { - struct wlan_bssid_ex *pdev_network = - &(adapter->registrypriv.dev_network); - u8 *pibss = - adapter->registrypriv.dev_network.MacAddress; - pmlmepriv->fw_state ^= _FW_UNDER_SURVEY; - memcpy(&pdev_network->Ssid, - &pmlmepriv->assoc_ssid, - sizeof(struct - ndis_802_11_ssid)); - r8712_update_registrypriv_dev_network - (adapter); - r8712_generate_random_ibss(pibss); - pmlmepriv->fw_state = - WIFI_ADHOC_MASTER_STATE; - pmlmepriv->to_join = false; - } - } - } else { - pmlmepriv->to_join = false; - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - if (!r8712_select_and_join_from_scan(pmlmepriv)) - mod_timer(&pmlmepriv->assoc_timer, jiffies + - msecs_to_jiffies(MAX_JOIN_TIMEOUT)); - else - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -/* - *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock - */ -void r8712_free_assoc_resources(struct _adapter *adapter) -{ - unsigned long irqL; - struct wlan_network *pwlan = NULL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - pwlan = r8712_find_network(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) { - struct sta_info *psta; - - psta = r8712_get_stainfo(&adapter->stapriv, - tgt_network->network.MacAddress); - - spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); - r8712_free_stainfo(adapter, psta); - spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); - } - - if (check_fwstate(pmlmepriv, - WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) - r8712_free_all_stainfo(adapter); - if (pwlan) - pwlan->fixed = false; - - if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) && - (adapter->stapriv.asoc_sta_count == 1))) - free_network_nolock(pmlmepriv, pwlan); -} - -/* - * r8712_indicate_connect: the caller has to lock pmlmepriv->lock - */ -void r8712_indicate_connect(struct _adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pmlmepriv->to_join = false; - set_fwstate(pmlmepriv, _FW_LINKED); - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK); - r8712_os_indicate_connect(padapter); - if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) - mod_timer(&pmlmepriv->dhcp_timer, - jiffies + msecs_to_jiffies(60000)); -} - -/* - * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock - */ -void r8712_ind_disconnect(struct _adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - _clr_fwstate_(pmlmepriv, _FW_LINKED); - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK); - r8712_os_indicate_disconnect(padapter); - } - if (padapter->pwrctrlpriv.pwr_mode != - padapter->registrypriv.power_mgnt) { - del_timer(&pmlmepriv->dhcp_timer); - r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt, - padapter->registrypriv.smart_ps); - } -} - -/*Notes: - *pnetwork : returns from r8712_joinbss_event_callback - *ptarget_wlan: found from scanned_queue - *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if - * "ptarget_sta" & "ptarget_wlan" exist. - *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check - * if "ptarget_wlan" exist. - *if join_res > 0, update "cur_network->network" from - * "pnetwork->network" if (ptarget_wlan !=NULL). - */ -void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - unsigned long irqL = 0, irqL2; - struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct wlan_network *cur_network = &pmlmepriv->cur_network; - struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL; - unsigned int the_same_macaddr = false; - struct wlan_network *pnetwork; - - if (sizeof(struct list_head) == 4 * sizeof(u32)) { - pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC); - if (!pnetwork) - return; - memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8, - sizeof(struct wlan_network) - 16); - } else { - pnetwork = (struct wlan_network *)pbuf; - } - -#ifdef __BIG_ENDIAN - /* endian_convert */ - pnetwork->join_res = le32_to_cpu(pnetwork->join_res); - pnetwork->network_type = le32_to_cpu(pnetwork->network_type); - pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length); - pnetwork->network.Ssid.SsidLength = - le32_to_cpu(pnetwork->network.Ssid.SsidLength); - pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy); - pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi); - pnetwork->network.NetworkTypeInUse = - le32_to_cpu(pnetwork->network.NetworkTypeInUse); - pnetwork->network.Configuration.ATIMWindow = - le32_to_cpu(pnetwork->network.Configuration.ATIMWindow); - pnetwork->network.Configuration.BeaconPeriod = - le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod); - pnetwork->network.Configuration.DSConfig = - le32_to_cpu(pnetwork->network.Configuration.DSConfig); - pnetwork->network.Configuration.FHConfig.DwellTime = - le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime); - pnetwork->network.Configuration.FHConfig.HopPattern = - le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern); - pnetwork->network.Configuration.FHConfig.HopSet = - le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet); - pnetwork->network.Configuration.FHConfig.Length = - le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length); - pnetwork->network.Configuration.Length = - le32_to_cpu(pnetwork->network.Configuration.Length); - pnetwork->network.InfrastructureMode = - le32_to_cpu(pnetwork->network.InfrastructureMode); - pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength); -#endif - - the_same_macaddr = !memcmp(pnetwork->network.MacAddress, - cur_network->network.MacAddress, ETH_ALEN); - pnetwork->network.Length = - r8712_get_wlan_bssid_ex_sz(&pnetwork->network); - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) - goto ignore_joinbss_callback; - if (pnetwork->join_res > 0) { - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - /*s1. find ptarget_wlan*/ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (the_same_macaddr) { - ptarget_wlan = - r8712_find_network(&pmlmepriv->scanned_queue, - cur_network->network.MacAddress); - } else { - pcur_wlan = - r8712_find_network(&pmlmepriv->scanned_queue, - cur_network->network.MacAddress); - if (pcur_wlan) - pcur_wlan->fixed = false; - - pcur_sta = r8712_get_stainfo(pstapriv, - cur_network->network.MacAddress); - spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL2); - r8712_free_stainfo(adapter, pcur_sta); - spin_unlock_irqrestore(&(pstapriv->sta_hash_lock), irqL2); - - ptarget_wlan = - r8712_find_network(&pmlmepriv->scanned_queue, - pnetwork->network.MacAddress); - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - } else { - ptarget_wlan = r8712_find_network(&pmlmepriv->scanned_queue, - pnetwork->network.MacAddress); - if (ptarget_wlan) - ptarget_wlan->fixed = true; - } - - if (!ptarget_wlan) { - if (check_fwstate(pmlmepriv, - _FW_UNDER_LINKING)) - pmlmepriv->fw_state ^= - _FW_UNDER_LINKING; - goto ignore_joinbss_callback; - } - - /*s2. find ptarget_sta & update ptarget_sta*/ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - if (the_same_macaddr) { - ptarget_sta = - r8712_get_stainfo(pstapriv, - pnetwork->network.MacAddress); - if (!ptarget_sta) - ptarget_sta = - r8712_alloc_stainfo(pstapriv, - pnetwork->network.MacAddress); - } else { - ptarget_sta = - r8712_alloc_stainfo(pstapriv, - pnetwork->network.MacAddress); - } - if (ptarget_sta) /*update ptarget_sta*/ { - ptarget_sta->aid = pnetwork->join_res; - ptarget_sta->qos_option = 1; - ptarget_sta->mac_id = 5; - if (adapter->securitypriv.AuthAlgrthm == 2) { - adapter->securitypriv.binstallGrpkey = false; - adapter->securitypriv.busetkipkey = false; - adapter->securitypriv.bgrpkey_handshake = false; - ptarget_sta->ieee8021x_blocked = true; - ptarget_sta->XPrivacy = - adapter->securitypriv.PrivacyAlgrthm; - memset((u8 *)&ptarget_sta->x_UncstKey, - 0, - sizeof(union Keytype)); - memset((u8 *)&ptarget_sta->tkiprxmickey, - 0, - sizeof(union Keytype)); - memset((u8 *)&ptarget_sta->tkiptxmickey, - 0, - sizeof(union Keytype)); - memset((u8 *)&ptarget_sta->txpn, - 0, - sizeof(union pn48)); - memset((u8 *)&ptarget_sta->rxpn, - 0, - sizeof(union pn48)); - } - } else { - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - pmlmepriv->fw_state ^= - _FW_UNDER_LINKING; - goto ignore_joinbss_callback; - } - } - - /*s3. update cur_network & indicate connect*/ - memcpy(&cur_network->network, &pnetwork->network, - pnetwork->network.Length); - cur_network->aid = pnetwork->join_res; - /*update fw_state will clr _FW_UNDER_LINKING*/ - switch (pnetwork->network.InfrastructureMode) { - case Ndis802_11Infrastructure: - pmlmepriv->fw_state = WIFI_STATION_STATE; - break; - case Ndis802_11IBSS: - pmlmepriv->fw_state = WIFI_ADHOC_STATE; - break; - default: - pmlmepriv->fw_state = WIFI_NULL_STATE; - break; - } - r8712_update_protection(adapter, - (cur_network->network.IEs) + - sizeof(struct NDIS_802_11_FIXED_IEs), - (cur_network->network.IELength)); - /*TODO: update HT_Capability*/ - update_ht_cap(adapter, cur_network->network.IEs, - cur_network->network.IELength); - /*indicate connect*/ - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - r8712_indicate_connect(adapter); - del_timer(&pmlmepriv->assoc_timer); - } else { - goto ignore_joinbss_callback; - } - } else { - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - mod_timer(&pmlmepriv->assoc_timer, - jiffies + msecs_to_jiffies(1)); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - } - } -ignore_joinbss_callback: - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - if (sizeof(struct list_head) == 4 * sizeof(u32)) - kfree(pnetwork); -} - -void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - unsigned long irqL; - struct sta_info *psta; - struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); - struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf; - - /* to do: */ - if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr)) - return; - psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (psta) { - /*the sta have been in sta_info_queue => do nothing - *(between drv has received this event before and - * fw have not yet to set key to CAM_ENTRY) - */ - return; - } - - psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr); - if (!psta) - return; - /* to do : init sta_info variable */ - psta->qos_option = 0; - psta->mac_id = le32_to_cpu(pstassoc->cam_id); - /* psta->aid = (uint)pstassoc->cam_id; */ - - if (adapter->securitypriv.AuthAlgrthm == 2) - psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm; - psta->ieee8021x_blocked = false; - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - if (adapter->stapriv.asoc_sta_count == 2) { - /* a sta + bc/mc_stainfo (not Ibss_stainfo) */ - r8712_indicate_connect(adapter); - } - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - unsigned long irqL, irqL2; - struct sta_info *psta; - struct wlan_network *pwlan = NULL; - struct wlan_bssid_ex *pdev_network = NULL; - u8 *pibss = NULL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct stadel_event *pstadel = (struct stadel_event *)pbuf; - struct sta_priv *pstapriv = &adapter->stapriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - - spin_lock_irqsave(&pmlmepriv->lock, irqL2); - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - r8712_ind_disconnect(adapter); - r8712_free_assoc_resources(adapter); - } - if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | - WIFI_ADHOC_STATE)) { - psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr); - spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); - r8712_free_stainfo(adapter, psta); - spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); - if (adapter->stapriv.asoc_sta_count == 1) { - /*a sta + bc/mc_stainfo (not Ibss_stainfo) */ - pwlan = r8712_find_network(&pmlmepriv->scanned_queue, - tgt_network->network.MacAddress); - if (pwlan) { - pwlan->fixed = false; - free_network_nolock(pmlmepriv, pwlan); - } - /*re-create ibss*/ - pdev_network = &(adapter->registrypriv.dev_network); - pibss = adapter->registrypriv.dev_network.MacAddress; - memcpy(pdev_network, &tgt_network->network, - r8712_get_wlan_bssid_ex_sz(&tgt_network->network)); - memcpy(&pdev_network->Ssid, - &pmlmepriv->assoc_ssid, - sizeof(struct ndis_802_11_ssid)); - r8712_update_registrypriv_dev_network(adapter); - r8712_generate_random_ibss(pibss); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { - _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE); - set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE); - } - } - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL2); -} - -void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - struct reportpwrstate_parm *preportpwrstate = - (struct reportpwrstate_parm *)pbuf; - - preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80); - r8712_cpwm_int_hdl(adapter, preportpwrstate); -} - -/* When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send - * the ADDBA req frame with start seq control = 0 to wifi client after - * the WPA handshake and the sequence number of following data packet - * will be 0. In this case, the Rx reorder sequence is not longer than 0 - * and the WiFi client will drop the data with seq number 0. - * So, the 8712 firmware has to inform driver with receiving the - * ADDBA-Req frame so that the driver can reset the - * sequence value of Rx reorder control. - */ -void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - struct ADDBA_Req_Report_parm *pAddbareq_pram = - (struct ADDBA_Req_Report_parm *)pbuf; - struct sta_info *psta; - struct sta_priv *pstapriv = &adapter->stapriv; - struct recv_reorder_ctrl *precvreorder_ctrl = NULL; - - psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress); - if (psta) { - precvreorder_ctrl = - &psta->recvreorder_ctrl[pAddbareq_pram->tid]; - /* set the indicate_seq to 0xffff so that the rx reorder - * can store any following data packet. - */ - precvreorder_ctrl->indicate_seq = 0xffff; - } -} - -void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf) -{ - if (!adapter->securitypriv.wps_hw_pbc_pressed) - adapter->securitypriv.wps_hw_pbc_pressed = true; -} - -void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter) -{ - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - u64 current_tx_pkts; - uint current_rx_pkts; - - current_tx_pkts = (adapter->xmitpriv.tx_pkts) - - (psitesurveyctrl->last_tx_pkts); - current_rx_pkts = (adapter->recvpriv.rx_pkts) - - (psitesurveyctrl->last_rx_pkts); - psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts; - psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts; - if ((current_tx_pkts > pregistrypriv->busy_thresh) || - (current_rx_pkts > pregistrypriv->busy_thresh)) - psitesurveyctrl->traffic_busy = true; - else - psitesurveyctrl->traffic_busy = false; -} - -void _r8712_join_timeout_handler(struct _adapter *adapter) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - if (adapter->driver_stopped || adapter->surprise_removed) - return; - spin_lock_irqsave(&pmlmepriv->lock, irqL); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - pmlmepriv->to_join = false; - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - r8712_os_indicate_disconnect(adapter); - _clr_fwstate_(pmlmepriv, _FW_LINKED); - } - if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) { - r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt, - adapter->registrypriv.smart_ps); - } - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -void r8712_scan_timeout_handler (struct _adapter *adapter) -{ - unsigned long irqL; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); - pmlmepriv->to_join = false; /* scan fail, so clear to_join flag */ - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -void _r8712_dhcp_timeout_handler (struct _adapter *adapter) -{ - if (adapter->driver_stopped || adapter->surprise_removed) - return; - if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) - r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt, - adapter->registrypriv.smart_ps); -} - -int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv) -{ - struct list_head *phead; - unsigned char *dst_ssid, *src_ssid; - struct _adapter *adapter; - struct __queue *queue = NULL; - struct wlan_network *pnetwork = NULL; - struct wlan_network *pnetwork_max_rssi = NULL; - - adapter = (struct _adapter *)pmlmepriv->nic_hdl; - queue = &pmlmepriv->scanned_queue; - phead = &queue->queue; - pmlmepriv->pscanned = phead->next; - while (1) { - if (end_of_queue_search(phead, pmlmepriv->pscanned)) { - if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) { - pnetwork = pnetwork_max_rssi; - goto ask_for_joinbss; - } - return -EINVAL; - } - pnetwork = container_of(pmlmepriv->pscanned, - struct wlan_network, list); - pmlmepriv->pscanned = pmlmepriv->pscanned->next; - if (pmlmepriv->assoc_by_bssid) { - dst_ssid = pnetwork->network.MacAddress; - src_ssid = pmlmepriv->assoc_bssid; - if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - if (is_same_network(&pmlmepriv->cur_network.network, - &pnetwork->network)) { - _clr_fwstate_(pmlmepriv, - _FW_UNDER_LINKING); - /*r8712_indicate_connect again*/ - r8712_indicate_connect(adapter); - return 2; - } - r8712_disassoc_cmd(adapter); - r8712_ind_disconnect(adapter); - r8712_free_assoc_resources(adapter); - } - goto ask_for_joinbss; - } - } else if (pmlmepriv->assoc_ssid.SsidLength == 0) { - goto ask_for_joinbss; - } - dst_ssid = pnetwork->network.Ssid.Ssid; - src_ssid = pmlmepriv->assoc_ssid.Ssid; - if ((pnetwork->network.Ssid.SsidLength == - pmlmepriv->assoc_ssid.SsidLength) && - (!memcmp(dst_ssid, src_ssid, - pmlmepriv->assoc_ssid.SsidLength))) { - if (pmlmepriv->assoc_by_rssi) { - /* if the ssid is the same, select the bss - * which has the max rssi - */ - if (pnetwork_max_rssi) { - if (pnetwork->network.Rssi > - pnetwork_max_rssi->network.Rssi) - pnetwork_max_rssi = pnetwork; - } else { - pnetwork_max_rssi = pnetwork; - } - } else if (is_desired_network(adapter, pnetwork)) { - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - r8712_disassoc_cmd(adapter); - r8712_free_assoc_resources(adapter); - } - goto ask_for_joinbss; - } - } - } - -ask_for_joinbss: - return r8712_joinbss_cmd(adapter, pnetwork); -} - -int r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv) -{ - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - struct cmd_obj *pcmd; - struct setauth_parm *psetauthparm; - - pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) - return -ENOMEM; - - psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC); - if (!psetauthparm) { - kfree(pcmd); - return -ENOMEM; - } - psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm; - pcmd->cmdcode = _SetAuth_CMD_; - pcmd->parmbuf = (unsigned char *)psetauthparm; - pcmd->cmdsz = sizeof(struct setauth_parm); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - INIT_LIST_HEAD(&pcmd->list); - r8712_enqueue_cmd(pcmdpriv, pcmd); - return 0; -} - -int r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, - sint keyid) -{ - struct cmd_priv *pcmdpriv = &adapter->cmdpriv; - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - u8 keylen; - int ret; - - pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) - return -ENOMEM; - psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC); - if (!psetkeyparm) { - ret = -ENOMEM; - goto err_free_cmd; - } - if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */ - psetkeyparm->algorithm = - (u8)psecuritypriv->XGrpPrivacy; - } else { /* WEP */ - psetkeyparm->algorithm = - (u8)psecuritypriv->PrivacyAlgrthm; - } - psetkeyparm->keyid = (u8)keyid; - - switch (psetkeyparm->algorithm) { - case _WEP40_: - keylen = 5; - memcpy(psetkeyparm->key, - psecuritypriv->DefKey[keyid].skey, keylen); - break; - case _WEP104_: - keylen = 13; - memcpy(psetkeyparm->key, - psecuritypriv->DefKey[keyid].skey, keylen); - break; - case _TKIP_: - if (keyid < 1 || keyid > 2) { - ret = -EINVAL; - goto err_free_parm; - } - keylen = 16; - memcpy(psetkeyparm->key, - &psecuritypriv->XGrpKey[keyid - 1], keylen); - psetkeyparm->grpkey = 1; - break; - case _AES_: - if (keyid < 1 || keyid > 2) { - ret = -EINVAL; - goto err_free_parm; - } - keylen = 16; - memcpy(psetkeyparm->key, - &psecuritypriv->XGrpKey[keyid - 1], keylen); - psetkeyparm->grpkey = 1; - break; - default: - ret = -EINVAL; - goto err_free_parm; - } - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *)psetkeyparm; - pcmd->cmdsz = (sizeof(struct setkey_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - INIT_LIST_HEAD(&pcmd->list); - r8712_enqueue_cmd(pcmdpriv, pcmd); - return 0; - -err_free_parm: - kfree(psetkeyparm); -err_free_cmd: - kfree(pcmd); - return ret; -} - -/* adjust IEs for r8712_joinbss_cmd in WMM */ -int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie, - uint in_len, uint initial_out_len) -{ - unsigned int ielength = 0; - unsigned int i, j; - - i = 12; /* after the fixed IE */ - while (i < in_len) { - ielength = initial_out_len; - if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 && - in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 && - in_ie[i + 5] == 0x02 && i + 5 < in_len) { - /*WMM element ID and OUI*/ - for (j = i; j < i + 9; j++) { - out_ie[ielength] = in_ie[j]; - ielength++; - } - out_ie[initial_out_len + 1] = 0x07; - out_ie[initial_out_len + 6] = 0x00; - out_ie[initial_out_len + 8] = 0x00; - break; - } - i += (in_ie[i + 1] + 2); /* to the next IE element */ - } - return ielength; -} - -/* - * Ported from 8185: IsInPreAuthKeyList(). - * - * Search by BSSID, - * Return Value: - * -1 :if there is no pre-auth key in the table - * >=0 :if there is pre-auth key, and return the entry id - */ -static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid) -{ - struct security_priv *p = &Adapter->securitypriv; - int i; - - for (i = 0; i < NUM_PMKID_CACHE; i++) - if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN)) - return i; - return -1; -} - -sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, - u8 *out_ie, uint in_len) -{ - u8 authmode = 0, match; - u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255]; - u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; - uint ielength, cnt, remove_cnt; - int iEntry; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - struct security_priv *psecuritypriv = &adapter->securitypriv; - uint ndisauthmode = psecuritypriv->ndisauthtype; - uint ndissecuritytype = psecuritypriv->ndisencryptstatus; - - if ((ndisauthmode == Ndis802_11AuthModeWPA) || - (ndisauthmode == Ndis802_11AuthModeWPAPSK)) { - authmode = _WPA_IE_ID_; - uncst_oui[0] = 0x0; - uncst_oui[1] = 0x50; - uncst_oui[2] = 0xf2; - } - if ((ndisauthmode == Ndis802_11AuthModeWPA2) || - (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) { - authmode = _WPA2_IE_ID_; - uncst_oui[0] = 0x0; - uncst_oui[1] = 0x0f; - uncst_oui[2] = 0xac; - } - switch (ndissecuritytype) { - case Ndis802_11Encryption1Enabled: - case Ndis802_11Encryption1KeyAbsent: - uncst_oui[3] = 0x1; - break; - case Ndis802_11Encryption2Enabled: - case Ndis802_11Encryption2KeyAbsent: - uncst_oui[3] = 0x2; - break; - case Ndis802_11Encryption3Enabled: - case Ndis802_11Encryption3KeyAbsent: - uncst_oui[3] = 0x4; - break; - default: - break; - } - /*Search required WPA or WPA2 IE and copy to sec_ie[] */ - cnt = 12; - match = false; - while (cnt < in_len) { - if (in_ie[cnt] == authmode) { - if ((authmode == _WPA_IE_ID_) && - (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) { - memcpy(&sec_ie[0], &in_ie[cnt], - in_ie[cnt + 1] + 2); - match = true; - break; - } - if (authmode == _WPA2_IE_ID_) { - memcpy(&sec_ie[0], &in_ie[cnt], - in_ie[cnt + 1] + 2); - match = true; - break; - } - if (((authmode == _WPA_IE_ID_) && - (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) || - (authmode == _WPA2_IE_ID_)) - memcpy(&bkup_ie[0], &in_ie[cnt], - in_ie[cnt + 1] + 2); - } - cnt += in_ie[cnt + 1] + 2; /*get next*/ - } - /*restruct WPA IE or WPA2 IE in sec_ie[] */ - if (match) { - if (sec_ie[0] == _WPA_IE_ID_) { - /* parsing SSN IE to select required encryption - * algorithm, and set the bc/mc encryption algorithm - */ - while (true) { - /*check wpa_oui tag*/ - if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) { - match = false; - break; - } - if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) { - /*IE Ver error*/ - match = false; - break; - } - if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) { - /* get bc/mc encryption type (group - * key type) - */ - switch (sec_ie[11]) { - case 0x0: /*none*/ - psecuritypriv->XGrpPrivacy = - _NO_PRIVACY_; - break; - case 0x1: /*WEP_40*/ - psecuritypriv->XGrpPrivacy = - _WEP40_; - break; - case 0x2: /*TKIP*/ - psecuritypriv->XGrpPrivacy = - _TKIP_; - break; - case 0x3: /*AESCCMP*/ - case 0x4: - psecuritypriv->XGrpPrivacy = - _AES_; - break; - case 0x5: /*WEP_104*/ - psecuritypriv->XGrpPrivacy = - _WEP104_; - break; - } - } else { - match = false; - break; - } - if (sec_ie[12] == 0x01) { - /*check the unicast encryption type*/ - if (memcmp(&sec_ie[14], - &uncst_oui[0], 4)) { - match = false; - break; - - } /*else the uncst_oui is match*/ - } else { /*mixed mode, unicast_enc_type > 1*/ - /*select the uncst_oui and remove - * the other uncst_oui - */ - cnt = sec_ie[12]; - remove_cnt = (cnt - 1) * 4; - sec_ie[12] = 0x01; - memcpy(&sec_ie[14], &uncst_oui[0], 4); - /*remove the other unicast suit*/ - memcpy(&sec_ie[18], - &sec_ie[18 + remove_cnt], - sec_ie[1] - 18 + 2 - - remove_cnt); - sec_ie[1] = sec_ie[1] - remove_cnt; - } - break; - } - } - if (authmode == _WPA2_IE_ID_) { - /* parsing RSN IE to select required encryption - * algorithm, and set the bc/mc encryption algorithm - */ - while (true) { - if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) { - /*IE Ver error*/ - match = false; - break; - } - if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) { - /*get bc/mc encryption type*/ - switch (sec_ie[7]) { - case 0x1: /*WEP_40*/ - psecuritypriv->XGrpPrivacy = - _WEP40_; - break; - case 0x2: /*TKIP*/ - psecuritypriv->XGrpPrivacy = - _TKIP_; - break; - case 0x4: /*AESWRAP*/ - psecuritypriv->XGrpPrivacy = - _AES_; - break; - case 0x5: /*WEP_104*/ - psecuritypriv->XGrpPrivacy = - _WEP104_; - break; - default: /*one*/ - psecuritypriv->XGrpPrivacy = - _NO_PRIVACY_; - break; - } - } else { - match = false; - break; - } - if (sec_ie[8] == 0x01) { - /*check the unicast encryption type*/ - if (memcmp(&sec_ie[10], - &uncst_oui[0], 4)) { - match = false; - break; - } /*else the uncst_oui is match*/ - } else { /*mixed mode, unicast_enc_type > 1*/ - /*select the uncst_oui and remove the - * other uncst_oui - */ - cnt = sec_ie[8]; - remove_cnt = (cnt - 1) * 4; - sec_ie[8] = 0x01; - memcpy(&sec_ie[10], &uncst_oui[0], 4); - /*remove the other unicast suit*/ - memcpy(&sec_ie[14], - &sec_ie[14 + remove_cnt], - (sec_ie[1] - 14 + 2 - - remove_cnt)); - sec_ie[1] = sec_ie[1] - remove_cnt; - } - break; - } - } - } - if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) { - /*copy fixed ie*/ - memcpy(out_ie, in_ie, 12); - ielength = 12; - /*copy RSN or SSN*/ - if (match) { - memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2); - ielength += sec_ie[1] + 2; - if (authmode == _WPA2_IE_ID_) { - /*the Pre-Authentication bit should be zero*/ - out_ie[ielength - 1] = 0; - out_ie[ielength - 2] = 0; - } - r8712_report_sec_ie(adapter, authmode, sec_ie); - } - } else { - /*copy fixed ie only*/ - memcpy(out_ie, in_ie, 12); - ielength = 12; - if (psecuritypriv->wps_phase) { - memcpy(out_ie + ielength, psecuritypriv->wps_ie, - psecuritypriv->wps_ie_len); - ielength += psecuritypriv->wps_ie_len; - } - } - iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid); - if (iEntry < 0) - return ielength; - if (authmode == _WPA2_IE_ID_) { - out_ie[ielength] = 1; - ielength++; - out_ie[ielength] = 0; /*PMKID count = 0x0100*/ - ielength++; - memcpy(&out_ie[ielength], - &psecuritypriv->PMKIDList[iEntry].PMKID, 16); - ielength += 16; - out_ie[13] += 18;/*PMKID length = 2+16*/ - } - return ielength; -} - -void r8712_init_registrypriv_dev_network(struct _adapter *adapter) -{ - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct eeprom_priv *peepriv = &adapter->eeprompriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - u8 *myhwaddr = myid(peepriv); - - memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN); - memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, - sizeof(struct ndis_802_11_ssid)); - pdev_network->Configuration.Length = - sizeof(struct NDIS_802_11_CONFIGURATION); - pdev_network->Configuration.BeaconPeriod = 100; - pdev_network->Configuration.FHConfig.Length = 0; - pdev_network->Configuration.FHConfig.HopPattern = 0; - pdev_network->Configuration.FHConfig.HopSet = 0; - pdev_network->Configuration.FHConfig.DwellTime = 0; -} - -void r8712_update_registrypriv_dev_network(struct _adapter *adapter) -{ - int sz = 0; - struct registry_priv *pregistrypriv = &adapter->registrypriv; - struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network; - struct security_priv *psecuritypriv = &adapter->securitypriv; - struct wlan_network *cur_network = &adapter->mlmepriv.cur_network; - - pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm - > 0 ? 1 : 0); /* adhoc no 802.1x */ - pdev_network->Rssi = 0; - switch (pregistrypriv->wireless_mode) { - case WIRELESS_11B: - pdev_network->NetworkTypeInUse = Ndis802_11DS; - break; - case WIRELESS_11G: - case WIRELESS_11BG: - pdev_network->NetworkTypeInUse = Ndis802_11OFDM24; - break; - case WIRELESS_11A: - pdev_network->NetworkTypeInUse = Ndis802_11OFDM5; - break; - default: - /* TODO */ - break; - } - pdev_network->Configuration.DSConfig = pregistrypriv->channel; - if (cur_network->network.InfrastructureMode == Ndis802_11IBSS) - pdev_network->Configuration.ATIMWindow = 3; - pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode; - /* 1. Supported rates - * 2. IE - */ - sz = r8712_generate_ie(pregistrypriv); - pdev_network->IELength = sz; - pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network); -} - -/*the function is at passive_level*/ -void r8712_joinbss_reset(struct _adapter *padapter) -{ - int i; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - /* todo: if you want to do something io/reg/hw setting before join_bss, - * please add code here - */ - phtpriv->ampdu_enable = false;/*reset to disabled*/ - for (i = 0; i < 16; i++) - phtpriv->baddbareq_issued[i] = false;/*reset it*/ - if (phtpriv->ht_option) { - /* validate usb rx aggregation */ - r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/ - } else { - /* invalidate usb rx aggregation */ - /* TH=1 => means that invalidate usb rx aggregation */ - r8712_write8(padapter, 0x102500D9, 1); - } -} - -/*the function is >= passive_level*/ -unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len) -{ - u32 ielen, out_len; - unsigned char *p; - struct ieee80211_ht_cap ht_capie; - unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - phtpriv->ht_option = 0; - p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12); - if (p && (ielen > 0)) { - if (pqospriv->qos_option == 0) { - out_len = *pout_len; - r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC, - _WMM_IE_Length_, WMM_IE, pout_len); - pqospriv->qos_option = 1; - } - out_len = *pout_len; - memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap)); - ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | - IEEE80211_HT_CAP_MAX_AMSDU | - IEEE80211_HT_CAP_DSSSCCK40); - ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR & - 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00); - r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY, - sizeof(struct ieee80211_ht_cap), - (unsigned char *)&ht_capie, pout_len); - phtpriv->ht_option = 1; - } - return phtpriv->ht_option; -} - -/* the function is > passive_level (in critical_section) */ -static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len) -{ - u8 *p, max_ampdu_sz; - int i; - uint len; - struct sta_info *bmc_sta, *psta; - struct ieee80211_ht_cap *pht_capie; - struct recv_reorder_ctrl *preorder_ctrl; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct wlan_network *pcur_network = &(pmlmepriv->cur_network); - - if (!phtpriv->ht_option) - return; - /* maybe needs check if ap supports rx ampdu. */ - if (!phtpriv->ampdu_enable && - (pregistrypriv->ampdu_enable == 1)) - phtpriv->ampdu_enable = true; - /*check Max Rx A-MPDU Size*/ - len = 0; - p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs), - WLAN_EID_HT_CAPABILITY, - &len, ie_len - - sizeof(struct NDIS_802_11_FIXED_IEs)); - if (p && len > 0) { - pht_capie = (struct ieee80211_ht_cap *)(p + 2); - max_ampdu_sz = (pht_capie->ampdu_params_info & - IEEE80211_HT_AMPDU_PARM_FACTOR); - /* max_ampdu_sz (kbytes); */ - max_ampdu_sz = 1 << (max_ampdu_sz + 3); - phtpriv->rx_ampdu_maxlen = max_ampdu_sz; - } - /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info - * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl - * wstart_b(indicate_seq) to default value=0xffff - * todo: check if AP can send A-MPDU packets - */ - bmc_sta = r8712_get_bcmc_stainfo(padapter); - if (bmc_sta) { - for (i = 0; i < 16; i++) { - preorder_ctrl = &bmc_sta->recvreorder_ctrl[i]; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - } - } - psta = r8712_get_stainfo(&padapter->stapriv, - pcur_network->network.MacAddress); - if (psta) { - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - } - } - len = 0; - p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs), - WLAN_EID_HT_OPERATION, &len, - ie_len - sizeof(struct NDIS_802_11_FIXED_IEs)); -} - -void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct ht_priv *phtpriv = &pmlmepriv->htpriv; - - if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) { - if (!phtpriv->baddbareq_issued[priority]) { - r8712_addbareq_cmd(padapter, (u8)priority); - phtpriv->baddbareq_issued[priority] = true; - } - } -} diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h deleted file mode 100644 index d7d25f240111fadf20365c72bb0297582a081d30..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ /dev/null @@ -1,205 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_MLME_H_ -#define __RTL871X_MLME_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wlan_bssdef.h" - -#define MAX_BSS_CNT 64 -#define MAX_JOIN_TIMEOUT 6000 - -#define SCANNING_TIMEOUT 4500 - -#define SCANQUEUE_LIFETIME 20 /* unit:sec */ - -#define WIFI_NULL_STATE 0x00000000 -#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state...*/ -#define WIFI_REASOC_STATE 0x00000002 -#define WIFI_SLEEP_STATE 0x00000004 -#define WIFI_STATION_STATE 0x00000008 -#define WIFI_AP_STATE 0x00000010 -#define WIFI_ADHOC_STATE 0x00000020 -#define WIFI_ADHOC_MASTER_STATE 0x00000040 -#define WIFI_UNDER_LINKING 0x00000080 -#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station - * is under site surveying - */ -#define WIFI_MP_STATE 0x00010000 -#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in cont. tx background*/ -#define WIFI_MP_CTX_ST 0x00040000 /* in cont. tx with - * single-tone - */ -#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in cont, tx - * background due - * to out of skb - */ -#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx*/ -#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in cont, tx with carrier - * suppression - */ -#define WIFI_MP_LPBK_STATE 0x00400000 - -#define _FW_UNDER_LINKING WIFI_UNDER_LINKING -#define _FW_LINKED WIFI_ASOC_STATE -#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR - -/* - * there are several "locks" in mlme_priv, - * since mlme_priv is a shared resource between many threads, - * like ISR/Call-Back functions, the OID handlers, and even timer functions. - * Each _queue has its own locks, already. - * Other items are protected by mlme_priv.lock. - * To avoid possible dead lock, any thread trying to modify mlme_priv - * SHALL not lock up more than one lock at a time! - */ - -#define traffic_threshold 10 -#define traffic_scan_period 500 - -struct sitesurvey_ctrl { - u64 last_tx_pkts; - uint last_rx_pkts; - sint traffic_busy; - struct timer_list sitesurvey_ctrl_timer; -}; - -struct mlme_priv { - spinlock_t lock; - spinlock_t lock2; - sint fw_state; /*shall we protect this variable? */ - u8 to_join; /*flag*/ - u8 *nic_hdl; - struct list_head *pscanned; - struct __queue free_bss_pool; - struct __queue scanned_queue; - u8 *free_bss_buf; - unsigned long num_of_scanned; - u8 passive_mode; /*add for Android's SCAN-ACTIVE/SCAN-PASSIVE */ - struct ndis_802_11_ssid assoc_ssid; - u8 assoc_bssid[6]; - struct wlan_network cur_network; - struct sitesurvey_ctrl sitesurveyctrl; - struct timer_list assoc_timer; - uint assoc_by_bssid; - uint assoc_by_rssi; - struct timer_list scan_to_timer; /* driver handles scan_timeout.*/ - struct timer_list dhcp_timer; /* set dhcp to if driver in ps mode.*/ - struct qos_priv qospriv; - struct ht_priv htpriv; - struct timer_list wdg_timer; /*watchdog periodic timer*/ -}; - -static inline u8 *get_bssid(struct mlme_priv *pmlmepriv) -{ - return pmlmepriv->cur_network.network.MacAddress; -} - -static inline u8 check_fwstate(struct mlme_priv *pmlmepriv, sint state) -{ - if (pmlmepriv->fw_state & state) - return true; - return false; -} - -static inline sint get_fwstate(struct mlme_priv *pmlmepriv) -{ - return pmlmepriv->fw_state; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - * - * ### NOTE:#### (!!!!) - * TAKE CARE BEFORE CALLING THIS FUNC, LOCK pmlmepriv->lock - */ -static inline void set_fwstate(struct mlme_priv *pmlmepriv, sint state) -{ - pmlmepriv->fw_state |= state; -} - -static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) -{ - pmlmepriv->fw_state &= ~state; -} - -/* - * No Limit on the calling context, - * therefore set it to be the critical section... - */ -static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) -{ - unsigned long irqL; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, state)) - pmlmepriv->fw_state ^= state; - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, - sint val) -{ - unsigned long irqL; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - pmlmepriv->num_of_scanned = val; - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); -} - -void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf); -void r8712_free_network_queue(struct _adapter *adapter); -int r8712_init_mlme_priv(struct _adapter *adapter); -void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv); -int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv); -int r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, sint keyid); -int r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv); -uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); -void r8712_generate_random_ibss(u8 *pibss); -u8 *r8712_get_capability_from_ie(u8 *ie); -struct wlan_network *r8712_get_oldest_wlan_network( - struct __queue *scanned_queue); -void r8712_free_assoc_resources(struct _adapter *adapter); -void r8712_ind_disconnect(struct _adapter *adapter); -void r8712_indicate_connect(struct _adapter *adapter); -int r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie, - u8 *out_ie, uint in_len); -int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint initial_out_len); -void r8712_init_registrypriv_dev_network(struct _adapter *adapter); -void r8712_update_registrypriv_dev_network(struct _adapter *adapter); -void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter); -void _r8712_join_timeout_handler(struct _adapter *adapter); -void r8712_scan_timeout_handler(struct _adapter *adapter); -void _r8712_dhcp_timeout_handler(struct _adapter *adapter); -struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv); -sint r8712_if_up(struct _adapter *padapter); -void r8712_joinbss_reset(struct _adapter *padapter); -unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie, - u8 *out_ie, uint in_len, uint *pout_len); -void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority); -int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork); - -#endif /*__RTL871X_MLME_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c deleted file mode 100644 index 099c512c8519fac29681eacd09335f8e76c70e77..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mp.c +++ /dev/null @@ -1,724 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#define _RTL871X_MP_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "rtl871x_mp_phy_regdef.h" -#include "rtl8712_cmd.h" - -static void _init_mp_priv_(struct mp_priv *pmp_priv) -{ - pmp_priv->mode = _LOOPBOOK_MODE_; - pmp_priv->curr_ch = 1; - pmp_priv->curr_modem = MIXED_PHY; - pmp_priv->curr_rateidx = 0; - pmp_priv->curr_txpoweridx = 0x14; - pmp_priv->antenna_tx = ANTENNA_A; - pmp_priv->antenna_rx = ANTENNA_AB; - pmp_priv->check_mp_pkt = 0; - pmp_priv->tx_pktcount = 0; - pmp_priv->rx_pktcount = 0; - pmp_priv->rx_crcerrpktcount = 0; -} - -static int init_mp_priv(struct mp_priv *pmp_priv) -{ - int i; - struct mp_xmit_frame *pmp_xmitframe; - - _init_mp_priv_(pmp_priv); - _init_queue(&pmp_priv->free_mp_xmitqueue); - pmp_priv->pallocated_mp_xmitframe_buf = NULL; - pmp_priv->pallocated_mp_xmitframe_buf = kmalloc(NR_MP_XMITFRAME * - sizeof(struct mp_xmit_frame) + 4, - GFP_ATOMIC); - if (!pmp_priv->pallocated_mp_xmitframe_buf) - return -ENOMEM; - - pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf + - 4 - - ((addr_t)(pmp_priv->pallocated_mp_xmitframe_buf) & 3); - pmp_xmitframe = (struct mp_xmit_frame *)pmp_priv->pmp_xmtframe_buf; - for (i = 0; i < NR_MP_XMITFRAME; i++) { - INIT_LIST_HEAD(&(pmp_xmitframe->list)); - list_add_tail(&(pmp_xmitframe->list), - &(pmp_priv->free_mp_xmitqueue.queue)); - pmp_xmitframe->pkt = NULL; - pmp_xmitframe->frame_tag = MP_FRAMETAG; - pmp_xmitframe->padapter = pmp_priv->papdater; - pmp_xmitframe++; - } - pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME; - return 0; -} - -static int free_mp_priv(struct mp_priv *pmp_priv) -{ - kfree(pmp_priv->pallocated_mp_xmitframe_buf); - return 0; -} - -void mp871xinit(struct _adapter *padapter) -{ - struct mp_priv *pmppriv = &padapter->mppriv; - - pmppriv->papdater = padapter; - init_mp_priv(pmppriv); -} - -void mp871xdeinit(struct _adapter *padapter) -{ - struct mp_priv *pmppriv = &padapter->mppriv; - - free_mp_priv(pmppriv); -} - -/* - * Special for bb and rf reg read/write - */ -static u32 fw_iocmd_read(struct _adapter *pAdapter, struct IOCMD_STRUCT iocmd) -{ - u32 cmd32 = 0, val32 = 0; - u8 iocmd_class = iocmd.cmdclass; - u16 iocmd_value = iocmd.value; - u8 iocmd_idx = iocmd.index; - - cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx; - if (r8712_fw_cmd(pAdapter, cmd32)) - r8712_fw_cmd_data(pAdapter, &val32, 1); - else - val32 = 0; - return val32; -} - -static u8 fw_iocmd_write(struct _adapter *pAdapter, - struct IOCMD_STRUCT iocmd, u32 value) -{ - u32 cmd32 = 0; - u8 iocmd_class = iocmd.cmdclass; - u32 iocmd_value = iocmd.value; - u8 iocmd_idx = iocmd.index; - - r8712_fw_cmd_data(pAdapter, &value, 0); - msleep(100); - cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx; - return r8712_fw_cmd(pAdapter, cmd32); -} - -/* offset : 0X800~0XFFF */ -u32 r8712_bb_reg_read(struct _adapter *pAdapter, u16 offset) -{ - u8 shift = offset & 0x0003; /* 4 byte access */ - u16 bb_addr = offset & 0x0FFC; /* 4 byte access */ - u32 bb_val = 0; - struct IOCMD_STRUCT iocmd; - - iocmd.cmdclass = IOCMD_CLASS_BB_RF; - iocmd.value = bb_addr; - iocmd.index = IOCMD_BB_READ_IDX; - bb_val = fw_iocmd_read(pAdapter, iocmd); - if (shift != 0) { - u32 bb_val2 = 0; - - bb_val >>= (shift * 8); - iocmd.value += 4; - bb_val2 = fw_iocmd_read(pAdapter, iocmd); - bb_val2 <<= ((4 - shift) * 8); - bb_val |= bb_val2; - } - return bb_val; -} - -/* offset : 0X800~0XFFF */ -u8 r8712_bb_reg_write(struct _adapter *pAdapter, u16 offset, u32 value) -{ - u8 shift = offset & 0x0003; /* 4 byte access */ - u16 bb_addr = offset & 0x0FFC; /* 4 byte access */ - struct IOCMD_STRUCT iocmd; - - iocmd.cmdclass = IOCMD_CLASS_BB_RF; - iocmd.value = bb_addr; - iocmd.index = IOCMD_BB_WRITE_IDX; - if (shift != 0) { - u32 oldValue = 0; - u32 newValue = value; - - oldValue = r8712_bb_reg_read(pAdapter, iocmd.value); - oldValue &= (0xFFFFFFFF >> ((4 - shift) * 8)); - value = oldValue | (newValue << (shift * 8)); - if (!fw_iocmd_write(pAdapter, iocmd, value)) - return false; - iocmd.value += 4; - oldValue = r8712_bb_reg_read(pAdapter, iocmd.value); - oldValue &= (0xFFFFFFFF << (shift * 8)); - value = oldValue | (newValue >> ((4 - shift) * 8)); - } - return fw_iocmd_write(pAdapter, iocmd, value); -} - -/* offset : 0x00 ~ 0xFF */ -u32 r8712_rf_reg_read(struct _adapter *pAdapter, u8 path, u8 offset) -{ - u16 rf_addr = (path << 8) | offset; - struct IOCMD_STRUCT iocmd; - - iocmd.cmdclass = IOCMD_CLASS_BB_RF; - iocmd.value = rf_addr; - iocmd.index = IOCMD_RF_READ_IDX; - return fw_iocmd_read(pAdapter, iocmd); -} - -u8 r8712_rf_reg_write(struct _adapter *pAdapter, u8 path, u8 offset, u32 value) -{ - u16 rf_addr = (path << 8) | offset; - struct IOCMD_STRUCT iocmd; - - iocmd.cmdclass = IOCMD_CLASS_BB_RF; - iocmd.value = rf_addr; - iocmd.index = IOCMD_RF_WRIT_IDX; - return fw_iocmd_write(pAdapter, iocmd, value); -} - -static u32 bitshift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) - if (((bitmask >> i) & 0x1) == 1) - break; - return i; -} - -static u32 get_bb_reg(struct _adapter *pAdapter, u16 offset, u32 bitmask) -{ - u32 org_value, bit_shift; - - org_value = r8712_bb_reg_read(pAdapter, offset); - bit_shift = bitshift(bitmask); - return (org_value & bitmask) >> bit_shift; -} - -static u8 set_bb_reg(struct _adapter *pAdapter, - u16 offset, - u32 bitmask, - u32 value) -{ - u32 org_value, bit_shift, new_value; - - if (bitmask != bMaskDWord) { - org_value = r8712_bb_reg_read(pAdapter, offset); - bit_shift = bitshift(bitmask); - new_value = (org_value & (~bitmask)) | (value << bit_shift); - } else { - new_value = value; - } - return r8712_bb_reg_write(pAdapter, offset, new_value); -} - -static u32 get_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset, - u32 bitmask) -{ - u32 org_value, bit_shift; - - org_value = r8712_rf_reg_read(pAdapter, path, offset); - bit_shift = bitshift(bitmask); - return (org_value & bitmask) >> bit_shift; -} - -static u8 set_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset, u32 bitmask, - u32 value) -{ - u32 org_value, bit_shift, new_value; - - if (bitmask != bMaskDWord) { - org_value = r8712_rf_reg_read(pAdapter, path, offset); - bit_shift = bitshift(bitmask); - new_value = (org_value & (~bitmask)) | (value << bit_shift); - } else { - new_value = value; - } - return r8712_rf_reg_write(pAdapter, path, offset, new_value); -} - -/* - * SetChannel - * Description - * Use H2C command to change channel, - * not only modify rf register, but also other setting need to be done. - */ -void r8712_SetChannel(struct _adapter *pAdapter) -{ - struct cmd_priv *pcmdpriv = &pAdapter->cmdpriv; - struct cmd_obj *pcmd = NULL; - struct SetChannel_parm *pparm = NULL; - u16 code = GEN_CMD_CODE(_SetChannel); - - pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); - if (!pcmd) - return; - pparm = kmalloc(sizeof(*pparm), GFP_ATOMIC); - if (!pparm) { - kfree(pcmd); - return; - } - pparm->curr_ch = pAdapter->mppriv.curr_ch; - init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code); - r8712_enqueue_cmd(pcmdpriv, pcmd); -} - -static void SetCCKTxPower(struct _adapter *pAdapter, u8 TxPower) -{ - u16 TxAGC = 0; - - TxAGC = TxPower; - set_bb_reg(pAdapter, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); -} - -static void SetOFDMTxPower(struct _adapter *pAdapter, u8 TxPower) -{ - u32 TxAGC = 0; - - TxAGC |= ((TxPower << 24) | (TxPower << 16) | (TxPower << 8) | - TxPower); - set_bb_reg(pAdapter, rTxAGC_Rate18_06, bTxAGCRate18_06, TxAGC); - set_bb_reg(pAdapter, rTxAGC_Rate54_24, bTxAGCRate54_24, TxAGC); - set_bb_reg(pAdapter, rTxAGC_Mcs03_Mcs00, bTxAGCRateMCS3_MCS0, TxAGC); - set_bb_reg(pAdapter, rTxAGC_Mcs07_Mcs04, bTxAGCRateMCS7_MCS4, TxAGC); - set_bb_reg(pAdapter, rTxAGC_Mcs11_Mcs08, bTxAGCRateMCS11_MCS8, TxAGC); - set_bb_reg(pAdapter, rTxAGC_Mcs15_Mcs12, bTxAGCRateMCS15_MCS12, TxAGC); -} - -void r8712_SetTxPower(struct _adapter *pAdapter) -{ - u8 TxPower = pAdapter->mppriv.curr_txpoweridx; - - SetCCKTxPower(pAdapter, TxPower); - SetOFDMTxPower(pAdapter, TxPower); -} - -void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset) -{ - u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D, tmpAGC; - - TxAGCOffset_B = ulTxAGCOffset & 0x000000ff; - TxAGCOffset_C = (ulTxAGCOffset & 0x0000ff00) >> 8; - TxAGCOffset_D = (ulTxAGCOffset & 0x00ff0000) >> 16; - tmpAGC = TxAGCOffset_D << 8 | TxAGCOffset_C << 4 | TxAGCOffset_B; - set_bb_reg(pAdapter, rFPGA0_TxGainStage, - (bXBTxAGC | bXCTxAGC | bXDTxAGC), tmpAGC); -} - -void r8712_SetDataRate(struct _adapter *pAdapter) -{ - u8 path = RF_PATH_A; - u8 offset = RF_SYN_G2; - u32 value; - - value = (pAdapter->mppriv.curr_rateidx < 4) ? 0x4440 : 0xF200; - r8712_rf_reg_write(pAdapter, path, offset, value); -} - -void r8712_SwitchBandwidth(struct _adapter *pAdapter) -{ - /* 3 1.Set MAC register : BWOPMODE bit2:1 20MhzBW */ - u8 regBwOpMode = 0; - u8 Bandwidth = pAdapter->mppriv.curr_bandwidth; - - regBwOpMode = r8712_read8(pAdapter, 0x10250203); - if (Bandwidth == HT_CHANNEL_WIDTH_20) - regBwOpMode |= BIT(2); - else - regBwOpMode &= ~(BIT(2)); - r8712_write8(pAdapter, 0x10250203, regBwOpMode); - /* 3 2.Set PHY related register */ - switch (Bandwidth) { - /* 20 MHz channel*/ - case HT_CHANNEL_WIDTH_20: - set_bb_reg(pAdapter, rFPGA0_RFMOD, bRFMOD, 0x0); - set_bb_reg(pAdapter, rFPGA1_RFMOD, bRFMOD, 0x0); - /* Use PHY_REG.txt default value. Do not need to change. - * Correct the tx power for CCK rate in 40M. - * It is set in Tx descriptor for 8192x series - */ - set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x58); - break; - /* 40 MHz channel*/ - case HT_CHANNEL_WIDTH_40: - set_bb_reg(pAdapter, rFPGA0_RFMOD, bRFMOD, 0x1); - set_bb_reg(pAdapter, rFPGA1_RFMOD, bRFMOD, 0x1); - /* Use PHY_REG.txt default value. Do not need to change. - * Correct the tx power for CCK rate in 40M. - * Set Control channel to upper or lower. These settings are - * required only for 40MHz - */ - set_bb_reg(pAdapter, rCCK0_System, bCCKSideBand, - (HAL_PRIME_CHNL_OFFSET_DONT_CARE >> 1)); - set_bb_reg(pAdapter, rOFDM1_LSTF, 0xC00, - HAL_PRIME_CHNL_OFFSET_DONT_CARE); - set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x18); - break; - default: - break; - } - - /* 3 3.Set RF related register */ - switch (Bandwidth) { - case HT_CHANNEL_WIDTH_20: - set_rf_reg(pAdapter, RF_PATH_A, RF_CHNLBW, - BIT(10) | BIT(11), 0x01); - break; - case HT_CHANNEL_WIDTH_40: - set_rf_reg(pAdapter, RF_PATH_A, RF_CHNLBW, - BIT(10) | BIT(11), 0x00); - break; - default: - break; - } -} - -/*------------------------------Define structure----------------------------*/ -struct R_ANTENNA_SELECT_OFDM { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 OFDM_TXSC:2; - u32 Reserved:2; -}; - -struct R_ANTENNA_SELECT_CCK { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -void r8712_SwitchAntenna(struct _adapter *pAdapter) -{ - u32 ofdm_tx_en_val = 0, ofdm_tx_ant_sel_val = 0; - u8 ofdm_rx_ant_sel_val = 0; - u8 cck_ant_select_val = 0; - u32 cck_ant_sel_val = 0; - struct R_ANTENNA_SELECT_CCK *p_cck_txrx; - - p_cck_txrx = (struct R_ANTENNA_SELECT_CCK *)&cck_ant_select_val; - - switch (pAdapter->mppriv.antenna_tx) { - case ANTENNA_A: - /* From SD3 Willis suggestion !!! Set RF A=TX and B as standby*/ - set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2); - set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1); - ofdm_tx_en_val = 0x3; - ofdm_tx_ant_sel_val = 0x11111111;/* Power save */ - p_cck_txrx->r_ccktx_enable = 0x8; - break; - case ANTENNA_B: - set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1); - set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2); - ofdm_tx_en_val = 0x3; - ofdm_tx_ant_sel_val = 0x22222222;/* Power save */ - p_cck_txrx->r_ccktx_enable = 0x4; - break; - case ANTENNA_AB: /* For 8192S */ - set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2); - set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2); - ofdm_tx_en_val = 0x3; - ofdm_tx_ant_sel_val = 0x3321333; /* Disable Power save */ - p_cck_txrx->r_ccktx_enable = 0xC; - break; - default: - break; - } - /*OFDM Tx*/ - set_bb_reg(pAdapter, rFPGA1_TxInfo, 0xffffffff, ofdm_tx_ant_sel_val); - /*OFDM Tx*/ - set_bb_reg(pAdapter, rFPGA0_TxInfo, 0x0000000f, ofdm_tx_en_val); - switch (pAdapter->mppriv.antenna_rx) { - case ANTENNA_A: - ofdm_rx_ant_sel_val = 0x1; /* A */ - p_cck_txrx->r_cckrx_enable = 0x0; /* default: A */ - p_cck_txrx->r_cckrx_enable_2 = 0x0; /* option: A */ - break; - case ANTENNA_B: - ofdm_rx_ant_sel_val = 0x2; /* B */ - p_cck_txrx->r_cckrx_enable = 0x1; /* default: B */ - p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option: B */ - break; - case ANTENNA_AB: - ofdm_rx_ant_sel_val = 0x3; /* AB */ - p_cck_txrx->r_cckrx_enable = 0x0; /* default:A */ - p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option:B */ - break; - default: - break; - } - /*OFDM Rx*/ - set_bb_reg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f, - ofdm_rx_ant_sel_val); - /*OFDM Rx*/ - set_bb_reg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f, - ofdm_rx_ant_sel_val); - - cck_ant_sel_val = cck_ant_select_val; - /*CCK TxRx*/ - set_bb_reg(pAdapter, rCCK0_AFESetting, bMaskByte3, cck_ant_sel_val); -} - -static void TriggerRFThermalMeter(struct _adapter *pAdapter) -{ - /* 0x24: RF Reg[6:5] */ - set_rf_reg(pAdapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60); -} - -static u32 ReadRFThermalMeter(struct _adapter *pAdapter) -{ - /* 0x24: RF Reg[4:0] */ - return get_rf_reg(pAdapter, RF_PATH_A, RF_T_METER, 0x1F); -} - -void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value) -{ - TriggerRFThermalMeter(pAdapter); - msleep(1000); - *value = ReadRFThermalMeter(pAdapter); -} - -void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart) -{ - if (bStart) { /* Start Single Carrier. */ - /* 1. if OFDM block on? */ - if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn)) - /*set OFDM block on*/ - set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable); - /* 2. set CCK test mode off, set to CCK normal mode */ - set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, bDisable); - /* 3. turn on scramble setting */ - set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable); - /* 4. Turn On Single Carrier Tx and off the other test modes. */ - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable); - } else { /* Stop Single Carrier.*/ - /* Turn off all test modes.*/ - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, - bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable); - msleep(20); - /*BB Reset*/ - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); - } -} - -void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart) -{ - u8 rfPath; - - switch (pAdapter->mppriv.antenna_tx) { - case ANTENNA_B: - rfPath = RF_PATH_B; - break; - case ANTENNA_A: - default: - rfPath = RF_PATH_A; - break; - } - if (bStart) { /* Start Single Tone.*/ - set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bDisable); - set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bDisable); - set_rf_reg(pAdapter, rfPath, RF_TX_G2, bRFRegOffsetMask, - 0xd4000); - msleep(100); - /* PAD all on.*/ - set_rf_reg(pAdapter, rfPath, RF_AC, bRFRegOffsetMask, 0x2001f); - msleep(100); - } else { /* Stop Single Tone.*/ - set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable); - set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable); - set_rf_reg(pAdapter, rfPath, RF_TX_G2, bRFRegOffsetMask, - 0x54000); - msleep(100); - /* PAD all on.*/ - set_rf_reg(pAdapter, rfPath, RF_AC, bRFRegOffsetMask, 0x30000); - msleep(100); - } -} - -void r8712_SetCarrierSuppressionTx(struct _adapter *pAdapter, u8 bStart) -{ - if (bStart) { /* Start Carrier Suppression.*/ - if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) { - /* 1. if CCK block on? */ - if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) { - /*set CCK block on*/ - set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, - bEnable); - } - /* Turn Off All Test Mode */ - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, - bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, - bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, - bDisable); - /*transmit mode*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); - /*turn off scramble setting*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, - bDisable); - /*Set CCK Tx Test Rate*/ - /*Set FTxRate to 1Mbps*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, 0x0); - } - } else { /* Stop Carrier Suppression. */ - if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) { - /*normal mode*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); - /*turn on scramble setting*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, - bEnable); - /*BB Reset*/ - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); - } - } -} - -static void SetCCKContinuousTx(struct _adapter *pAdapter, u8 bStart) -{ - u32 cckrate; - - if (bStart) { - /* 1. if CCK block on? */ - if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) { - /*set CCK block on*/ - set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable); - } - /* Turn Off All Test Mode */ - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable); - /*Set CCK Tx Test Rate*/ - cckrate = pAdapter->mppriv.curr_rateidx; - set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, cckrate); - /*transmit mode*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); - /*turn on scramble setting*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable); - } else { - /*normal mode*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); - /*turn on scramble setting*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable); - /*BB Reset*/ - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); - } -} /* mpt_StartCckContTx */ - -static void SetOFDMContinuousTx(struct _adapter *pAdapter, u8 bStart) -{ - if (bStart) { - /* 1. if OFDM block on? */ - if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn)) { - /*set OFDM block on*/ - set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable); - } - /* 2. set CCK test mode off, set to CCK normal mode*/ - set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, bDisable); - /* 3. turn on scramble setting */ - set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable); - /* 4. Turn On Continue Tx and turn off the other test modes.*/ - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bEnable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable); - } else { - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, - bDisable); - set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable); - msleep(20); - /*BB Reset*/ - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0); - set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1); - } -} /* mpt_StartOfdmContTx */ - -void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart) -{ - /* ADC turn off [bit24-21] adc port0 ~ port1 */ - if (bStart) { - r8712_bb_reg_write(pAdapter, rRx_Wait_CCCA, - r8712_bb_reg_read(pAdapter, - rRx_Wait_CCCA) & 0xFE1FFFFF); - msleep(100); - } - if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) - SetCCKContinuousTx(pAdapter, bStart); - else if ((pAdapter->mppriv.curr_rateidx >= MPT_RATE_6M) && - (pAdapter->mppriv.curr_rateidx <= MPT_RATE_MCS15)) - SetOFDMContinuousTx(pAdapter, bStart); - /* ADC turn on [bit24-21] adc port0 ~ port1 */ - if (!bStart) - r8712_bb_reg_write(pAdapter, rRx_Wait_CCCA, - r8712_bb_reg_read(pAdapter, - rRx_Wait_CCCA) | 0x01E00000); -} - -void r8712_ResetPhyRxPktCount(struct _adapter *pAdapter) -{ - u32 i, phyrx_set = 0; - - for (i = OFDM_PPDU_BIT; i <= HT_MPDU_FAIL_BIT; i++) { - phyrx_set = 0; - phyrx_set |= (i << 28); /*select*/ - phyrx_set |= 0x08000000; /* set counter to zero*/ - r8712_write32(pAdapter, RXERR_RPT, phyrx_set); - } -} - -static u32 GetPhyRxPktCounts(struct _adapter *pAdapter, u32 selbit) -{ - /*selection*/ - u32 phyrx_set = 0; - u32 SelectBit; - - SelectBit = selbit << 28; - phyrx_set |= (SelectBit & 0xF0000000); - r8712_write32(pAdapter, RXERR_RPT, phyrx_set); - /*Read packet count*/ - return r8712_read32(pAdapter, RXERR_RPT) & RPTMaxCount; -} - -u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter) -{ - u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_OK_BIT); - u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_OK_BIT); - u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_OK_BIT); - - return OFDM_cnt + CCK_cnt + HT_cnt; -} - -u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter) -{ - u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_FAIL_BIT); - u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_FAIL_BIT); - u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_FAIL_BIT); - - return OFDM_cnt + CCK_cnt + HT_cnt; -} diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h deleted file mode 100644 index 0a60b1e6ccafc5a92b34fa8f19241e950e82c17d..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mp.h +++ /dev/null @@ -1,275 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_MP_H_ -#define __RTL871X_MP_H_ - -#define MPT_NOOP 0 -#define MPT_READ_MAC_1BYTE 1 -#define MPT_READ_MAC_2BYTE 2 -#define MPT_READ_MAC_4BYTE 3 -#define MPT_WRITE_MAC_1BYTE 4 -#define MPT_WRITE_MAC_2BYTE 5 -#define MPT_WRITE_MAC_4BYTE 6 -#define MPT_READ_BB_CCK 7 -#define MPT_WRITE_BB_CCK 8 -#define MPT_READ_BB_OFDM 9 -#define MPT_WRITE_BB_OFDM 10 -#define MPT_READ_RF 11 -#define MPT_WRITE_RF 12 -#define MPT_READ_EEPROM_1BYTE 13 -#define MPT_WRITE_EEPROM_1BYTE 14 -#define MPT_READ_EEPROM_2BYTE 15 -#define MPT_WRITE_EEPROM_2BYTE 16 -#define MPT_SET_CSTHRESHOLD 21 -#define MPT_SET_INITGAIN 22 -#define MPT_SWITCH_BAND 23 -#define MPT_SWITCH_CHANNEL 24 -#define MPT_SET_DATARATE 25 -#define MPT_SWITCH_ANTENNA 26 -#define MPT_SET_TX_POWER 27 -#define MPT_SET_CONT_TX 28 -#define MPT_SET_SINGLE_CARRIER 29 -#define MPT_SET_CARRIER_SUPPRESSION 30 -#define MPT_GET_RATE_TABLE 31 -#define MPT_READ_TSSI 32 -#define MPT_GET_THERMAL_METER 33 -#define MAX_MP_XMITBUF_SZ 2048 -#define NR_MP_XMITFRAME 8 - -struct mp_xmit_frame { - struct list_head list; - struct pkt_attrib attrib; - _pkt *pkt; - int frame_tag; - struct _adapter *padapter; - u8 *mem_addr; - u16 sz[8]; - struct urb *pxmit_urb[8]; - u8 bpending[8]; - u8 last[8]; -}; - -struct mp_wiparam { - u32 bcompleted; - u32 act_type; - u32 io_offset; - u32 io_value; -}; - -struct mp_priv { - struct _adapter *papdater; - /*OID cmd handler*/ - struct mp_wiparam workparam; - u8 act_in_progress; - /*Tx Section*/ - u8 TID; - u32 tx_pktcount; - /*Rx Section*/ - u32 rx_pktcount; - u32 rx_crcerrpktcount; - u32 rx_pktloss; - struct recv_stat rxstat; - /*RF/BB relative*/ - u32 curr_ch; - u32 curr_rateidx; - u8 curr_bandwidth; - u8 curr_modem; - u8 curr_txpoweridx; - u32 curr_crystalcap; - u16 antenna_tx; - u16 antenna_rx; - u8 curr_rfpath; - u8 check_mp_pkt; - uint ForcedDataRate; - struct wlan_network mp_network; - unsigned char network_macaddr[6]; - /*Testing Flag*/ - u32 mode;/*0 for normal type packet, - * 1 for loopback packet (16bytes TXCMD) - */ - sint prev_fw_state; - u8 *pallocated_mp_xmitframe_buf; - u8 *pmp_xmtframe_buf; - struct __queue free_mp_xmitqueue; - u32 free_mp_xmitframe_cnt; -}; - -struct IOCMD_STRUCT { - u8 cmdclass; - u16 value; - u8 index; -}; - -struct rf_reg_param { - u32 path; - u32 offset; - u32 value; -}; - -struct bb_reg_param { - u32 offset; - u32 value; -}; - -/* ======================================================================= */ - -#define LOWER true -#define RAISE false -#define IOCMD_CTRL_REG 0x10250370 -#define IOCMD_DATA_REG 0x10250374 -#define IOCMD_GET_THERMAL_METER 0xFD000028 -#define IOCMD_CLASS_BB_RF 0xF0 -#define IOCMD_BB_READ_IDX 0x00 -#define IOCMD_BB_WRITE_IDX 0x01 -#define IOCMD_RF_READ_IDX 0x02 -#define IOCMD_RF_WRIT_IDX 0x03 -#define BB_REG_BASE_ADDR 0x800 -#define RF_PATH_A 0 -#define RF_PATH_B 1 -#define RF_PATH_C 2 -#define RF_PATH_D 3 -#define MAX_RF_PATH_NUMS 2 -#define _2MAC_MODE_ 0 -#define _LOOPBOOK_MODE_ 1 - -/* MP set force data rate base on the definition. */ -enum { - /* CCK rate. */ - MPT_RATE_1M, /* 0 */ - MPT_RATE_2M, - MPT_RATE_55M, - MPT_RATE_11M, /* 3 */ - - /* OFDM rate. */ - MPT_RATE_6M, /* 4 */ - MPT_RATE_9M, - MPT_RATE_12M, - MPT_RATE_18M, - MPT_RATE_24M, - MPT_RATE_36M, - MPT_RATE_48M, - MPT_RATE_54M, /* 11 */ - - /* HT rate. */ - MPT_RATE_MCS0, /* 12 */ - MPT_RATE_MCS1, - MPT_RATE_MCS2, - MPT_RATE_MCS3, - MPT_RATE_MCS4, - MPT_RATE_MCS5, - MPT_RATE_MCS6, - MPT_RATE_MCS7, /* 19 */ - MPT_RATE_MCS8, - MPT_RATE_MCS9, - MPT_RATE_MCS10, - MPT_RATE_MCS11, - MPT_RATE_MCS12, - MPT_RATE_MCS13, - MPT_RATE_MCS14, - MPT_RATE_MCS15, /* 27 */ - MPT_RATE_LAST -}; - -/* Represent Channel Width in HT Capabilities */ -enum HT_CHANNEL_WIDTH { - HT_CHANNEL_WIDTH_20 = 0, - HT_CHANNEL_WIDTH_40 = 1, -}; - -#define MAX_TX_PWR_INDEX_N_MODE 64 /* 0x3F */ - -enum POWER_MODE { - POWER_LOW = 0, - POWER_NORMAL -}; - -#define RX_PKT_BROADCAST 1 -#define RX_PKT_DEST_ADDR 2 -#define RX_PKT_PHY_MATCH 3 - -#define RPTMaxCount 0x000FFFFF - -/* parameter 1 : BitMask - * bit 0 : OFDM PPDU - * bit 1 : OFDM False Alarm - * bit 2 : OFDM MPDU OK - * bit 3 : OFDM MPDU Fail - * bit 4 : CCK PPDU - * bit 5 : CCK False Alarm - * bit 6 : CCK MPDU ok - * bit 7 : CCK MPDU fail - * bit 8 : HT PPDU counter - * bit 9 : HT false alarm - * bit 10 : HT MPDU total - * bit 11 : HT MPDU OK - * bit 12 : HT MPDU fail - * bit 15 : RX full drop - */ -enum RXPHY_BITMASK { - OFDM_PPDU_BIT = 0, - OFDM_MPDU_OK_BIT, - OFDM_MPDU_FAIL_BIT, - CCK_PPDU_BIT, - CCK_MPDU_OK_BIT, - CCK_MPDU_FAIL_BIT, - HT_PPDU_BIT, - HT_MPDU_BIT, - HT_MPDU_OK_BIT, - HT_MPDU_FAIL_BIT, -}; - -enum ENCRY_CTRL_STATE { - HW_CONTROL, /*hw encryption& decryption*/ - SW_CONTROL, /*sw encryption& decryption*/ - HW_ENCRY_SW_DECRY, /*hw encryption & sw decryption*/ - SW_ENCRY_HW_DECRY /*sw encryption & hw decryption*/ -}; - -/* Bandwidth Offset */ -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 -/*=======================================================================*/ -void mp871xinit(struct _adapter *padapter); -void mp871xdeinit(struct _adapter *padapter); -u32 r8712_bb_reg_read(struct _adapter *Adapter, u16 offset); -u8 r8712_bb_reg_write(struct _adapter *Adapter, u16 offset, u32 value); -u32 r8712_rf_reg_read(struct _adapter *Adapter, u8 path, u8 offset); -u8 r8712_rf_reg_write(struct _adapter *Adapter, u8 path, - u8 offset, u32 value); -u32 r8712_get_bb_reg(struct _adapter *Adapter, u16 offset, u32 bitmask); -u8 r8712_set_bb_reg(struct _adapter *Adapter, u16 offset, - u32 bitmask, u32 value); -u32 r8712_get_rf_reg(struct _adapter *Adapter, u8 path, u8 offset, - u32 bitmask); -u8 r8712_set_rf_reg(struct _adapter *Adapter, u8 path, u8 offset, - u32 bitmask, u32 value); - -void r8712_SetChannel(struct _adapter *pAdapter); -void r8712_SetTxPower(struct _adapter *pAdapte); -void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset); -void r8712_SetDataRate(struct _adapter *pAdapter); -void r8712_SwitchBandwidth(struct _adapter *pAdapter); -void r8712_SwitchAntenna(struct _adapter *pAdapter); -void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value); -void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart); -void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart); -void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart); -void r8712_SetCarrierSuppressionTx(struct _adapter *pAdapter, u8 bStart); -void r8712_ResetPhyRxPktCount(struct _adapter *pAdapter); -u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter); -u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter); - -#endif /*__RTL871X_MP_H_*/ - diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c deleted file mode 100644 index 26fa09b45c908090c8d43504a58bfb1f51efedbb..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c +++ /dev/null @@ -1,883 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_mp_ioctl.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#include <linux/rndis.h> -#include "osdep_service.h" -#include "drv_types.h" -#include "mlme_osdep.h" -#include "rtl871x_mp.h" -#include "rtl871x_mp_ioctl.h" - -uint oid_null_function(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv) -{ - uint status = RNDIS_STATUS_SUCCESS; - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid == SET_OID) { - if (poid_par_priv->information_buf_len >= sizeof(u8)) - Adapter->registrypriv.wireless_mode = - *(u8 *)poid_par_priv->information_buf; - else - status = RNDIS_STATUS_INVALID_LENGTH; - } else if (poid_par_priv->type_of_oid == QUERY_OID) { - if (poid_par_priv->information_buf_len >= sizeof(u8)) { - *(u8 *)poid_par_priv->information_buf = - Adapter->registrypriv.wireless_mode; - *poid_par_priv->bytes_rw = - poid_par_priv->information_buf_len; - } else { - status = RNDIS_STATUS_INVALID_LENGTH; - } - } else { - status = RNDIS_STATUS_NOT_ACCEPTED; - } - return status; -} - -uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct bb_reg_param *pbbreg; - u16 offset; - u32 value; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param)) - return RNDIS_STATUS_INVALID_LENGTH; - pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf); - offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/ - if (offset < BB_REG_BASE_ADDR) - offset |= BB_REG_BASE_ADDR; - value = pbbreg->value; - r8712_bb_reg_write(Adapter, offset, value); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct bb_reg_param *pbbreg; - u16 offset; - u32 value; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param)) - return RNDIS_STATUS_INVALID_LENGTH; - pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf); - offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/ - if (offset < BB_REG_BASE_ADDR) - offset |= BB_REG_BASE_ADDR; - value = r8712_bb_reg_read(Adapter, offset); - pbbreg->value = value; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct rf_reg_param *pbbreg; - u8 path; - u8 offset; - u32 value; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param)) - return RNDIS_STATUS_INVALID_LENGTH; - pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf); - path = (u8)pbbreg->path; - if (path > RF_PATH_B) - return RNDIS_STATUS_NOT_ACCEPTED; - offset = (u8)pbbreg->offset; - value = pbbreg->value; - r8712_rf_reg_write(Adapter, path, offset, value); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct rf_reg_param *pbbreg; - u8 path; - u8 offset; - u32 value; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param)) - return RNDIS_STATUS_INVALID_LENGTH; - pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf); - path = (u8)pbbreg->path; - if (path > RF_PATH_B) /* 1T2R path_a /path_b */ - return RNDIS_STATUS_NOT_ACCEPTED; - offset = (u8)pbbreg->offset; - value = r8712_rf_reg_read(Adapter, path, offset); - pbbreg->value = value; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -/*This function initializes the DUT to the MP test mode*/ -static int mp_start_test(struct _adapter *padapter) -{ - struct mp_priv *pmppriv = &padapter->mppriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct wlan_bssid_ex *bssid; - struct sta_info *psta; - unsigned long length; - unsigned long irqL; - int res = 0; - - bssid = kzalloc(sizeof(*bssid), GFP_KERNEL); - if (!bssid) - return -ENOMEM; - - /* 3 1. initialize a new struct wlan_bssid_ex */ - memcpy(bssid->MacAddress, pmppriv->network_macaddr, ETH_ALEN); - bssid->Ssid.SsidLength = 16; - memcpy(bssid->Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc", - bssid->Ssid.SsidLength); - bssid->InfrastructureMode = Ndis802_11IBSS; - bssid->NetworkTypeInUse = Ndis802_11DS; - bssid->IELength = 0; - length = r8712_get_wlan_bssid_ex_sz(bssid); - if (length % 4) { - /*round up to multiple of 4 bytes.*/ - bssid->Length = ((length >> 2) + 1) << 2; - } else { - bssid->Length = length; - } - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) - goto end_of_mp_start_test; - /*init mp_start_test status*/ - pmppriv->prev_fw_state = get_fwstate(pmlmepriv); - pmlmepriv->fw_state = WIFI_MP_STATE; - if (pmppriv->mode == _LOOPBOOK_MODE_) - set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/ - set_fwstate(pmlmepriv, _FW_UNDER_LINKING); - /* 3 2. create a new psta for mp driver */ - /* clear psta in the cur_network, if any */ - psta = r8712_get_stainfo(&padapter->stapriv, - tgt_network->network.MacAddress); - if (psta) - r8712_free_stainfo(padapter, psta); - psta = r8712_alloc_stainfo(&padapter->stapriv, bssid->MacAddress); - if (!psta) { - res = -ENOMEM; - goto end_of_mp_start_test; - } - /* 3 3. join pseudo AdHoc */ - tgt_network->join_res = 1; - tgt_network->aid = psta->aid = 1; - memcpy(&tgt_network->network, bssid, length); - _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING); - r8712_os_indicate_connect(padapter); - /* Set to LINKED STATE for MP TRX Testing */ - set_fwstate(pmlmepriv, _FW_LINKED); -end_of_mp_start_test: - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - kfree(bssid); - return res; -} - -/*This function change the DUT from the MP test mode into normal mode */ -static int mp_stop_test(struct _adapter *padapter) -{ - struct mp_priv *pmppriv = &padapter->mppriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wlan_network *tgt_network = &pmlmepriv->cur_network; - struct sta_info *psta; - unsigned long irqL; - - spin_lock_irqsave(&pmlmepriv->lock, irqL); - if (!check_fwstate(pmlmepriv, WIFI_MP_STATE)) - goto end_of_mp_stop_test; - /* 3 1. disconnect pseudo AdHoc */ - r8712_os_indicate_disconnect(padapter); - /* 3 2. clear psta used in mp test mode. */ - psta = r8712_get_stainfo(&padapter->stapriv, - tgt_network->network.MacAddress); - if (psta) - r8712_free_stainfo(padapter, psta); - /* 3 3. return to normal state (default:station mode) */ - pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE;*/ - /*flush the cur_network*/ - memset(tgt_network, 0, sizeof(struct wlan_network)); -end_of_mp_stop_test: - spin_unlock_irqrestore(&pmlmepriv->lock, irqL); - return _SUCCESS; -} - -uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 ratevalue; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len != sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - ratevalue = *((u32 *)poid_par_priv->information_buf); - if (ratevalue >= MPT_RATE_LAST) - return RNDIS_STATUS_INVALID_DATA; - Adapter->mppriv.curr_rateidx = ratevalue; - r8712_SetDataRate(Adapter); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - u32 mode; - u8 val8; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - mode = *((u32 *)poid_par_priv->information_buf); - Adapter->mppriv.mode = mode;/* 1 for loopback*/ - if (mp_start_test(Adapter)) - status = RNDIS_STATUS_NOT_ACCEPTED; - r8712_write8(Adapter, MSR, 1); /* Link in ad hoc network, 0x1025004C */ - r8712_write8(Adapter, RCR, 0); /* RCR : disable all pkt, 0x10250048 */ - /* RCR disable Check BSSID, 0x1025004a */ - r8712_write8(Adapter, RCR + 2, 0x57); - /* disable RX filter map , mgt frames will put in RX FIFO 0 */ - r8712_write16(Adapter, RXFLTMAP0, 0x0); - val8 = r8712_read8(Adapter, EE_9346CR); - if (!(val8 & _9356SEL)) { /*boot from EFUSE*/ - r8712_efuse_reg_init(Adapter); - r8712_efuse_change_max_size(Adapter); - r8712_efuse_reg_uninit(Adapter); - } - return status; -} - -uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (mp_stop_test(Adapter) == _FAIL) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 Channel; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len != sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - Channel = *((u32 *)poid_par_priv->information_buf); - if (Channel > 14) - return RNDIS_STATUS_NOT_ACCEPTED; - Adapter->mppriv.curr_ch = Channel; - r8712_SetChannel(Adapter); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 antenna; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len != sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - antenna = *((u32 *)poid_par_priv->information_buf); - Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16); - Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF); - r8712_SwitchAntenna(Adapter); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 tx_pwr_idx; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len != sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - tx_pwr_idx = *((u32 *)poid_par_priv->information_buf); - if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE) - return RNDIS_STATUS_NOT_ACCEPTED; - Adapter->mppriv.curr_txpoweridx = (u8)tx_pwr_idx; - r8712_SetTxPower(Adapter); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (poid_par_priv->information_buf_len == sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - Adapter->mppriv.tx_pktcount; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (poid_par_priv->information_buf_len == sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - Adapter->mppriv.rx_pktcount; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (poid_par_priv->information_buf_len == sizeof(u32)) { - *(u32 *)poid_par_priv->information_buf = - Adapter->mppriv.rx_crcerrpktcount; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - Adapter->mppriv.tx_pktcount = 0; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len == sizeof(u32)) { - Adapter->mppriv.rx_pktcount = 0; - Adapter->mppriv.rx_crcerrpktcount = 0; - } else { - return RNDIS_STATUS_INVALID_LENGTH; - } - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - r8712_ResetPhyRxPktCount(Adapter); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len != sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - *(u32 *)poid_par_priv->information_buf = - r8712_GetPhyRxPktReceived(Adapter); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len != sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - *(u32 *)poid_par_priv->information_buf = - r8712_GetPhyRxPktCRC32Error(Adapter); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - Adapter->mppriv.curr_modem = *((u8 *)poid_par_priv->information_buf); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 bStartTest; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - bStartTest = *((u32 *)poid_par_priv->information_buf); - r8712_SetContinuousTx(Adapter, (u8)bStartTest); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 bStartTest; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - bStartTest = *((u32 *)poid_par_priv->information_buf); - r8712_SetSingleCarrierTx(Adapter, (u8)bStartTest); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 bStartTest; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - bStartTest = *((u32 *)poid_par_priv->information_buf); - r8712_SetCarrierSuppressionTx(Adapter, (u8)bStartTest); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 bStartTest; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - bStartTest = *((u32 *)poid_par_priv->information_buf); - r8712_SetSingleToneTx(Adapter, (u8)bStartTest); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct mp_rw_reg *RegRWStruct; - u16 offset; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf; - if ((RegRWStruct->offset >= 0x10250800) && - (RegRWStruct->offset <= 0x10250FFF)) { - /*baseband register*/ - /*0ffset :0x800~0xfff*/ - offset = (u16)(RegRWStruct->offset) & 0xFFF; - RegRWStruct->value = r8712_bb_reg_read(Adapter, offset); - } else { - switch (RegRWStruct->width) { - case 1: - RegRWStruct->value = r8712_read8(Adapter, - RegRWStruct->offset); - break; - case 2: - RegRWStruct->value = r8712_read16(Adapter, - RegRWStruct->offset); - break; - case 4: - RegRWStruct->value = r8712_read32(Adapter, - RegRWStruct->offset); - break; - default: - status = RNDIS_STATUS_NOT_ACCEPTED; - break; - } - } - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return status; -} - -uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct mp_rw_reg *RegRWStruct; - u16 offset; - u32 value; - u32 oldValue = 0; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf; - if ((RegRWStruct->offset >= 0x10250800) && - (RegRWStruct->offset <= 0x10250FFF)) { - /*baseband register*/ - offset = (u16)(RegRWStruct->offset) & 0xFFF; - value = RegRWStruct->value; - switch (RegRWStruct->width) { - case 1: - oldValue = r8712_bb_reg_read(Adapter, offset); - oldValue &= 0xFFFFFF00; - value &= 0x000000FF; - value |= oldValue; - break; - case 2: - oldValue = r8712_bb_reg_read(Adapter, offset); - oldValue &= 0xFFFF0000; - value &= 0x0000FFFF; - value |= oldValue; - break; - } - r8712_bb_reg_write(Adapter, offset, value); - } else { - switch (RegRWStruct->width) { - case 1: - r8712_write8(Adapter, RegRWStruct->offset, - (unsigned char)RegRWStruct->value); - break; - case 2: - r8712_write16(Adapter, RegRWStruct->offset, - (unsigned short)RegRWStruct->value); - break; - case 4: - r8712_write32(Adapter, RegRWStruct->offset, - (unsigned int)RegRWStruct->value); - break; - default: - status = RNDIS_STATUS_NOT_ACCEPTED; - break; - } - } - return status; -} - -uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (Adapter->mppriv.act_in_progress) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (poid_par_priv->information_buf_len < sizeof(u8)) - return RNDIS_STATUS_INVALID_LENGTH; - /*init workparam*/ - Adapter->mppriv.act_in_progress = true; - Adapter->mppriv.workparam.bcompleted = false; - Adapter->mppriv.workparam.act_type = MPT_GET_THERMAL_METER; - Adapter->mppriv.workparam.io_offset = 0; - Adapter->mppriv.workparam.io_value = 0xFFFFFFFF; - r8712_GetThermalMeter(Adapter, &Adapter->mppriv.workparam.io_value); - Adapter->mppriv.workparam.bcompleted = true; - Adapter->mppriv.act_in_progress = false; - *(u32 *)poid_par_priv->information_buf = - Adapter->mppriv.workparam.io_value; - *poid_par_priv->bytes_rw = sizeof(u32); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - uint status = RNDIS_STATUS_SUCCESS; - - struct EFUSE_ACCESS_STRUCT *pefuse; - u8 *data; - u16 addr = 0, cnts = 0; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < - sizeof(struct EFUSE_ACCESS_STRUCT)) - return RNDIS_STATUS_INVALID_LENGTH; - pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf; - addr = pefuse->start_addr; - cnts = pefuse->cnts; - data = pefuse->data; - memset(data, 0xFF, cnts); - if ((addr > 511) || (cnts < 1) || (cnts > 512) || (addr + cnts) > - EFUSE_MAX_SIZE) - return RNDIS_STATUS_NOT_ACCEPTED; - if (!r8712_efuse_access(Adapter, true, addr, cnts, data)) - status = RNDIS_STATUS_FAILURE; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return status; -} - -/*------------------------------------------------------------------------*/ -uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - uint status = RNDIS_STATUS_SUCCESS; - - struct EFUSE_ACCESS_STRUCT *pefuse; - u8 *data; - u16 addr = 0, cnts = 0; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf; - addr = pefuse->start_addr; - cnts = pefuse->cnts; - data = pefuse->data; - - if ((addr > 511) || (cnts < 1) || (cnts > 512) || - (addr + cnts) > r8712_efuse_get_max_size(Adapter)) - return RNDIS_STATUS_NOT_ACCEPTED; - if (!r8712_efuse_access(Adapter, false, addr, cnts, data)) - status = RNDIS_STATUS_FAILURE; - return status; -} - -/*----------------------------------------------------------------------*/ - -uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(int)) - return RNDIS_STATUS_INVALID_LENGTH; - r8712_efuse_reg_init(Adapter); - *(int *)poid_par_priv->information_buf = - r8712_efuse_get_current_size(Adapter); - r8712_efuse_reg_uninit(Adapter); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - *(int *)poid_par_priv->information_buf = - r8712_efuse_get_max_size(Adapter); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv) -{ - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid == QUERY_OID) - status = oid_rt_pro_read_efuse_hdl(poid_par_priv); - else - status = oid_rt_pro_write_efuse_hdl(poid_par_priv); - return status; -} - -uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - u8 *data; - - *poid_par_priv->bytes_rw = 0; - if (poid_par_priv->information_buf_len < EFUSE_MAP_MAX_SIZE) - return RNDIS_STATUS_INVALID_LENGTH; - data = (u8 *)poid_par_priv->information_buf; - if (poid_par_priv->type_of_oid == QUERY_OID) { - if (r8712_efuse_map_read(Adapter, 0, EFUSE_MAP_MAX_SIZE, data)) - *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE; - else - status = RNDIS_STATUS_FAILURE; - } else { - /* SET_OID */ - if (r8712_efuse_reg_init(Adapter)) { - if (r8712_efuse_map_write(Adapter, 0, - EFUSE_MAP_MAX_SIZE, data)) - *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE; - else - status = RNDIS_STATUS_FAILURE; - r8712_efuse_reg_uninit(Adapter); - } else { - status = RNDIS_STATUS_FAILURE; - } - } - return status; -} - -uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 bandwidth; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - bandwidth = *((u32 *)poid_par_priv->information_buf);/*4*/ - if (bandwidth != HT_CHANNEL_WIDTH_20) - bandwidth = HT_CHANNEL_WIDTH_40; - Adapter->mppriv.curr_bandwidth = (u8)bandwidth; - r8712_SwitchBandwidth(Adapter); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u8 rx_pkt_type; - u32 rcr_val32; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u8)) - return RNDIS_STATUS_INVALID_LENGTH; - rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/*4*/ - rcr_val32 = r8712_read32(Adapter, RCR);/*RCR = 0x10250048*/ - rcr_val32 &= ~(RCR_CBSSID | RCR_AB | RCR_AM | RCR_APM | RCR_AAP); - switch (rx_pkt_type) { - case RX_PKT_BROADCAST: - rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32); - break; - case RX_PKT_DEST_ADDR: - rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32); - break; - case RX_PKT_PHY_MATCH: - rcr_val32 |= (RCR_APM | RCR_ACRC32); - break; - default: - rcr_val32 &= ~(RCR_AAP | - RCR_APM | - RCR_AM | - RCR_AB | - RCR_ACRC32); - break; - } - if (rx_pkt_type == RX_PKT_DEST_ADDR) - Adapter->mppriv.check_mp_pkt = 1; - else - Adapter->mppriv.check_mp_pkt = 0; - r8712_write32(Adapter, RCR, rcr_val32); - return RNDIS_STATUS_SUCCESS; -} - -/*--------------------------------------------------------------------------*/ -/*Linux*/ -unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv) -{ - return _SUCCESS; -} - -/*-------------------------------------------------------------------------*/ -uint oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - /*CALL the power_down function*/ - return RNDIS_STATUS_SUCCESS; -} - -/*-------------------------------------------------------------------------- */ -uint oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - *(int *)poid_par_priv->information_buf = - Adapter->registrypriv.low_power ? POWER_LOW : POWER_NORMAL; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h deleted file mode 100644 index aa4d5ce471f2fa55379cf1421784dec4f6eb0ee2..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h +++ /dev/null @@ -1,328 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871X_MP_IOCTL_H -#define _RTL871X_MP_IOCTL_H - -#include "osdep_service.h" -#include "drv_types.h" -#include "mp_custom_oid.h" -#include "rtl871x_ioctl.h" -#include "rtl871x_ioctl_rtl.h" -#include "rtl8712_efuse.h" - -#define TESTFWCMDNUMBER 1000000 -#define TEST_H2CINT_WAIT_TIME 500 -#define TEST_C2HINT_WAIT_TIME 500 -#define HCI_TEST_SYSCFG_HWMASK 1 -#define _BUSCLK_40M (4 << 2) - -struct CFG_DBG_MSG_STRUCT { - u32 DebugLevel; - u32 DebugComponent_H32; - u32 DebugComponent_L32; -}; - -struct mp_rw_reg { - uint offset; - uint width; - u32 value; -}; - -/* for OID_RT_PRO_READ16_EEPROM & OID_RT_PRO_WRITE16_EEPROM */ -struct eeprom_rw_param { - uint offset; - u16 value; -}; - -struct EFUSE_ACCESS_STRUCT { - u16 start_addr; - u16 cnts; - u8 data[]; -}; - -struct burst_rw_reg { - uint offset; - uint len; - u8 Data[256]; -}; - -struct usb_vendor_req { - u8 bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; - u8 u8Dir;/*0:OUT, 1:IN */ - u8 u8InData; -}; - -struct DR_VARIABLE_STRUCT { - u8 offset; - u32 variable; -}; - -/* oid_rtl_seg_87_11_00 */ -uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_81_80_00 */ -uint oid_rt_pro_set_data_rate_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_channel_direct_call_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_antenna_bb_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_tx_power_control_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_81_80_20 */ -uint oid_rt_pro_query_tx_packet_sent_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_query_rx_packet_received_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_query_rx_packet_crc32_error_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_reset_tx_packet_sent_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_reset_rx_packet_received_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_continuous_tx_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_single_carrier_tx_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_carrier_suppression_tx_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_single_tone_tx_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_81_87 */ -uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_81_85 */ -uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_get_efuse_current_size_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_get_thermal_meter_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_reset_phy_rx_packet_count_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_phy_rx_packet_received_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_phy_rx_packet_crc32_error_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_set_power_down_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_get_power_mode_hdl( - struct oid_par_priv *poid_par_priv); -#ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */ -/* This ifdef _MUST_ be left in!! */ - -#else /* _RTL871X_MP_IOCTL_C_ */ -extern struct oid_obj_priv oid_rtl_seg_81_87[5]; -extern struct oid_obj_priv oid_rtl_seg_87_11_00[32]; -extern struct oid_obj_priv oid_rtl_seg_87_11_20[5]; -extern struct oid_obj_priv oid_rtl_seg_87_11_50[2]; -extern struct oid_obj_priv oid_rtl_seg_87_11_80[1]; -extern struct oid_obj_priv oid_rtl_seg_87_11_B0[1]; -extern struct oid_obj_priv oid_rtl_seg_87_11_F0[16]; -extern struct oid_obj_priv oid_rtl_seg_87_12_00[32]; - -#endif /* _RTL871X_MP_IOCTL_C_ */ - -enum MP_MODE { - MP_START_MODE, - MP_STOP_MODE, - MP_ERR_MODE -}; - -struct rwreg_param { - unsigned int offset; - unsigned int width; - unsigned int value; -}; - -struct bbreg_param { - unsigned int offset; - unsigned int phymask; - unsigned int value; -}; - -struct txpower_param { - unsigned int pwr_index; -}; - -struct datarate_param { - unsigned int rate_index; -}; - -struct rfintfs_parm { - unsigned int rfintfs; -}; - -struct mp_xmit_packet { - unsigned int len; -}; - -struct psmode_param { - unsigned int ps_mode; - unsigned int smart_ps; -}; - -struct mp_ioctl_handler { - unsigned int paramsize; - unsigned int (*handler)(struct oid_par_priv *poid_par_priv); - unsigned int oid; -}; - -struct mp_ioctl_param { - unsigned int subcode; - unsigned int len; - unsigned char data[]; -}; - -#define GEN_MP_IOCTL_SUBCODE(code) _MP_IOCTL_ ## code ## _CMD_ - -enum RTL871X_MP_IOCTL_SUBCODE { - GEN_MP_IOCTL_SUBCODE(MP_START), /*0*/ - GEN_MP_IOCTL_SUBCODE(MP_STOP), /*1*/ - GEN_MP_IOCTL_SUBCODE(READ_REG), /*2*/ - GEN_MP_IOCTL_SUBCODE(WRITE_REG), - GEN_MP_IOCTL_SUBCODE(SET_CHANNEL), /*4*/ - GEN_MP_IOCTL_SUBCODE(SET_TXPOWER), /*5*/ - GEN_MP_IOCTL_SUBCODE(SET_DATARATE), /*6*/ - GEN_MP_IOCTL_SUBCODE(READ_BB_REG), /*7*/ - GEN_MP_IOCTL_SUBCODE(WRITE_BB_REG), - GEN_MP_IOCTL_SUBCODE(READ_RF_REG), /*9*/ - GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG), - GEN_MP_IOCTL_SUBCODE(SET_RF_INTFS), - GEN_MP_IOCTL_SUBCODE(IOCTL_XMIT_PACKET), /*12*/ - GEN_MP_IOCTL_SUBCODE(PS_STATE), /*13*/ - GEN_MP_IOCTL_SUBCODE(READ16_EEPROM), /*14*/ - GEN_MP_IOCTL_SUBCODE(WRITE16_EEPROM), /*15*/ - GEN_MP_IOCTL_SUBCODE(SET_PTM), /*16*/ - GEN_MP_IOCTL_SUBCODE(READ_TSSI), /*17*/ - GEN_MP_IOCTL_SUBCODE(CNTU_TX), /*18*/ - GEN_MP_IOCTL_SUBCODE(SET_BANDWIDTH), /*19*/ - GEN_MP_IOCTL_SUBCODE(SET_RX_PKT_TYPE), /*20*/ - GEN_MP_IOCTL_SUBCODE(RESET_PHY_RX_PKT_CNT), /*21*/ - GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_RECV), /*22*/ - GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_ERROR), /*23*/ - GEN_MP_IOCTL_SUBCODE(SET_POWER_DOWN), /*24*/ - GEN_MP_IOCTL_SUBCODE(GET_THERMAL_METER), /*25*/ - GEN_MP_IOCTL_SUBCODE(GET_POWER_MODE), /*26*/ - GEN_MP_IOCTL_SUBCODE(EFUSE), /*27*/ - GEN_MP_IOCTL_SUBCODE(EFUSE_MAP), /*28*/ - GEN_MP_IOCTL_SUBCODE(GET_EFUSE_MAX_SIZE), /*29*/ - GEN_MP_IOCTL_SUBCODE(GET_EFUSE_CURRENT_SIZE), /*30*/ - GEN_MP_IOCTL_SUBCODE(SC_TX), /*31*/ - GEN_MP_IOCTL_SUBCODE(CS_TX), /*32*/ - GEN_MP_IOCTL_SUBCODE(ST_TX), /*33*/ - GEN_MP_IOCTL_SUBCODE(SET_ANTENNA), /*34*/ - MAX_MP_IOCTL_SUBCODE, -}; - -unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv); - -#ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */ -/* This ifdef _MUST_ be left in!! */ - -static struct mp_ioctl_handler mp_ioctl_hdl[] = { - {sizeof(u32), oid_rt_pro_start_test_hdl, - OID_RT_PRO_START_TEST},/*0*/ - {sizeof(u32), oid_rt_pro_stop_test_hdl, - OID_RT_PRO_STOP_TEST},/*1*/ - {sizeof(struct rwreg_param), - oid_rt_pro_read_register_hdl, - OID_RT_PRO_READ_REGISTER},/*2*/ - {sizeof(struct rwreg_param), - oid_rt_pro_write_register_hdl, - OID_RT_PRO_WRITE_REGISTER}, - {sizeof(u32), - oid_rt_pro_set_channel_direct_call_hdl, - OID_RT_PRO_SET_CHANNEL_DIRECT_CALL}, - {sizeof(struct txpower_param), - oid_rt_pro_set_tx_power_control_hdl, - OID_RT_PRO_SET_TX_POWER_CONTROL}, - {sizeof(u32), - oid_rt_pro_set_data_rate_hdl, - OID_RT_PRO_SET_DATA_RATE}, - {sizeof(struct bb_reg_param), - oid_rt_pro_read_bb_reg_hdl, - OID_RT_PRO_READ_BB_REG},/*7*/ - {sizeof(struct bb_reg_param), - oid_rt_pro_write_bb_reg_hdl, - OID_RT_PRO_WRITE_BB_REG}, - {sizeof(struct rwreg_param), - oid_rt_pro_read_rf_reg_hdl, - OID_RT_PRO_RF_READ_REGISTRY},/*9*/ - {sizeof(struct rwreg_param), - oid_rt_pro_write_rf_reg_hdl, - OID_RT_PRO_RF_WRITE_REGISTRY}, - {sizeof(struct rfintfs_parm), NULL, 0}, - {0, mp_ioctl_xmit_packet_hdl, 0},/*12*/ - {sizeof(struct psmode_param), NULL, 0},/*13*/ - {sizeof(struct eeprom_rw_param), NULL, 0},/*14*/ - {sizeof(struct eeprom_rw_param), NULL, 0},/*15*/ - {sizeof(unsigned char), NULL, 0},/*16*/ - {sizeof(u32), NULL, 0},/*17*/ - {sizeof(u32), oid_rt_pro_set_continuous_tx_hdl, - OID_RT_PRO_SET_CONTINUOUS_TX},/*18*/ - {sizeof(u32), oid_rt_set_bandwidth_hdl, - OID_RT_SET_BANDWIDTH},/*19*/ - {sizeof(u32), oid_rt_set_rx_packet_type_hdl, - OID_RT_SET_RX_PACKET_TYPE},/*20*/ - {0, oid_rt_reset_phy_rx_packet_count_hdl, - OID_RT_RESET_PHY_RX_PACKET_COUNT},/*21*/ - {sizeof(u32), oid_rt_get_phy_rx_packet_received_hdl, - OID_RT_GET_PHY_RX_PACKET_RECEIVED},/*22*/ - {sizeof(u32), oid_rt_get_phy_rx_packet_crc32_error_hdl, - OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR},/*23*/ - {sizeof(unsigned char), oid_rt_set_power_down_hdl, - OID_RT_SET_POWER_DOWN},/*24*/ - {sizeof(u32), oid_rt_get_thermal_meter_hdl, - OID_RT_PRO_GET_THERMAL_METER},/*25*/ - {sizeof(u32), oid_rt_get_power_mode_hdl, - OID_RT_GET_POWER_MODE},/*26*/ - {sizeof(struct EFUSE_ACCESS_STRUCT), - oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE},/*27*/ - {EFUSE_MAP_MAX_SIZE, oid_rt_pro_efuse_map_hdl, - OID_RT_PRO_EFUSE_MAP},/*28*/ - {sizeof(u32), oid_rt_get_efuse_max_size_hdl, - OID_RT_GET_EFUSE_MAX_SIZE},/*29*/ - {sizeof(u32), oid_rt_get_efuse_current_size_hdl, - OID_RT_GET_EFUSE_CURRENT_SIZE},/*30*/ - {sizeof(u32), oid_rt_pro_set_single_carrier_tx_hdl, - OID_RT_PRO_SET_SINGLE_CARRIER_TX},/*31*/ - {sizeof(u32), oid_rt_pro_set_carrier_suppression_tx_hdl, - OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX},/*32*/ - {sizeof(u32), oid_rt_pro_set_single_tone_tx_hdl, - OID_RT_PRO_SET_SINGLE_TONE_TX},/*33*/ - {sizeof(u32), oid_rt_pro_set_antenna_bb_hdl, - OID_RT_PRO_SET_ANTENNA_BB},/*34*/ -}; - -#else /* _RTL871X_MP_IOCTL_C_ */ -extern struct mp_ioctl_handler mp_ioctl_hdl[]; -#endif /* _RTL871X_MP_IOCTL_C_ */ - -#endif - diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h deleted file mode 100644 index bb9f83d58225dc3727121c690224dfe9308cd0f5..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h +++ /dev/null @@ -1,1034 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/***************************************************************************** - * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved. - * - * Module: __INC_HAL8192SPHYREG_H - * - * - * Note: 1. Define PMAC/BB register map - * 2. Define RF register map - * 3. PMAC/BB register bit mask. - * 4. RF reg bit mask. - * 5. Other BB/RF relative definition. - * - * - * Export: Constants, macro, functions(API), global variables(None). - * - * Abbrev: - * - * History: - * Data Who Remark - * 08/07/2007 MHC 1. Porting from 9x series PHYCFG.h. - * 2. Reorganize code architecture. - * 09/25/2008 MH 1. Add RL6052 register definition - * - *****************************************************************************/ -#ifndef __RTL871X_MP_PHY_REGDEF_H -#define __RTL871X_MP_PHY_REGDEF_H - -/*--------------------------Define Parameters-------------------------------*/ - -/*============================================================ - * 8192S Register offset definition - *============================================================ - * - * - * BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF - * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF - * 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 - * 3. RF register 0x00-2E - * 4. Bit Mask for BB/RF register - * 5. Other definition for BB/RF R/W - * - * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF - * 1. Page1(0x100) - */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* - * 2. Page2(0x200) - * - * The following two definition are only used for USB interface. - *#define RF_BB_CMD_ADDR 0x02c0 // RF/BB read/write command address. - *#define RF_BB_CMD_DATA 0x02c4 // RF/BB read/write command data. - * - * - * 3. Page8(0x800) - */ -#define rFPGA0_RFMOD 0x800 /*RF mode & CCK TxSC RF - * BW Setting?? - */ -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 -#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 -#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ -#define rFPGA0_XA_HSSIParameter2 0x824 -#define rFPGA0_XB_HSSIParameter1 0x828 -#define rFPGA0_XB_HSSIParameter2 0x82c -#define rFPGA0_XC_HSSIParameter1 0x830 -#define rFPGA0_XC_HSSIParameter2 0x834 -#define rFPGA0_XD_HSSIParameter1 0x838 -#define rFPGA0_XD_HSSIParameter2 0x83c -#define rFPGA0_XA_LSSIParameter 0x840 -#define rFPGA0_XB_LSSIParameter 0x844 -#define rFPGA0_XC_LSSIParameter 0x848 -#define rFPGA0_XD_LSSIParameter 0x84c - -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - -#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ -#define rFPGA0_XCD_SwitchControl 0x85c - -#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */ -#define rFPGA0_XB_RFInterfaceOE 0x864 -#define rFPGA0_XC_RFInterfaceOE 0x868 -#define rFPGA0_XD_RFInterfaceOE 0x86c -#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Ctrl */ -#define rFPGA0_XCD_RFInterfaceSW 0x874 - -#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting - * RF-R/W protection - * for parameter4?? - */ -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 /* Useless now */ -#define rFPGA0_AnalogParameter4 0x88c - -#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Transceiver LSSI Readback */ -#define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac - -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ -#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now */ -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ - -/* - * 4. Page9(0x900) - */ -#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC */ - -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now */ - -/* - * 5. PageA(0xA00) - * - * Set Control channel to upper or lower. - * These settings are required only for 40MHz - */ -#define rCCK0_System 0xa00 - -#define rCCK0_AFESetting 0xa04 /* Disable init gain now */ -#define rCCK0_CCA 0xa08 /* Disable init gain now */ - -#define rCCK0_RxAGC1 0xa0c -/* AGC default value, saturation level - * Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. - * Not the same as 90 series - */ -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel - * estimation threshold - */ -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f - * channel report - */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ - -/* - * 6. PageC(0xC00) - */ -#define rOFDM0_LSTF 0xc00 -#define rOFDM0_TRxPathEnable 0xc04 -#define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c - -/*RxIQ DC offset, Rx digital filter, DC notch filter */ -#define rOFDM0_XARxAFE 0xc10 -#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */ -#define rOFDM0_XBRxAFE 0xc18 -#define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune - * init gain - */ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & - * Short-GI - */ - -#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ -#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ - -#define rOFDM0_XAAGCCore1 0xc50 /* DIG */ -#define rOFDM0_XAAGCCore2 0xc54 -#define rOFDM0_XBAGCCore1 0xc58 -#define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 -#define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c - -#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ -#define rOFDM0_XATxAFE 0xc84 -#define rOFDM0_XBTxIQImbalance 0xc88 -#define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 -#define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 -#define rOFDM0_XDTxAFE 0xc9c - -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 - -/* - * 7. PageD(0xD00) - */ -#define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - -/* - * 8. PageE(0xE00) - */ -#define rTxAGC_Rate18_06 0xe00 -#define rTxAGC_Rate54_24 0xe04 -#define rTxAGC_CCK_Mcs32 0xe08 -#define rTxAGC_Mcs03_Mcs00 0xe10 -#define rTxAGC_Mcs07_Mcs04 0xe14 -#define rTxAGC_Mcs11_Mcs08 0xe18 -#define rTxAGC_Mcs15_Mcs12 0xe1c - -/* Analog- control in RX_WAIT_CCA : REG: EE0 - * [Analog- Power & Control Register] - */ -#define rRx_Wait_CCCA 0xe70 -#define rAnapar_Ctrl_BB 0xee0 - -/* - * 7. RF Register 0x00-0x2E (RF 8256) - * RF-0222D 0x00-3F - * - * Zebra1 - */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - -/* RL6052 Register definition */ -#define RF_AC 0x00 -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define rRfChannel 0x18 /* RF channel and BW switch */ -#define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x24 - -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ - -#define RF_RCK_OS 0x30 /* RF TX PA control */ - -#define RF_TXPA_G1 0x31 /* RF TX PA control */ -#define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ - -/* - * Bit Mask - * - * 1. Page1(0x100) - */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 -#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && \ - (_Offset <= 0xfff)) - -/* 2. Page8(0x800) */ -#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 -#define bCCKEn 0x1000000 -#define bOFDMEn 0x2000000 - -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* change gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 -#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParm1 */ -#define b3WireAddressLength 0x400 -#define b3WireRFPowerDown 0x1 /* Useless now */ -#define b5GPAPEPolarity 0x40000000 -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf -#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#define bRFSI_ANTSW 0x100 -#define bRFSI_ANTSWB 0x200 -#define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 -#define bBandSelect 0x1 -#define bHTSIG2_GI 0x80 -#define bHTSIG2_Smoothing 0x01 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 -#define bLSSIReadAddress 0x7f800000 /* T65 RF */ -#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ -#define bLSSIReadBackData 0xfffff /* T65 RF */ -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /*0: 44MHz, 1:88MHz*/ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ -#define bADClkPhase 0x4000000 - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap01 0xc0000000 -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - -#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 switch*/ -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx initial gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* the threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* the threshold for ant divers */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -#define bTxAGCRate18_06 0x7f7f7f7f /* Useless */ -#define bTxAGCRate54_24 0x7f7f7f7f -#define bTxAGCRateMCS32 0x7f -#define bTxAGCRateCCK 0x7f00 -#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f -#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f -#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f -#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register - * Zebra1 - */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/*Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - -/* - * Other Definition - */ - -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - -/* for PutRegsetting & GetRegSetting BitMask */ -#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ -#define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 -#define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff -#define bMaskDWord 0xffffffff - -/* for PutRFRegsetting & GetRFRegSetting BitMask */ -#define bRFRegOffsetMask 0xfffff -#define bEnable 0x1 /* Useless */ -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define ANTENNA_A 0x1 /* Useless */ -#define ANTENNA_B 0x2 -#define ANTENNA_AB 0x3 /* ANTENNA_A |ANTENNA_B */ - -#define ANTENNA_C 0x4 -#define ANTENNA_D 0x8 - -/* accept all physical address */ -#define RCR_AAP BIT(0) -#define RCR_APM BIT(1) /* accept physical match */ -#define RCR_AM BIT(2) /* accept multicast */ -#define RCR_AB BIT(3) /* accept broadcast */ -#define RCR_ACRC32 BIT(5) /* accept error packet */ -#define RCR_9356SEL BIT(6) -#define RCR_AICV BIT(12) /* Accept ICV error packet */ -#define RCR_RXFTH0 (BIT(13)|BIT(14)|BIT(15)) /* Rx FIFO threshold */ -#define RCR_ADF BIT(18) /* Accept Data(frame type) frame */ -#define RCR_ACF BIT(19) /* Accept control frame */ -#define RCR_AMF BIT(20) /* Accept management frame */ -#define RCR_ADD3 BIT(21) -#define RCR_APWRMGT BIT(22) /* Accept power management packet */ -#define RCR_CBSSID BIT(23) /* Accept BSSID match packet */ -#define RCR_ENMARP BIT(28) /* enable mac auto reset phy */ -#define RCR_EnCS1 BIT(29) /* enable carrier sense method 1 */ -#define RCR_EnCS2 BIT(30) /* enable carrier sense method 2 */ -/* Rx Early mode is performed for packet size greater than 1536 */ -#define RCR_OnlyErlPkt BIT(31) - -/*--------------------------Define Parameters-------------------------------*/ - -#endif /*__INC_HAL8192SPHYREG_H */ - diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c deleted file mode 100644 index cd6d9ff0bebca7c2d4dbaf0b001628eb84db08d3..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_pwrctrl.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_PWRCTRL_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" - -#define RTL8712_SDIO_LOCAL_BASE 0X10100000 -#define SDIO_HCPWM (RTL8712_SDIO_LOCAL_BASE + 0x0081) - -void r8712_set_rpwm(struct _adapter *padapter, u8 val8) -{ - u8 rpwm; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (pwrpriv->rpwm == val8) { - if (pwrpriv->rpwm_retry == 0) - return; - } - if (padapter->driver_stopped || padapter->surprise_removed) - return; - rpwm = val8 | pwrpriv->tog; - switch (val8) { - case PS_STATE_S1: - pwrpriv->cpwm = val8; - break; - case PS_STATE_S2:/* only for USB normal powersave mode use, - * temp mark some code. - */ - case PS_STATE_S3: - case PS_STATE_S4: - pwrpriv->cpwm = val8; - break; - default: - break; - } - pwrpriv->rpwm_retry = 0; - pwrpriv->rpwm = val8; - r8712_write8(padapter, 0x1025FE58, rpwm); - pwrpriv->tog += 0x80; -} - -void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode, uint smart_ps) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (ps_mode > PM_Card_Disable) - return; - /* if driver is in active state, we dont need set smart_ps.*/ - if (ps_mode == PS_MODE_ACTIVE) - smart_ps = 0; - if ((pwrpriv->pwr_mode != ps_mode) || (pwrpriv->smart_ps != smart_ps)) { - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - pwrpriv->bSleep = true; - else - pwrpriv->bSleep = false; - pwrpriv->pwr_mode = ps_mode; - pwrpriv->smart_ps = smart_ps; - schedule_work(&pwrpriv->SetPSModeWorkItem); - } -} - -/* - * Caller:ISR handler... - * - * This will be called when CPWM interrupt is up. - * - * using to update cpwn of drv; and drv will make a decision to up or - * down pwr level - */ -void r8712_cpwm_int_hdl(struct _adapter *padapter, - struct reportpwrstate_parm *preportpwrstate) -{ - struct pwrctrl_priv *pwrpriv = &(padapter->pwrctrlpriv); - struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); - - if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80)) - return; - del_timer(&padapter->pwrctrlpriv.rpwm_check_timer); - mutex_lock(&pwrpriv->mutex_lock); - pwrpriv->cpwm = (preportpwrstate->state) & 0xf; - if (pwrpriv->cpwm >= PS_STATE_S2) { - if (pwrpriv->alives & CMD_ALIVE) - complete(&(pcmdpriv->cmd_queue_comp)); - } - pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80; - mutex_unlock(&pwrpriv->mutex_lock); -} - -static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag) -{ - pwrctrl->alives |= tag; -} - -static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, uint tag) -{ - if (pwrctrl->alives & tag) - pwrctrl->alives ^= tag; -} - -static void _rpwm_check_handler (struct _adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - - if (padapter->driver_stopped || padapter->surprise_removed) - return; - if (pwrpriv->cpwm != pwrpriv->rpwm) - schedule_work(&pwrpriv->rpwm_workitem); -} - -static void SetPSModeWorkItemCallback(struct work_struct *work) -{ - struct pwrctrl_priv *pwrpriv = container_of(work, - struct pwrctrl_priv, SetPSModeWorkItem); - struct _adapter *padapter = container_of(pwrpriv, - struct _adapter, pwrctrlpriv); - if (!pwrpriv->bSleep) { - mutex_lock(&pwrpriv->mutex_lock); - if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - r8712_set_rpwm(padapter, PS_STATE_S4); - mutex_unlock(&pwrpriv->mutex_lock); - } -} - -static void rpwm_workitem_callback(struct work_struct *work) -{ - struct pwrctrl_priv *pwrpriv = container_of(work, - struct pwrctrl_priv, rpwm_workitem); - struct _adapter *padapter = container_of(pwrpriv, - struct _adapter, pwrctrlpriv); - if (pwrpriv->cpwm != pwrpriv->rpwm) { - mutex_lock(&pwrpriv->mutex_lock); - r8712_read8(padapter, SDIO_HCPWM); - pwrpriv->rpwm_retry = 1; - r8712_set_rpwm(padapter, pwrpriv->rpwm); - mutex_unlock(&pwrpriv->mutex_lock); - } -} - -static void rpwm_check_handler (struct timer_list *t) -{ - struct _adapter *adapter = - from_timer(adapter, t, pwrctrlpriv.rpwm_check_timer); - - _rpwm_check_handler(adapter); -} - -void r8712_init_pwrctrl_priv(struct _adapter *padapter) -{ - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; - - memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv)); - mutex_init(&pwrctrlpriv->mutex_lock); - pwrctrlpriv->cpwm = PS_STATE_S4; - pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE; - pwrctrlpriv->smart_ps = 0; - pwrctrlpriv->tog = 0x80; -/* clear RPWM to ensure driver and fw back to initial state. */ - r8712_write8(padapter, 0x1025FE58, 0); - INIT_WORK(&pwrctrlpriv->SetPSModeWorkItem, SetPSModeWorkItemCallback); - INIT_WORK(&pwrctrlpriv->rpwm_workitem, rpwm_workitem_callback); - timer_setup(&pwrctrlpriv->rpwm_check_timer, rpwm_check_handler, 0); -} - -/* - * Caller: r8712_cmd_thread - * Check if the fw_pwrstate is okay for issuing cmd. - * If not (cpwm should be is less than P2 state), then the sub-routine - * will raise the cpwm to be greater than or equal to P2. - * Calling Context: Passive - * Return Value: - * 0: r8712_cmd_thread can issue cmds to firmware afterwards. - * -EINVAL: r8712_cmd_thread can not do anything. - */ -int r8712_register_cmd_alive(struct _adapter *padapter) -{ - int res = 0; - struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - - mutex_lock(&pwrctrl->mutex_lock); - register_task_alive(pwrctrl, CMD_ALIVE); - if (pwrctrl->cpwm < PS_STATE_S2) { - r8712_set_rpwm(padapter, PS_STATE_S3); - res = -EINVAL; - } - mutex_unlock(&pwrctrl->mutex_lock); - return res; -} - -/* - * Caller: ISR - * If ISR's txdone, - * No more pkts for TX, - * Then driver shall call this fun. to power down firmware again. - */ -void r8712_unregister_cmd_alive(struct _adapter *padapter) -{ - struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - - mutex_lock(&pwrctrl->mutex_lock); - unregister_task_alive(pwrctrl, CMD_ALIVE); - if ((pwrctrl->cpwm > PS_STATE_S2) && - (pwrctrl->pwr_mode > PS_MODE_ACTIVE)) { - if ((pwrctrl->alives == 0) && - (check_fwstate(&padapter->mlmepriv, - _FW_UNDER_LINKING) != true)) { - r8712_set_rpwm(padapter, PS_STATE_S0); - } - } - mutex_unlock(&pwrctrl->mutex_lock); -} - -void r8712_flush_rwctrl_works(struct _adapter *padapter) -{ - struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; - - flush_work(&pwrctrl->SetPSModeWorkItem); - flush_work(&pwrctrl->rpwm_workitem); -} diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h deleted file mode 100644 index b35b9c7920ebbf3eceb252872fd06ff7c176ff40..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ /dev/null @@ -1,113 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_PWRCTRL_H_ -#define __RTL871X_PWRCTRL_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define CMD_ALIVE BIT(2) - -enum Power_Mgnt { - PS_MODE_ACTIVE = 0, - PS_MODE_MIN, - PS_MODE_MAX, - PS_MODE_DTIM, - PS_MODE_VOIP, - PS_MODE_UAPSD_WMM, - PS_MODE_UAPSD, - PS_MODE_IBSS, - PS_MODE_WWLAN, - PM_Radio_Off, - PM_Card_Disable, - PS_MODE_NUM -}; - -/* - * BIT[2:0] = HW state - * BIT[3] = Protocol PS state, 0: register active state, - * 1: register sleep state - * BIT[4] = sub-state - */ - -#define PS_DPS BIT(0) -#define PS_LCLK (PS_DPS) -#define PS_RF_OFF BIT(1) -#define PS_ALL_ON BIT(2) -#define PS_ST_ACTIVE BIT(3) -#define PS_LP BIT(4) /* low performance */ - -#define PS_STATE_MASK (0x0F) -#define PS_STATE_HW_MASK (0x07) -#define PS_SEQ_MASK (0xc0) - -#define PS_STATE(x) (PS_STATE_MASK & (x)) -#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x)) -#define PS_SEQ(x) (PS_SEQ_MASK & (x)) - -#define PS_STATE_S0 (PS_DPS) -#define PS_STATE_S1 (PS_LCLK) -#define PS_STATE_S2 (PS_RF_OFF) -#define PS_STATE_S3 (PS_ALL_ON) -#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON)) - -#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON)) -#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE)) -#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) - -struct reportpwrstate_parm { - unsigned char mode; - unsigned char state; /* the CPWM value */ - unsigned short rsvd; -}; - -struct pwrctrl_priv { - struct mutex mutex_lock; - /*volatile*/ u8 rpwm; /* requested power state for fw */ - /* fw current power state. updated when 1. read from HCPWM or - * 2. driver lowers power level - */ - /*volatile*/ u8 cpwm; - /*volatile*/ u8 tog; /* toggling */ - /*volatile*/ u8 cpwm_tog; /* toggling */ - /*volatile*/ u8 tgt_rpwm; /* wanted power state */ - uint pwr_mode; - uint smart_ps; - uint alives; - uint ImrContent; /* used to store original imr. */ - uint bSleep; /* sleep -> active is different from active -> sleep. */ - - struct work_struct SetPSModeWorkItem; - struct work_struct rpwm_workitem; - struct timer_list rpwm_check_timer; - u8 rpwm_retry; - uint bSetPSModeWorkItemInProgress; - - spinlock_t pnp_pwr_mgnt_lock; - s32 pnp_current_pwr_state; - u8 pnp_bstop_trx; - u8 pnp_wwirp_pending; -}; - -void r8712_init_pwrctrl_priv(struct _adapter *adapter); -int r8712_register_cmd_alive(struct _adapter *padapter); -void r8712_unregister_cmd_alive(struct _adapter *padapter); -void r8712_cpwm_int_hdl(struct _adapter *padapter, - struct reportpwrstate_parm *preportpwrstate); -void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode, - uint smart_ps); -void r8712_set_rpwm(struct _adapter *padapter, u8 val8); -void r8712_flush_rwctrl_works(struct _adapter *padapter); - -#endif /* __RTL871X_PWRCTRL_H_ */ diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c deleted file mode 100644 index 8a3566214af726ec347772a817b67de545f8a669..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ /dev/null @@ -1,671 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_recv.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_RECV_C_ - -#include <linux/ip.h> -#include <linux/if_ether.h> -#include <linux/etherdevice.h> -#include <linux/ieee80211.h> -#include <net/cfg80211.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "mlme_osdep.h" -#include "ethernet.h" -#include "usb_ops.h" -#include "wifi.h" - -static const u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; - -/* Datagram Delivery Protocol */ -static const u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3}; - -void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) -{ - memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv)); - spin_lock_init(&psta_recvpriv->lock); - _init_queue(&psta_recvpriv->defrag_q); -} - -int _r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter) -{ - int ret; - sint i; - union recv_frame *precvframe; - - memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv)); - spin_lock_init(&precvpriv->lock); - _init_queue(&precvpriv->free_recv_queue); - _init_queue(&precvpriv->recv_pending_queue); - precvpriv->adapter = padapter; - precvpriv->free_recvframe_cnt = NR_RECVFRAME; - precvpriv->pallocated_frame_buf = kzalloc(NR_RECVFRAME * - sizeof(union recv_frame) + RXFRAME_ALIGN_SZ, - GFP_ATOMIC); - if (!precvpriv->pallocated_frame_buf) - return -ENOMEM; - precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + - RXFRAME_ALIGN_SZ - - ((addr_t)(precvpriv->pallocated_frame_buf) & - (RXFRAME_ALIGN_SZ - 1)); - precvframe = (union recv_frame *)precvpriv->precv_frame_buf; - for (i = 0; i < NR_RECVFRAME; i++) { - INIT_LIST_HEAD(&(precvframe->u.list)); - list_add_tail(&(precvframe->u.list), - &(precvpriv->free_recv_queue.queue)); - r8712_os_recv_resource_alloc(padapter, precvframe); - precvframe->u.hdr.adapter = padapter; - precvframe++; - } - precvpriv->rx_pending_cnt = 1; - ret = r8712_init_recv_priv(precvpriv, padapter); - if (ret) - kfree(precvpriv->pallocated_frame_buf); - - return ret; -} - -void _r8712_free_recv_priv(struct recv_priv *precvpriv) -{ - kfree(precvpriv->pallocated_frame_buf); - r8712_free_recv_priv(precvpriv); -} - -union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue) -{ - unsigned long irqL; - union recv_frame *precvframe; - struct _adapter *padapter; - struct recv_priv *precvpriv; - - spin_lock_irqsave(&pfree_recv_queue->lock, irqL); - precvframe = list_first_entry_or_null(&pfree_recv_queue->queue, - union recv_frame, u.hdr.list); - if (precvframe) { - list_del_init(&precvframe->u.hdr.list); - padapter = precvframe->u.hdr.adapter; - if (padapter) { - precvpriv = &padapter->recvpriv; - if (pfree_recv_queue == &precvpriv->free_recv_queue) - precvpriv->free_recvframe_cnt--; - } - } - spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL); - return precvframe; -} - -/* - * caller : defrag; recvframe_chk_defrag in recv_thread (passive) - * pframequeue: defrag_queue : will be accessed in recv_thread (passive) - * using spin_lock to protect - */ -void r8712_free_recvframe_queue(struct __queue *pframequeue, - struct __queue *pfree_recv_queue) -{ - union recv_frame *precvframe; - struct list_head *plist, *phead; - - spin_lock(&pframequeue->lock); - phead = &pframequeue->queue; - plist = phead->next; - while (!end_of_queue_search(phead, plist)) { - precvframe = container_of(plist, union recv_frame, u.list); - plist = plist->next; - r8712_free_recvframe(precvframe, pfree_recv_queue); - } - spin_unlock(&pframequeue->lock); -} - -sint r8712_recvframe_chkmic(struct _adapter *adapter, - union recv_frame *precvframe) -{ - sint i, res = _SUCCESS; - u32 datalen; - u8 miccode[8]; - u8 bmic_err = false; - u8 *pframe, *payload, *pframemic; - u8 *mickey, idx, *iv; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - stainfo = r8712_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); - if (prxattrib->encrypt == _TKIP_) { - /* calculate mic code */ - if (stainfo) { - if (is_multicast_ether_addr(prxattrib->ra)) { - iv = precvframe->u.hdr.rx_data + - prxattrib->hdrlen; - idx = iv[3]; - mickey = &psecuritypriv->XGrprxmickey[(((idx >> - 6) & 0x3)) - 1].skey[0]; - if (!psecuritypriv->binstallGrpkey) - return _FAIL; - } else { - mickey = &stainfo->tkiprxmickey.skey[0]; - } - /*icv_len included the mic code*/ - datalen = precvframe->u.hdr.len - prxattrib->hdrlen - - prxattrib->iv_len - prxattrib->icv_len - 8; - pframe = precvframe->u.hdr.rx_data; - payload = pframe + prxattrib->hdrlen + - prxattrib->iv_len; - seccalctkipmic(mickey, pframe, payload, datalen, - &miccode[0], - (unsigned char)prxattrib->priority); - pframemic = payload + datalen; - bmic_err = false; - for (i = 0; i < 8; i++) { - if (miccode[i] != *(pframemic + i)) - bmic_err = true; - } - if (bmic_err) { - if (prxattrib->bdecrypted) - r8712_handle_tkip_mic_err(adapter, - (u8)is_multicast_ether_addr(prxattrib->ra)); - res = _FAIL; - } else { - /* mic checked ok */ - if (!psecuritypriv->bcheck_grpkey && - is_multicast_ether_addr(prxattrib->ra)) - psecuritypriv->bcheck_grpkey = true; - } - recvframe_pull_tail(precvframe, 8); - } - } - return res; -} - -/* decrypt and set the ivlen,icvlen of the recv_frame */ -union recv_frame *r8712_decryptor(struct _adapter *padapter, - union recv_frame *precv_frame) -{ - struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - union recv_frame *return_packet = precv_frame; - - if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) || - psecuritypriv->sw_decrypt)) { - psecuritypriv->hw_decrypted = false; - switch (prxattrib->encrypt) { - case _WEP40_: - case _WEP104_: - r8712_wep_decrypt(padapter, (u8 *)precv_frame); - break; - case _TKIP_: - r8712_tkip_decrypt(padapter, (u8 *)precv_frame); - break; - case _AES_: - r8712_aes_decrypt(padapter, (u8 *)precv_frame); - break; - default: - break; - } - } else if (prxattrib->bdecrypted == 1) { - psecuritypriv->hw_decrypted = true; - } - return return_packet; -} - -/*###set the security information in the recv_frame */ -union recv_frame *r8712_portctrl(struct _adapter *adapter, - union recv_frame *precv_frame) -{ - u8 *psta_addr, *ptr; - uint auth_alg; - struct recv_frame_hdr *pfhdr; - struct sta_info *psta; - struct sta_priv *pstapriv; - union recv_frame *prtnframe; - u16 ether_type; - - pstapriv = &adapter->stapriv; - ptr = precv_frame->u.hdr.rx_data; - pfhdr = &precv_frame->u.hdr; - psta_addr = pfhdr->attrib.ta; - psta = r8712_get_stainfo(pstapriv, psta_addr); - auth_alg = adapter->securitypriv.AuthAlgrthm; - if (auth_alg == 2) { - /* get ether_type */ - ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; - ether_type = get_unaligned_be16(ptr); - - if (psta && psta->ieee8021x_blocked) { - /* blocked - * only accept EAPOL frame - */ - if (ether_type == 0x888e) { - prtnframe = precv_frame; - } else { - /*free this frame*/ - r8712_free_recvframe(precv_frame, - &adapter->recvpriv.free_recv_queue); - prtnframe = NULL; - } - } else { - /* allowed - * check decryption status, and decrypt the - * frame if needed - */ - prtnframe = precv_frame; - /* check is the EAPOL frame or not (Rekey) */ - if (ether_type == 0x888e) { - /* check Rekey */ - prtnframe = precv_frame; - } - } - } else { - prtnframe = precv_frame; - } - return prtnframe; -} - -static sint recv_decache(union recv_frame *precv_frame, u8 bretry, - struct stainfo_rxcache *prxcache) -{ - sint tid = precv_frame->u.hdr.attrib.priority; - u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) | - (precv_frame->u.hdr.attrib.frag_num & 0xf); - - if (tid > 15) - return _FAIL; - if (seq_ctrl == prxcache->tid_rxseq[tid]) - return _FAIL; - prxcache->tid_rxseq[tid] = seq_ctrl; - return _SUCCESS; -} - -static sint sta2sta_data_frame(struct _adapter *adapter, - union recv_frame *precv_frame, - struct sta_info **psta) -{ - u8 *ptr = precv_frame->u.hdr.rx_data; - sint ret = _SUCCESS; - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - u8 *sta_addr = NULL; - bool bmcast = is_multicast_ether_addr(pattrib->dst); - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - /* filter packets that SA is myself or multicast or broadcast */ - if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) - return _FAIL; - if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) - return _FAIL; - if (is_zero_ether_addr(pattrib->bssid) || - is_zero_ether_addr(mybssid) || - (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) - return _FAIL; - sta_addr = pattrib->src; - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* For Station mode, sa and bssid should always be BSSID, - * and DA is my mac-address - */ - if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) - return _FAIL; - sta_addr = pattrib->bssid; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - if (bmcast) { - /* For AP mode, if DA == MCAST, then BSSID should - * be also MCAST - */ - if (!is_multicast_ether_addr(pattrib->bssid)) - return _FAIL; - } else { /* not mc-frame */ - /* For AP mode, if DA is non-MCAST, then it must be - * BSSID, and bssid == BSSID - */ - if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) - return _FAIL; - sta_addr = pattrib->src; - } - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN); - memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); - memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN); - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - sta_addr = mybssid; - } else { - ret = _FAIL; - } - if (bmcast) - *psta = r8712_get_bcmc_stainfo(adapter); - else - *psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */ - if (!*psta) { - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) - adapter->mppriv.rx_pktloss++; - return _FAIL; - } - return ret; -} - -static sint ap2sta_data_frame(struct _adapter *adapter, - union recv_frame *precv_frame, - struct sta_info **psta) -{ - u8 *ptr = precv_frame->u.hdr.rx_data; - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - u8 *mybssid = get_bssid(pmlmepriv); - u8 *myhwaddr = myid(&adapter->eeprompriv); - bool bmcast = is_multicast_ether_addr(pattrib->dst); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - /* if NULL-frame, drop packet */ - if ((GetFrameSubType(ptr)) == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC)) - return _FAIL; - /* drop QoS-SubType Data, including QoS NULL, - * excluding QoS-Data - */ - if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == - WIFI_QOS_DATA_TYPE) { - if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6))) - return _FAIL; - } - - /* filter packets that SA is myself or multicast or broadcast */ - if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) - return _FAIL; - - /* da should be for me */ - if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) - return _FAIL; - /* check BSSID */ - if (is_zero_ether_addr(pattrib->bssid) || - is_zero_ether_addr(mybssid) || - (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) - return _FAIL; - if (bmcast) - *psta = r8712_get_bcmc_stainfo(adapter); - else - *psta = r8712_get_stainfo(pstapriv, pattrib->bssid); - if (!*psta) - return _FAIL; - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) && - check_fwstate(pmlmepriv, _FW_LINKED)) { - memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN); - memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); - memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN); - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - memcpy(pattrib->bssid, mybssid, ETH_ALEN); - *psta = r8712_get_stainfo(pstapriv, pattrib->bssid); - if (!*psta) - return _FAIL; - } else { - return _FAIL; - } - return _SUCCESS; -} - -static sint sta2ap_data_frame(struct _adapter *adapter, - union recv_frame *precv_frame, - struct sta_info **psta) -{ - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - unsigned char *mybssid = get_bssid(pmlmepriv); - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* For AP mode, if DA is non-MCAST, then it must be BSSID, - * and bssid == BSSID - * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR - */ - if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) - return _FAIL; - *psta = r8712_get_stainfo(pstapriv, pattrib->src); - if (!*psta) - return _FAIL; - } - return _SUCCESS; -} - -static sint validate_recv_ctrl_frame(struct _adapter *adapter, - union recv_frame *precv_frame) -{ - return _FAIL; -} - -static sint validate_recv_mgnt_frame(struct _adapter *adapter, - union recv_frame *precv_frame) -{ - return _FAIL; -} - -static sint validate_recv_data_frame(struct _adapter *adapter, - union recv_frame *precv_frame) -{ - int res; - u8 bretry; - u8 *psa, *pda, *pbssid; - struct sta_info *psta = NULL; - u8 *ptr = precv_frame->u.hdr.rx_data; - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - struct security_priv *psecuritypriv = &adapter->securitypriv; - - bretry = GetRetry(ptr); - pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr); - psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr); - pbssid = get_hdr_bssid(ptr); - if (!pbssid) - return _FAIL; - memcpy(pattrib->dst, pda, ETH_ALEN); - memcpy(pattrib->src, psa, ETH_ALEN); - memcpy(pattrib->bssid, pbssid, ETH_ALEN); - switch (pattrib->to_fr_ds) { - case 0: - memcpy(pattrib->ra, pda, ETH_ALEN); - memcpy(pattrib->ta, psa, ETH_ALEN); - res = sta2sta_data_frame(adapter, precv_frame, &psta); - break; - case 1: - memcpy(pattrib->ra, pda, ETH_ALEN); - memcpy(pattrib->ta, pbssid, ETH_ALEN); - res = ap2sta_data_frame(adapter, precv_frame, &psta); - break; - case 2: - memcpy(pattrib->ra, pbssid, ETH_ALEN); - memcpy(pattrib->ta, psa, ETH_ALEN); - res = sta2ap_data_frame(adapter, precv_frame, &psta); - break; - case 3: - memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); - memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); - return _FAIL; - default: - return _FAIL; - } - if (res == _FAIL) - return _FAIL; - if (!psta) - return _FAIL; - precv_frame->u.hdr.psta = psta; - pattrib->amsdu = 0; - /* parsing QC field */ - if (pattrib->qos == 1) { - pattrib->priority = GetPriority((ptr + 24)); - pattrib->ack_policy = GetAckpolicy((ptr + 24)); - pattrib->amsdu = GetAMsdu((ptr + 24)); - pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26; - } else { - pattrib->priority = 0; - pattrib->hdrlen = (pattrib->to_fr_ds == 3) ? 30 : 24; - } - - if (pattrib->order)/*HT-CTRL 11n*/ - pattrib->hdrlen += 4; - precv_frame->u.hdr.preorder_ctrl = - &psta->recvreorder_ctrl[pattrib->priority]; - - /* decache, drop duplicate recv packets */ - if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == - _FAIL) - return _FAIL; - - if (pattrib->privacy) { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, - is_multicast_ether_addr(pattrib->ra)); - SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, - pattrib->encrypt); - } else { - pattrib->encrypt = 0; - pattrib->iv_len = pattrib->icv_len = 0; - } - return _SUCCESS; -} - -sint r8712_validate_recv_frame(struct _adapter *adapter, - union recv_frame *precv_frame) -{ - /*shall check frame subtype, to / from ds, da, bssid */ - /*then call check if rx seq/frag. duplicated.*/ - - u8 type; - u8 subtype; - sint retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - - u8 *ptr = precv_frame->u.hdr.rx_data; - u8 ver = (unsigned char)(*ptr) & 0x3; - - /*add version chk*/ - if (ver != 0) - return _FAIL; - type = GetFrameType(ptr); - subtype = GetFrameSubType(ptr); /*bit(7)~bit(2)*/ - pattrib->to_fr_ds = get_tofr_ds(ptr); - pattrib->frag_num = GetFragNum(ptr); - pattrib->seq_num = GetSequence(ptr); - pattrib->pw_save = GetPwrMgt(ptr); - pattrib->mfrag = GetMFrag(ptr); - pattrib->mdata = GetMData(ptr); - pattrib->privacy = GetPrivacy(ptr); - pattrib->order = GetOrder(ptr); - switch (type) { - case IEEE80211_FTYPE_MGMT: - retval = validate_recv_mgnt_frame(adapter, precv_frame); - break; - case IEEE80211_FTYPE_CTL: - retval = validate_recv_ctrl_frame(adapter, precv_frame); - break; - case IEEE80211_FTYPE_DATA: - pattrib->qos = (subtype & BIT(7)) ? 1 : 0; - retval = validate_recv_data_frame(adapter, precv_frame); - break; - default: - return _FAIL; - } - return retval; -} - -int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) -{ - /*remove the wlanhdr and add the eth_hdr*/ - sint rmv_len; - u16 len; - u8 bsnaphdr; - u8 *psnap_type; - struct ieee80211_snap_hdr *psnap; - struct _adapter *adapter = precvframe->u.hdr.adapter; - struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - - u8 *ptr = precvframe->u.hdr.rx_data; /*point to frame_ctrl field*/ - struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib; - - if (pattrib->encrypt) - recvframe_pull_tail(precvframe, pattrib->icv_len); - psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + - pattrib->iv_len); - psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE; - /* convert hdr + possible LLC headers into Ethernet header */ - if ((!memcmp(psnap, (void *)rfc1042_header, SNAP_SIZE) && - (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_IPX, 2)) && - (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) || - !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType - */ - bsnaphdr = true; - } else { - /* Leave Ethernet header part of hdr and full payload */ - bsnaphdr = false; - } - rmv_len = pattrib->hdrlen + pattrib->iv_len + - (bsnaphdr ? SNAP_SIZE : 0); - len = precvframe->u.hdr.len - rmv_len; - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ptr += rmv_len; - *ptr = 0x87; - *(ptr + 1) = 0x12; - /* append rx status for mp test packets */ - ptr = recvframe_pull(precvframe, (rmv_len - - sizeof(struct ethhdr) + 2) - 24); - if (!ptr) - return -ENOMEM; - memcpy(ptr, get_rxmem(precvframe), 24); - ptr += 24; - } else { - ptr = recvframe_pull(precvframe, (rmv_len - - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); - if (!ptr) - return -ENOMEM; - } - - memcpy(ptr, pattrib->dst, ETH_ALEN); - memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN); - if (!bsnaphdr) { - __be16 be_tmp = htons(len); - - memcpy(ptr + 12, &be_tmp, 2); - } - return 0; -} - -void r8712_recv_entry(union recv_frame *precvframe) -{ - struct _adapter *padapter; - struct recv_priv *precvpriv; - - s32 ret = _SUCCESS; - - padapter = precvframe->u.hdr.adapter; - precvpriv = &(padapter->recvpriv); - - padapter->ledpriv.LedControlHandler(padapter, LED_CTL_RX); - - ret = recv_func(padapter, precvframe); - if (ret == _FAIL) - goto _recv_entry_drop; - precvpriv->rx_pkts++; - precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail - - precvframe->u.hdr.rx_data); - return; -_recv_entry_drop: - precvpriv->rx_drop++; - padapter->mppriv.rx_pktloss = precvpriv->rx_drop; -} diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h deleted file mode 100644 index 0760bccbf389c131b0b802c49c1bdbd239b1a353..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ /dev/null @@ -1,208 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _RTL871X_RECV_H_ -#define _RTL871X_RECV_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define NR_RECVFRAME 256 - -#define RXFRAME_ALIGN 8 -#define RXFRAME_ALIGN_SZ (1 << RXFRAME_ALIGN) - -#define MAX_SUBFRAME_COUNT 64 - -/* for Rx reordering buffer control */ -struct recv_reorder_ctrl { - struct _adapter *padapter; - u16 indicate_seq; /* =wstart_b, init_value=0xffff */ - u16 wend_b; - u8 wsize_b; - struct __queue pending_recvframe_queue; - struct timer_list reordering_ctrl_timer; -}; - -struct stainfo_rxcache { - u16 tid_rxseq[16]; -}; - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 - -struct smooth_rssi_data { - u32 elements[100]; /* array to store values */ - u32 index; /* index to current array to store */ - u32 total_num; /* num of valid elements */ - u32 total_val; /* sum of valid elements */ -}; - -struct rx_pkt_attrib { - u8 amsdu; - u8 order; - u8 qos; - u8 to_fr_ds; - u8 frag_num; - u16 seq_num; - u8 pw_save; - u8 mfrag; - u8 mdata; - u8 privacy; /* in frame_ctrl field */ - u8 bdecrypted; - int hdrlen; /* the WLAN Header Len */ - int encrypt; /* 0 no encrypt. != 0 encrypt algorithm */ - int iv_len; - int icv_len; - int priority; - int ack_policy; - u8 crc_err; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 ta[ETH_ALEN]; - u8 ra[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u8 tcpchk_valid; /* 0: invalid, 1: valid */ - u8 ip_chkrpt; /* 0: incorrect, 1: correct */ - u8 tcp_chkrpt; /* 0: incorrect, 1: correct */ - u8 signal_qual; - s8 rx_mimo_signal_qual[2]; - u8 mcs_rate; - u8 htc; - u8 signal_strength; -}; - -/* - * accesser of recv_priv: recv_entry(dispatch / passive level); - * recv_thread(passive) ; returnpkt(dispatch) - * ; halt(passive) ; - * - * using enter_critical section to protect - */ -struct recv_priv { - spinlock_t lock; - struct __queue free_recv_queue; - struct __queue recv_pending_queue; - u8 *pallocated_frame_buf; - u8 *precv_frame_buf; - uint free_recvframe_cnt; - struct _adapter *adapter; - uint rx_bytes; - uint rx_pkts; - uint rx_drop; - uint rx_icv_err; - uint rx_largepacket_crcerr; - uint rx_smallpacket_crcerr; - uint rx_middlepacket_crcerr; - u8 rx_pending_cnt; - uint ff_hwaddr; - struct tasklet_struct recv_tasklet; - struct sk_buff_head free_recv_skb_queue; - struct sk_buff_head rx_skb_queue; - u8 *pallocated_recv_buf; - u8 *precv_buf; /* 4 alignment */ - struct __queue free_recv_buf_queue; - u32 free_recv_buf_queue_cnt; - /* For the phy information */ - s8 rssi; - u8 signal; - u8 noise; - u8 fw_rssi; - struct smooth_rssi_data signal_qual_data; - struct smooth_rssi_data signal_strength_data; -}; - -struct sta_recv_priv { - spinlock_t lock; - sint option; - struct __queue defrag_q; /* keeping the fragment frame until defrag */ - struct stainfo_rxcache rxcache; - uint sta_rx_bytes; - uint sta_rx_pkts; - uint sta_rx_fail; -}; - -#include "rtl8712_recv.h" - -/* get a free recv_frame from pfree_recv_queue */ -union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue); -void r8712_free_recvframe(union recv_frame *precvframe, - struct __queue *pfree_recv_queue); -void r8712_free_recvframe_queue(struct __queue *pframequeue, - struct __queue *pfree_recv_queue); -int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe); -int recv_func(struct _adapter *padapter, void *pcontext); - -static inline u8 *get_rxmem(union recv_frame *precvframe) -{ - /* always return rx_head... */ - if (!precvframe) - return NULL; - return precvframe->u.hdr.rx_head; -} - -static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz) -{ - /* used for extract sz bytes from rx_data, update rx_data and return - * the updated rx_data to the caller - */ - if (!precvframe) - return NULL; - precvframe->u.hdr.rx_data += sz; - if (precvframe->u.hdr.rx_data > precvframe->u.hdr.rx_tail) { - precvframe->u.hdr.rx_data -= sz; - return NULL; - } - precvframe->u.hdr.len -= sz; - return precvframe->u.hdr.rx_data; -} - -static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz) -{ - /* used for append sz bytes from ptr to rx_tail, update rx_tail and - * return the updated rx_tail to the caller - * after putting, rx_tail must be still larger than rx_end. - */ - if (!precvframe) - return NULL; - precvframe->u.hdr.rx_tail += sz; - if (precvframe->u.hdr.rx_tail > precvframe->u.hdr.rx_end) { - precvframe->u.hdr.rx_tail -= sz; - return NULL; - } - precvframe->u.hdr.len += sz; - return precvframe->u.hdr.rx_tail; -} - -static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) -{ - /* rmv data from rx_tail (by yitsen) - * used for extract sz bytes from rx_end, update rx_end and return the - * updated rx_end to the caller - * after pulling, rx_end must be still larger than rx_data. - */ - if (!precvframe) - return NULL; - precvframe->u.hdr.rx_tail -= sz; - if (precvframe->u.hdr.rx_tail < precvframe->u.hdr.rx_data) { - precvframe->u.hdr.rx_tail += sz; - return NULL; - } - precvframe->u.hdr.len -= sz; - return precvframe->u.hdr.rx_tail; -} - -struct sta_info; - -void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv); -sint r8712_recvframe_chkmic(struct _adapter *adapter, - union recv_frame *precvframe); -union recv_frame *r8712_decryptor(struct _adapter *adapter, - union recv_frame *precv_frame); -union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *adapter, - union recv_frame *precv_frame); -int r8712_validate_recv_frame(struct _adapter *adapter, - union recv_frame *precv_frame); -union recv_frame *r8712_portctrl(struct _adapter *adapter, - union recv_frame *precv_frame); - -#endif - diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h deleted file mode 100644 index 7d98921a48fac022b7f456b423375ed3bc5a96cf..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_rf.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_RF_H_ -#define __RTL871X_RF_H_ - -#include "rtl871x_cmd.h" -#include "rtl871x_mp_phy_regdef.h" - -#define OFDM_PHY 1 -#define MIXED_PHY 2 -#define CCK_PHY 3 -#define NumRates (13) -#define RTL8711_RF_MAX_SENS 6 -#define RTL8711_RF_DEF_SENS 4 -#define NUM_CHANNELS 15 - -struct regulatory_class { - u32 starting_freq; /*MHz, */ - u8 channel_set[NUM_CHANNELS]; - u8 channel_cck_power[NUM_CHANNELS]; /*dbm*/ - u8 channel_ofdm_power[NUM_CHANNELS];/*dbm*/ - u8 txpower_limit; /*dbm*/ - u8 channel_spacing; /*MHz*/ - u8 modem; -}; - -enum _REG_PREAMBLE_MODE { - PREAMBLE_LONG = 1, - PREAMBLE_AUTO = 2, - PREAMBLE_SHORT = 3, -}; - -enum { - RTL8712_RFC_1T = 0x10, - RTL8712_RFC_2T = 0x20, - RTL8712_RFC_1R = 0x01, - RTL8712_RFC_2R = 0x02, - RTL8712_RFC_1T1R = 0x11, - RTL8712_RFC_1T2R = 0x12, - RTL8712_RFC_TURBO = 0x92, - RTL8712_RFC_2T2R = 0x22 -}; - -#endif /*__RTL871X_RF_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c deleted file mode 100644 index e46a5dbc7b65fa53108ff5f8834cc5873cc27704..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ /dev/null @@ -1,1386 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_security.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_SECURITY_C_ - -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kref.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/circ_buf.h> -#include <linux/uaccess.h> -#include <asm/byteorder.h> -#include <linux/atomic.h> -#include <linux/crc32poly.h> -#include <linux/semaphore.h> -#include <linux/ieee80211.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" - -/* =====WEP related===== */ - -struct arc4context { - u32 x; - u32 y; - u8 state[256]; -}; - -static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len) -{ - u32 t, u; - u32 keyindex; - u32 stateindex; - u8 *state; - u32 counter; - - state = parc4ctx->state; - parc4ctx->x = 0; - parc4ctx->y = 0; - for (counter = 0; counter < 256; counter++) - state[counter] = (u8)counter; - keyindex = 0; - stateindex = 0; - for (counter = 0; counter < 256; counter++) { - t = state[counter]; - stateindex = (stateindex + key[keyindex] + t) & 0xff; - u = state[stateindex]; - state[stateindex] = (u8)t; - state[counter] = (u8)u; - if (++keyindex >= key_len) - keyindex = 0; - } -} - -static u32 arcfour_byte(struct arc4context *parc4ctx) -{ - u32 x; - u32 y; - u32 sx, sy; - u8 *state; - - state = parc4ctx->state; - x = (parc4ctx->x + 1) & 0xff; - sx = state[x]; - y = (sx + parc4ctx->y) & 0xff; - sy = state[y]; - parc4ctx->x = x; - parc4ctx->y = y; - state[y] = (u8)sx; - state[x] = (u8)sy; - return state[(sx + sy) & 0xff]; -} - -static void arcfour_encrypt(struct arc4context *parc4ctx, - u8 *dest, u8 *src, u32 len) -{ - u32 i; - - for (i = 0; i < len; i++) - dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx); -} - -static sint bcrc32initialized; -static u32 crc32_table[256]; - -static u8 crc32_reverseBit(u8 data) -{ - return ((u8)(data << 7) & 0x80) | ((data << 5) & 0x40) | ((data << 3) - & 0x20) | ((data << 1) & 0x10) | ((data >> 1) & 0x08) | - ((data >> 3) & 0x04) | ((data >> 5) & 0x02) | ((data >> 7) & - 0x01); -} - -static void crc32_init(void) -{ - sint i, j; - u32 c; - u8 *p = (u8 *)&c, *p1; - u8 k; - - if (bcrc32initialized == 1) - return; - - for (i = 0; i < 256; ++i) { - k = crc32_reverseBit((u8)i); - for (c = ((u32)k) << 24, j = 8; j > 0; --j) - c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY_BE : (c << 1); - p1 = (u8 *)&crc32_table[i]; - p1[0] = crc32_reverseBit(p[3]); - p1[1] = crc32_reverseBit(p[2]); - p1[2] = crc32_reverseBit(p[1]); - p1[3] = crc32_reverseBit(p[0]); - } - bcrc32initialized = 1; -} - -static u32 getcrc32(u8 *buf, u32 len) -{ - u8 *p; - u32 crc; - - if (!bcrc32initialized) - crc32_init(); - crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ - for (p = buf; len > 0; ++p, --len) - crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); - return ~crc; /* transmit complement, per CRC-32 spec */ -} - -/* - * Need to consider the fragment situation - */ -void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe) -{ /* exclude ICV */ - unsigned char crc[4]; - struct arc4context mycontext; - u32 curfragnum, length, keylength, pki; - u8 *pframe, *payload, *iv; /*,*wepkey*/ - u8 wepkey[16]; - struct pkt_attrib *pattrib = &((struct xmit_frame *) - pxmitframe)->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) - return; - pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET; - /*start to encrypt each fragment*/ - if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) { - pki = psecuritypriv->PrivacyKeyIndex; - keylength = psecuritypriv->DefKeylen[pki]; - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - iv = pframe + pattrib->hdrlen; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->DefKey[ - psecuritypriv->PrivacyKeyIndex].skey[0], - keylength); - payload = pframe + pattrib->iv_len + pattrib->hdrlen; - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len; - *((__le32 *)crc) = cpu_to_le32(getcrc32( - payload, length)); - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, - length); - arcfour_encrypt(&mycontext, payload + length, - crc, 4); - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - pattrib->iv_len - - pattrib->icv_len; - *((__le32 *)crc) = cpu_to_le32(getcrc32( - payload, length)); - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, - length); - arcfour_encrypt(&mycontext, payload + length, - crc, 4); - pframe += pxmitpriv->frag_len; - pframe = (u8 *)RND4((addr_t)(pframe)); - } - } - } -} - -void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe) -{ - /* exclude ICV */ - u8 crc[4]; - struct arc4context mycontext; - u32 length, keylength; - u8 *pframe, *payload, *iv, wepkey[16]; - u8 keyindex; - struct rx_pkt_attrib *prxattrib = &(((union recv_frame *) - precvframe)->u.hdr.attrib); - struct security_priv *psecuritypriv = &padapter->securitypriv; - - pframe = (unsigned char *)((union recv_frame *)precvframe)-> - u.hdr.rx_data; - /* start to decrypt recvframe */ - if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == - _WEP104_)) { - iv = pframe + prxattrib->hdrlen; - keyindex = (iv[3] & 0x3); - keylength = psecuritypriv->DefKeylen[keyindex]; - memcpy(&wepkey[0], iv, 3); - memcpy(&wepkey[3], &psecuritypriv->DefKey[ - psecuritypriv->PrivacyKeyIndex].skey[0], - keylength); - length = ((union recv_frame *)precvframe)-> - u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len; - payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; - /* decrypt payload include icv */ - arcfour_init(&mycontext, wepkey, 3 + keylength); - arcfour_encrypt(&mycontext, payload, payload, length); - /* calculate icv and compare the icv */ - *((__le32 *)crc) = cpu_to_le32(getcrc32(payload, length - 4)); - } -} - -/* 3 =====TKIP related===== */ - -static u32 secmicgetuint32(u8 *p) -/* Convert from Byte[] to Us4Byte32 in a portable way */ -{ - s32 i; - u32 res = 0; - - for (i = 0; i < 4; i++) - res |= ((u32)(*p++)) << (8 * i); - return res; -} - -static void secmicputuint32(u8 *p, u32 val) -/* Convert from Us4Byte32 to Byte[] in a portable way */ -{ - long i; - - for (i = 0; i < 4; i++) { - *p++ = (u8)(val & 0xff); - val >>= 8; - } -} - -static void secmicclear(struct mic_data *pmicdata) -{ -/* Reset the state to the empty message. */ - pmicdata->L = pmicdata->K0; - pmicdata->R = pmicdata->K1; - pmicdata->nBytesInM = 0; - pmicdata->M = 0; -} - -void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key) -{ - /* Set the key */ - pmicdata->K0 = secmicgetuint32(key); - pmicdata->K1 = secmicgetuint32(key + 4); - /* and reset the message */ - secmicclear(pmicdata); -} - -static void secmicappendbyte(struct mic_data *pmicdata, u8 b) -{ - /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((u32)b) << (8 * pmicdata->nBytesInM); - pmicdata->nBytesInM++; - /* Process the word if it is full. */ - if (pmicdata->nBytesInM >= 4) { - pmicdata->L ^= pmicdata->M; - pmicdata->R ^= ROL32(pmicdata->L, 17); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | - ((pmicdata->L & 0x00ff00ff) << 8); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROL32(pmicdata->L, 3); - pmicdata->L += pmicdata->R; - pmicdata->R ^= ROR32(pmicdata->L, 2); - pmicdata->L += pmicdata->R; - /* Clear the buffer */ - pmicdata->M = 0; - pmicdata->nBytesInM = 0; - } -} - -void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes) -{ - /* This is simple */ - while (nbytes > 0) { - secmicappendbyte(pmicdata, *src++); - nbytes--; - } -} - -void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst) -{ - /* Append the minimum padding */ - secmicappendbyte(pmicdata, 0x5a); - secmicappendbyte(pmicdata, 0); - secmicappendbyte(pmicdata, 0); - secmicappendbyte(pmicdata, 0); - secmicappendbyte(pmicdata, 0); - /* and then zeroes until the length is a multiple of 4 */ - while (pmicdata->nBytesInM != 0) - secmicappendbyte(pmicdata, 0); - /* The appendByte function has already computed the result. */ - secmicputuint32(dst, pmicdata->L); - secmicputuint32(dst + 4, pmicdata->R); - /* Reset to the empty message. */ - secmicclear(pmicdata); -} - -void seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, - u8 pri) -{ - - struct mic_data micdata; - u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; - - r8712_secmicsetkey(&micdata, key); - priority[0] = pri; - /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ - if (header[1] & 1) { /* ToDS==1 */ - r8712_secmicappend(&micdata, &header[16], 6); /* DA */ - if (header[1] & 2) /* From Ds==1 */ - r8712_secmicappend(&micdata, &header[24], 6); - else - r8712_secmicappend(&micdata, &header[10], 6); - } else { /* ToDS==0 */ - r8712_secmicappend(&micdata, &header[4], 6); /* DA */ - if (header[1] & 2) /* From Ds==1 */ - r8712_secmicappend(&micdata, &header[16], 6); - else - r8712_secmicappend(&micdata, &header[10], 6); - } - r8712_secmicappend(&micdata, &priority[0], 4); - r8712_secmicappend(&micdata, data, data_len); - r8712_secgetmic(&micdata, mic_code); -} - -/* macros for extraction/creation of unsigned char/unsigned short values */ -#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) -#define Lo8(v16) ((u8)((v16) & 0x00FF)) -#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF)) -#define Lo16(v32) ((u16)((v32) & 0xFFFF)) -#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF)) -#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) - -/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) - -/* S-box lookup: 16 bits --> 16 bits */ -#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) - -/* fixed algorithm "parameters" */ -#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ -#define TA_SIZE 6 /* 48-bit transmitter address */ -#define TK_SIZE 16 /* 128-bit temporal key */ -#define P1K_SIZE 10 /* 80-bit Phase1 key */ -#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ - -/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */ -static const unsigned short Sbox1[2][256] = {/* Sbox for hash (can be in ROM) */ - { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, - }, - { /* second half is unsigned char-reversed version of first! */ - 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, - 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, - 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, - 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, - 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, - 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, - 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, - 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, - 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, - 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, - 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, - 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, - 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, - 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, - 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, - 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, - 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, - 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, - 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, - 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, - 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, - 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, - 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, - 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, - 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, - 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, - 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, - 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, - 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, - 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, - 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, - 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C, - } -}; - -/* - ********************************************************************** - * Routine: Phase 1 -- generate P1K, given TA, TK, IV32 - * - * Inputs: - * tk[] = temporal key [128 bits] - * ta[] = transmitter's MAC address [ 48 bits] - * iv32 = upper 32 bits of IV [ 32 bits] - * Output: - * p1k[] = Phase 1 key [ 80 bits] - * - * Note: - * This function only needs to be called every 2**16 packets, - * although in theory it could be called every packet. - * - ********************************************************************** - */ -static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) -{ - sint i; - - /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ - p1k[0] = Lo16(iv32); - p1k[1] = Hi16(iv32); - p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */ - p1k[3] = Mk16(ta[3], ta[2]); - p1k[4] = Mk16(ta[5], ta[4]); - /* Now compute an unbalanced Feistel cipher with 80-bit block */ - /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ - for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); - p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); - p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); - p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); - p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); - p1k[4] += (unsigned short)i; /* avoid "slide attacks" */ - } -} - -/* - ********************************************************************** - * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 - * - * Inputs: - * tk[] = Temporal key [128 bits] - * p1k[] = Phase 1 output key [ 80 bits] - * iv16 = low 16 bits of IV counter [ 16 bits] - * Output: - * rc4key[] = the key used to encrypt the packet [128 bits] - * - * Note: - * The value {TA,IV32,IV16} for Phase1/Phase2 must be unique - * across all packets using the same key TK value. Then, for a - * given value of TK[], this TKIP48 construction guarantees that - * the final RC4KEY value is unique across all packets. - * - * Suggested implementation optimization: if PPK[] is "overlaid" - * appropriately on RC4KEY[], there is no need for the final - * for loop below that copies the PPK[] result into RC4KEY[]. - * - ********************************************************************** - */ -static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) -{ - sint i; - u16 PPK[6]; /* temporary key for mixing */ - - /* Note: all adds in the PPK[] equations below are mod 2**16 */ - for (i = 0; i < 5; i++) - PPK[i] = p1k[i]; /* first, copy P1K to PPK */ - PPK[5] = p1k[4] + iv16; /* next, add in IV16 */ - /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ - PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ - PPK[1] += _S_(PPK[0] ^ TK16(1)); - PPK[2] += _S_(PPK[1] ^ TK16(2)); - PPK[3] += _S_(PPK[2] ^ TK16(3)); - PPK[4] += _S_(PPK[3] ^ TK16(4)); - PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ - /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ - PPK[0] += RotR1(PPK[5] ^ TK16(6)); - PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - /* Note: At this point, for a given key TK[0..15], the 96-bit output */ - /* value PPK[0..5] is guaranteed to be unique, as a function */ - /* of the 96-bit "input" value {TA,IV32,IV16}. That is, P1K */ - /* is now a keyed permutation of {TA,IV32,IV16}. */ - /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ - rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */ - rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ - rc4key[2] = Lo8(iv16); - rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); - /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ - for (i = 0; i < 6; i++) { - rc4key[4 + 2 * i] = Lo8(PPK[i]); - rc4key[5 + 2 * i] = Hi8(PPK[i]); - } -} - -/*The hlen isn't include the IV*/ -u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe) -{ /* exclude ICV */ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - u8 crc[4]; - struct arc4context mycontext; - u32 curfragnum, length; - - u8 *pframe, *payload, *iv, *prwskey; - union pn48 txpn; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u32 res = _SUCCESS; - - if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) - return _FAIL; - - pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET; - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt == _TKIP_) { - if (pattrib->psta) - stainfo = pattrib->psta; - else - stainfo = r8712_get_stainfo(&padapter->stapriv, - &pattrib->ra[0]); - if (stainfo) { - prwskey = &stainfo->x_UncstKey.skey[0]; - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - iv = pframe + pattrib->hdrlen; - payload = pframe + pattrib->iv_len + - pattrib->hdrlen; - GET_TKIP_PN(iv, txpn); - pnl = (u16)(txpn.val); - pnh = (u32)(txpn.val >> 16); - phase1((u16 *)&ttkey[0], prwskey, - &pattrib->ta[0], pnh); - phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], - pnl); - if ((curfragnum + 1) == pattrib->nr_frags) { - /* 4 the last fragment */ - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len; - *((__le32 *)crc) = cpu_to_le32( - getcrc32(payload, length)); - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, - payload, length); - arcfour_encrypt(&mycontext, payload + - length, crc, 4); - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len; - *((__le32 *)crc) = cpu_to_le32(getcrc32( - payload, length)); - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, - payload, length); - arcfour_encrypt(&mycontext, - payload + length, crc, - 4); - pframe += pxmitpriv->frag_len; - pframe = (u8 *)RND4((addr_t)(pframe)); - } - } - } else { - res = _FAIL; - } - } - return res; -} - -/* The hlen doesn't include the IV */ -void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) -{ /* exclude ICV */ - u16 pnl; - u32 pnh; - u8 rc4key[16]; - u8 ttkey[16]; - u8 crc[4]; - struct arc4context mycontext; - u32 length; - u8 *pframe, *payload, *iv, *prwskey, idx = 0; - union pn48 txpn; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &((union recv_frame *) - precvframe)->u.hdr.attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - pframe = (unsigned char *)((union recv_frame *) - precvframe)->u.hdr.rx_data; - /* 4 start to decrypt recvframe */ - if (prxattrib->encrypt == _TKIP_) { - stainfo = r8712_get_stainfo(&padapter->stapriv, - &prxattrib->ta[0]); - if (stainfo) { - iv = pframe + prxattrib->hdrlen; - payload = pframe + prxattrib->iv_len + - prxattrib->hdrlen; - length = ((union recv_frame *)precvframe)-> - u.hdr.len - prxattrib->hdrlen - - prxattrib->iv_len; - if (is_multicast_ether_addr(prxattrib->ra)) { - idx = iv[3]; - prwskey = &psecuritypriv->XGrpKey[ - ((idx >> 6) & 0x3) - 1].skey[0]; - if (!psecuritypriv->binstallGrpkey) - return; - } else { - prwskey = &stainfo->x_UncstKey.skey[0]; - } - GET_TKIP_PN(iv, txpn); - pnl = (u16)(txpn.val); - pnh = (u32)(txpn.val >> 16); - phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], - pnh); - phase2(&rc4key[0], prwskey, (unsigned short *) - &ttkey[0], pnl); - /* 4 decrypt payload include icv */ - arcfour_init(&mycontext, rc4key, 16); - arcfour_encrypt(&mycontext, payload, payload, length); - *((__le32 *)crc) = cpu_to_le32(getcrc32(payload, - length - 4)); - } - } -} - -/* 3 =====AES related===== */ - -#define MAX_MSG_SIZE 2048 -/*****************************/ -/******** SBOX Table *********/ -/*****************************/ - -static const u8 sbox_table[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -}; - -/****************************************/ -/* aes128k128d() */ -/* Performs a 128 bit AES encrypt with */ -/* 128 bit data. */ -/****************************************/ -static void xor_128(u8 *a, u8 *b, u8 *out) -{ - sint i; - - for (i = 0; i < 16; i++) - out[i] = a[i] ^ b[i]; -} - -static void xor_32(u8 *a, u8 *b, u8 *out) -{ - sint i; - - for (i = 0; i < 4; i++) - out[i] = a[i] ^ b[i]; -} - -static u8 sbox(u8 a) -{ - return sbox_table[(sint)a]; -} - -static void next_key(u8 *key, sint round) -{ - u8 rcon; - u8 sbox_key[4]; - static const u8 rcon_table[12] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x1b, 0x36, 0x36, 0x36 - }; - - sbox_key[0] = sbox(key[13]); - sbox_key[1] = sbox(key[14]); - sbox_key[2] = sbox(key[15]); - sbox_key[3] = sbox(key[12]); - rcon = rcon_table[round]; - xor_32(&key[0], sbox_key, &key[0]); - key[0] = key[0] ^ rcon; - xor_32(&key[4], &key[0], &key[4]); - xor_32(&key[8], &key[4], &key[8]); - xor_32(&key[12], &key[8], &key[12]); -} - -static void byte_sub(u8 *in, u8 *out) -{ - sint i; - - for (i = 0; i < 16; i++) - out[i] = sbox(in[i]); -} - -static void shift_row(u8 *in, u8 *out) -{ - out[0] = in[0]; - out[1] = in[5]; - out[2] = in[10]; - out[3] = in[15]; - out[4] = in[4]; - out[5] = in[9]; - out[6] = in[14]; - out[7] = in[3]; - out[8] = in[8]; - out[9] = in[13]; - out[10] = in[2]; - out[11] = in[7]; - out[12] = in[12]; - out[13] = in[1]; - out[14] = in[6]; - out[15] = in[11]; -} - -static void mix_column(u8 *in, u8 *out) -{ - sint i; - u8 add1b[4]; - u8 add1bf7[4]; - u8 rotl[4]; - u8 swap_halves[4]; - u8 andf7[4]; - u8 rotr[4]; - u8 temp[4]; - u8 tempb[4]; - - for (i = 0; i < 4; i++) { - if ((in[i] & 0x80) == 0x80) - add1b[i] = 0x1b; - else - add1b[i] = 0x00; - } - swap_halves[0] = in[2]; /* Swap halves */ - swap_halves[1] = in[3]; - swap_halves[2] = in[0]; - swap_halves[3] = in[1]; - rotl[0] = in[3]; /* Rotate left 8 bits */ - rotl[1] = in[0]; - rotl[2] = in[1]; - rotl[3] = in[2]; - andf7[0] = in[0] & 0x7f; - andf7[1] = in[1] & 0x7f; - andf7[2] = in[2] & 0x7f; - andf7[3] = in[3] & 0x7f; - for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ - andf7[i] = andf7[i] << 1; - if ((andf7[i - 1] & 0x80) == 0x80) - andf7[i] = (andf7[i] | 0x01); - } - andf7[0] = andf7[0] << 1; - andf7[0] = andf7[0] & 0xfe; - xor_32(add1b, andf7, add1bf7); - xor_32(in, add1bf7, rotr); - temp[0] = rotr[0]; /* Rotate right 8 bits */ - rotr[0] = rotr[1]; - rotr[1] = rotr[2]; - rotr[2] = rotr[3]; - rotr[3] = temp[0]; - xor_32(add1bf7, rotr, temp); - xor_32(swap_halves, rotl, tempb); - xor_32(temp, tempb, out); -} - -static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) -{ - sint round; - sint i; - u8 intermediatea[16]; - u8 intermediateb[16]; - u8 round_key[16]; - - for (i = 0; i < 16; i++) - round_key[i] = key[i]; - for (round = 0; round < 11; round++) { - if (round == 0) { - xor_128(round_key, data, ciphertext); - next_key(round_key, round); - } else if (round == 10) { - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - xor_128(intermediateb, round_key, ciphertext); - } else { /* 1 - 9 */ - byte_sub(ciphertext, intermediatea); - shift_row(intermediatea, intermediateb); - mix_column(&intermediateb[0], &intermediatea[0]); - mix_column(&intermediateb[4], &intermediatea[4]); - mix_column(&intermediateb[8], &intermediatea[8]); - mix_column(&intermediateb[12], &intermediatea[12]); - xor_128(intermediatea, round_key, ciphertext); - next_key(round_key, round); - } - } -} - -/************************************************/ -/* construct_mic_iv() */ -/* Builds the MIC IV from header fields and PN */ -/************************************************/ -static void construct_mic_iv(u8 *mic_iv, sint qc_exists, sint a4_exists, - u8 *mpdu, uint payload_length, u8 *pn_vector) -{ - sint i; - - mic_iv[0] = 0x59; - if (qc_exists && a4_exists) - mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ - if (qc_exists && !a4_exists) - mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ - if (!qc_exists) - mic_iv[1] = 0x00; - for (i = 2; i < 8; i++) - mic_iv[i] = mpdu[i + 8]; - for (i = 8; i < 14; i++) - mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ - mic_iv[14] = (unsigned char)(payload_length / 256); - mic_iv[15] = (unsigned char)(payload_length % 256); -} - -/************************************************/ -/* construct_mic_header1() */ -/* Builds the first MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header1(u8 *mic_header1, sint header_length, u8 *mpdu) -{ - mic_header1[0] = (u8)((header_length - 2) / 256); - mic_header1[1] = (u8)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ - /* Mute retry, more data and pwr mgt bits */ - mic_header1[3] = mpdu[1] & 0xc7; - mic_header1[4] = mpdu[4]; /* A1 */ - mic_header1[5] = mpdu[5]; - mic_header1[6] = mpdu[6]; - mic_header1[7] = mpdu[7]; - mic_header1[8] = mpdu[8]; - mic_header1[9] = mpdu[9]; - mic_header1[10] = mpdu[10]; /* A2 */ - mic_header1[11] = mpdu[11]; - mic_header1[12] = mpdu[12]; - mic_header1[13] = mpdu[13]; - mic_header1[14] = mpdu[14]; - mic_header1[15] = mpdu[15]; -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, sint a4_exists, - sint qc_exists) -{ - sint i; - - for (i = 0; i < 16; i++) - mic_header2[i] = 0x00; - mic_header2[0] = mpdu[16]; /* A3 */ - mic_header2[1] = mpdu[17]; - mic_header2[2] = mpdu[18]; - mic_header2[3] = mpdu[19]; - mic_header2[4] = mpdu[20]; - mic_header2[5] = mpdu[21]; - mic_header2[6] = 0x00; - mic_header2[7] = 0x00; /* mpdu[23]; */ - if (!qc_exists && a4_exists) - for (i = 0; i < 6; i++) - mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ - if (qc_exists && !a4_exists) { - mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ - mic_header2[9] = mpdu[25] & 0x00; - } - if (qc_exists && a4_exists) { - for (i = 0; i < 6; i++) - mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ - mic_header2[14] = mpdu[30] & 0x0f; - mic_header2[15] = mpdu[31] & 0x00; - } -} - -/************************************************/ -/* construct_mic_header2() */ -/* Builds the last MIC header block from */ -/* header fields. */ -/************************************************/ -static void construct_ctr_preload(u8 *ctr_preload, - sint a4_exists, sint qc_exists, - u8 *mpdu, u8 *pn_vector, sint c) -{ - sint i; - - for (i = 0; i < 16; i++) - ctr_preload[i] = 0x00; - i = 0; - ctr_preload[0] = 0x01; /* flag */ - if (qc_exists && a4_exists) - ctr_preload[1] = mpdu[30] & 0x0f; - if (qc_exists && !a4_exists) - ctr_preload[1] = mpdu[24] & 0x0f; - for (i = 2; i < 8; i++) - ctr_preload[i] = mpdu[i + 8]; - for (i = 8; i < 14; i++) - ctr_preload[i] = pn_vector[13 - i]; - ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */ - ctr_preload[15] = (unsigned char)(c % 256); -} - -/************************************/ -/* bitwise_xor() */ -/* A 128 bit, bitwise exclusive or */ -/************************************/ -static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) -{ - sint i; - - for (i = 0; i < 16; i++) - out[i] = ina[i] ^ inb[i]; -} - -static void aes_cipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) -{ - uint qc_exists, a4_exists, i, j, payload_remainder; - uint num_blocks, payload_index; - - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - u16 frtype = GetFrameType(pframe); - u16 frsubtype = GetFrameSubType(pframe); - - frsubtype >>= 4; - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - - if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) - a4_exists = 0; - else - a4_exists = 1; - - if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) || - (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) || - (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) { - qc_exists = 1; - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - } else if ((frsubtype == 0x08) || - (frsubtype == 0x09) || - (frsubtype == 0x0a) || - (frsubtype == 0x0b)) { - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector); - construct_mic_header1(mic_header1, hdrlen, pframe); - construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists); - payload_remainder = plen % 16; - num_blocks = plen / 16; - /* Find start of payload */ - payload_index = hdrlen + 8; - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - for (j = 0; j < 8; j++) - mic[j] = aes_out[j]; - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - pframe[payload_index + j] = mic[j]; - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - if (payload_remainder > 0) { /* If short final block, then pad it,*/ - /* encrypt and copy unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, num_blocks + 1); - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, 0); - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - pframe[payload_index++] = chain_buffer[j]; -} - -u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) -{ /* exclude ICV */ - /* Intermediate Buffers */ - sint curfragnum, length; - u8 *pframe, *prwskey; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &((struct xmit_frame *) - pxmitframe)->attrib; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u32 res = _SUCCESS; - - if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) - return _FAIL; - pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET; - /* 4 start to encrypt each fragment */ - if (pattrib->encrypt == _AES_) { - if (pattrib->psta) - stainfo = pattrib->psta; - else - stainfo = r8712_get_stainfo(&padapter->stapriv, - &pattrib->ra[0]); - if (stainfo) { - prwskey = &stainfo->x_UncstKey.skey[0]; - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len; - aes_cipher(prwskey, pattrib->hdrlen, - pframe, length); - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - pattrib->icv_len; - aes_cipher(prwskey, pattrib->hdrlen, - pframe, length); - pframe += pxmitpriv->frag_len; - pframe = (u8 *)RND4((addr_t)(pframe)); - } - } - } else { - res = _FAIL; - } - } - return res; -} - -static void aes_decipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) -{ - static u8 message[MAX_MSG_SIZE]; - uint qc_exists, a4_exists, i, j, payload_remainder; - uint num_blocks, payload_index; - u8 pn_vector[6]; - u8 mic_iv[16]; - u8 mic_header1[16]; - u8 mic_header2[16]; - u8 ctr_preload[16]; - /* Intermediate Buffers */ - u8 chain_buffer[16]; - u8 aes_out[16]; - u8 padded_buffer[16]; - u8 mic[8]; - uint frtype = GetFrameType(pframe); - uint frsubtype = GetFrameSubType(pframe); - - frsubtype >>= 4; - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); - /* start to decrypt the payload */ - /*(plen including llc, payload and mic) */ - num_blocks = (plen - 8) / 16; - payload_remainder = (plen - 8) % 16; - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) - a4_exists = 0; - else - a4_exists = 1; - if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) || - (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) || - (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) { - qc_exists = 1; - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - } else if ((frsubtype == 0x08) || - (frsubtype == 0x09) || - (frsubtype == 0x0a) || - (frsubtype == 0x0b)) { - if (hdrlen != WLAN_HDR_A3_QOS_LEN) - hdrlen += 2; - qc_exists = 1; - } else { - qc_exists = 0; - } - /* now, decrypt pframe with hdrlen offset and plen long */ - payload_index = hdrlen + 8; /* 8 is for extiv */ - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - pframe[payload_index++] = chain_buffer[j]; - } - if (payload_remainder > 0) { /* If short final block, pad it,*/ - /* encrypt it and copy the unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - pframe, pn_vector, num_blocks + 1); - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - pframe[payload_index++] = chain_buffer[j]; - } - /* start to calculate the mic */ - memcpy((void *)message, pframe, (hdrlen + plen + 8)); - pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen + 1]; - pn_vector[2] = pframe[hdrlen + 4]; - pn_vector[3] = pframe[hdrlen + 5]; - pn_vector[4] = pframe[hdrlen + 6]; - pn_vector[5] = pframe[hdrlen + 7]; - construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8, - pn_vector); - construct_mic_header1(mic_header1, hdrlen, message); - construct_mic_header2(mic_header2, message, a4_exists, qc_exists); - payload_remainder = (plen - 8) % 16; - num_blocks = (plen - 8) / 16; - /* Find start of payload */ - payload_index = hdrlen + 8; - /* Calculate MIC */ - aes128k128d(key, mic_iv, aes_out); - bitwise_xor(aes_out, mic_header1, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - bitwise_xor(aes_out, mic_header2, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - for (i = 0; i < num_blocks; i++) { - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - payload_index += 16; - aes128k128d(key, chain_buffer, aes_out); - } - /* Add on the final payload block if it needs padding */ - if (payload_remainder > 0) { - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index++]; - bitwise_xor(aes_out, padded_buffer, chain_buffer); - aes128k128d(key, chain_buffer, aes_out); - } - for (j = 0; j < 8; j++) - mic[j] = aes_out[j]; - /* Insert MIC into payload */ - for (j = 0; j < 8; j++) - message[payload_index + j] = mic[j]; - payload_index = hdrlen + 8; - for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, i + 1); - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, &message[payload_index], chain_buffer); - for (j = 0; j < 16; j++) - message[payload_index++] = chain_buffer[j]; - } - if (payload_remainder > 0) { /* If short final block, pad it,*/ - /* encrypt and copy unpadded part back */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, - message, pn_vector, num_blocks + 1); - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index + j]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < payload_remainder; j++) - message[payload_index++] = chain_buffer[j]; - } - /* Encrypt the MIC */ - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, - pn_vector, 0); - for (j = 0; j < 16; j++) - padded_buffer[j] = 0x00; - for (j = 0; j < 8; j++) - padded_buffer[j] = message[j + hdrlen + plen]; - aes128k128d(key, ctr_preload, aes_out); - bitwise_xor(aes_out, padded_buffer, chain_buffer); - for (j = 0; j < 8; j++) - message[payload_index++] = chain_buffer[j]; - /* compare the mic */ -} - -void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) -{ /* exclude ICV */ - /* Intermediate Buffers */ - sint length; - u8 *pframe, *prwskey, *iv, idx; - struct sta_info *stainfo; - struct rx_pkt_attrib *prxattrib = &((union recv_frame *) - precvframe)->u.hdr.attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - pframe = (unsigned char *)((union recv_frame *)precvframe)-> - u.hdr.rx_data; - /* 4 start to encrypt each fragment */ - if (prxattrib->encrypt == _AES_) { - stainfo = r8712_get_stainfo(&padapter->stapriv, - &prxattrib->ta[0]); - if (stainfo) { - if (is_multicast_ether_addr(prxattrib->ra)) { - iv = pframe + prxattrib->hdrlen; - idx = iv[3]; - prwskey = &psecuritypriv->XGrpKey[ - ((idx >> 6) & 0x3) - 1].skey[0]; - if (!psecuritypriv->binstallGrpkey) - return; - - } else { - prwskey = &stainfo->x_UncstKey.skey[0]; - } - length = ((union recv_frame *)precvframe)-> - u.hdr.len - prxattrib->hdrlen - - prxattrib->iv_len; - aes_decipher(prwskey, prxattrib->hdrlen, pframe, - length); - } - } -} - -void r8712_use_tkipkey_handler(struct timer_list *t) -{ - struct _adapter *padapter = - from_timer(padapter, t, securitypriv.tkip_timer); - - padapter->securitypriv.busetkipkey = true; -} diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h deleted file mode 100644 index 8461b7f05359a0d97ab7ae8ff5ad75a8ee28a3a2..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ /dev/null @@ -1,218 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __RTL871X_SECURITY_H_ -#define __RTL871X_SECURITY_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -#define _NO_PRIVACY_ 0x0 -#define _WEP40_ 0x1 -#define _TKIP_ 0x2 -#define _TKIP_WTMIC_ 0x3 -#define _AES_ 0x4 -#define _WEP104_ 0x5 - -#define _WPA_IE_ID_ 0xdd -#define _WPA2_IE_ID_ 0x30 - -#ifndef Ndis802_11AuthModeWPA2 -#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1) -#endif - -#ifndef Ndis802_11AuthModeWPA2PSK -#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2) -#endif - -union pn48 { - u64 val; -#if defined(__BIG_ENDIAN) - struct { - u8 TSC7; - u8 TSC6; - u8 TSC5; - u8 TSC4; - u8 TSC3; - u8 TSC2; - u8 TSC1; - u8 TSC0; - } _byte_; -#else - struct { - u8 TSC0; - u8 TSC1; - u8 TSC2; - u8 TSC3; - u8 TSC4; - u8 TSC5; - u8 TSC6; - u8 TSC7; - } _byte_; -#endif -}; - -union Keytype { - u8 skey[16]; - u32 lkey[4]; -}; - -struct RT_PMKID_LIST { - u8 bUsed; - u8 Bssid[6]; - u8 PMKID[16]; - u8 SsidBuf[33]; - u8 *ssid_octet; - u16 ssid_length; -}; - -struct security_priv { - u32 AuthAlgrthm; /* 802.11 auth, could be open, shared, - * 8021x and authswitch - */ - u32 PrivacyAlgrthm; /* This specify the privacy for shared - * auth. algorithm. - */ - u32 PrivacyKeyIndex; /* this is only valid for legendary - * wep, 0~3 for key id. - */ - union Keytype DefKey[4]; /* this is only valid for def. key */ - u32 DefKeylen[4]; - u32 XGrpPrivacy; /* This specify the privacy algthm. - * used for Grp key - */ - u32 XGrpKeyid; /* key id used for Grp Key */ - union Keytype XGrpKey[2]; /* 802.1x Group Key, for - * inx0 and inx1 - */ - union Keytype XGrptxmickey[2]; - union Keytype XGrprxmickey[2]; - union pn48 Grptxpn; /* PN48 used for Grp Key xmit. */ - union pn48 Grprxpn; /* PN48 used for Grp Key recv. */ - u8 wps_hw_pbc_pressed;/*for hw pbc pressed*/ - u8 wps_phase;/*for wps*/ - u8 wps_ie[MAX_WPA_IE_LEN << 2]; - int wps_ie_len; - u8 binstallGrpkey; - u8 busetkipkey; - struct timer_list tkip_timer; - u8 bcheck_grpkey; - u8 bgrpkey_handshake; - s32 sw_encrypt; /* from registry_priv */ - s32 sw_decrypt; /* from registry_priv */ - s32 hw_decrypted; /* if the rx packets is hw_decrypted==false, - * it means the hw has not been ready. - */ - u32 ndisauthtype; /* keeps the auth_type & enc_status from upper - * layer ioctl(wpa_supplicant or wzc) - */ - u32 ndisencryptstatus; - struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */ - struct NDIS_802_11_WEP ndiswep; - u8 assoc_info[600]; - u8 szofcapability[256]; /* for wpa2 usage */ - u8 oidassociation[512]; /* for wpa/wpa2 usage */ - u8 authenticator_ie[256]; /* store ap security information element */ - u8 supplicant_ie[256]; /* store sta security information element */ - /* for tkip countermeasure */ - u32 last_mic_err_time; - u8 btkip_countermeasure; - u8 btkip_wait_report; - u32 btkip_countermeasure_time; - /*------------------------------------------------------------------- - * For WPA2 Pre-Authentication. - *------------------------------------------------------------------ - **/ - struct RT_PMKID_LIST PMKIDList[NUM_PMKID_CACHE]; - u8 PMKIDIndex; -}; - -#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \ -do { \ - switch (psecuritypriv->AuthAlgrthm) { \ - case 0: \ - case 1: \ - case 3: \ - encry_algo = (u8)psecuritypriv->PrivacyAlgrthm; \ - break; \ - case 2: \ - if (bmcst) \ - encry_algo = (u8)psecuritypriv->XGrpPrivacy; \ - else \ - encry_algo = (u8)psta->XPrivacy; \ - break; \ - } \ -} while (0) -#define SET_ICE_IV_LEN(iv_len, icv_len, encrypt)\ -do {\ - switch (encrypt) { \ - case _WEP40_: \ - case _WEP104_: \ - iv_len = 4; \ - icv_len = 4; \ - break; \ - case _TKIP_: \ - iv_len = 8; \ - icv_len = 4; \ - break; \ - case _AES_: \ - iv_len = 8; \ - icv_len = 8; \ - break; \ - default: \ - iv_len = 0; \ - icv_len = 0; \ - break; \ - } \ -} while (0) -#define GET_TKIP_PN(iv, txpn) \ -do {\ - txpn._byte_.TSC0 = iv[2];\ - txpn._byte_.TSC1 = iv[0];\ - txpn._byte_.TSC2 = iv[4];\ - txpn._byte_.TSC3 = iv[5];\ - txpn._byte_.TSC4 = iv[6];\ - txpn._byte_.TSC5 = iv[7];\ -} while (0) - -#define ROL32(A, n) (((A) << (n)) | (((A) >> (32 - (n))) & ((1UL << (n)) - 1))) -#define ROR32(A, n) ROL32((A), 32 - (n)) - -struct mic_data { - u32 K0, K1; /* Key */ - u32 L, R; /* Current state */ - u32 M; /* Message accumulator (single word) */ - u32 nBytesInM; /* # bytes in M */ -}; - -void seccalctkipmic( - u8 *key, - u8 *header, - u8 *data, - u32 data_len, - u8 *Miccode, - u8 priority); - -void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key); -void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes); -void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst); -u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe); -u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe); -void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe); -void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); -void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); -void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe); -void r8712_use_tkipkey_handler(struct timer_list *t); - -#endif /*__RTL871X_SECURITY_H_ */ - diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c deleted file mode 100644 index 2c806a0105bf6c7cf0b02079ea377e9c851e5ec8..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_sta_mgt.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_STA_MGT_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "xmit_osdep.h" -#include "sta_info.h" - -static void _init_stainfo(struct sta_info *psta) -{ - memset((u8 *)psta, 0, sizeof(struct sta_info)); - spin_lock_init(&psta->lock); - INIT_LIST_HEAD(&psta->list); - INIT_LIST_HEAD(&psta->hash_list); - _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); - _r8712_init_sta_recv_priv(&psta->sta_recvpriv); - INIT_LIST_HEAD(&psta->asoc_list); - INIT_LIST_HEAD(&psta->auth_list); -} - -int _r8712_init_sta_priv(struct sta_priv *pstapriv) -{ - struct sta_info *psta; - s32 i; - - pstapriv->pallocated_stainfo_buf = kmalloc(sizeof(struct sta_info) * - NUM_STA + 4, GFP_ATOMIC); - if (!pstapriv->pallocated_stainfo_buf) - return -ENOMEM; - pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 - - ((addr_t)(pstapriv->pallocated_stainfo_buf) & 3); - _init_queue(&pstapriv->free_sta_queue); - spin_lock_init(&pstapriv->sta_hash_lock); - pstapriv->asoc_sta_count = 0; - _init_queue(&pstapriv->sleep_q); - _init_queue(&pstapriv->wakeup_q); - psta = (struct sta_info *)(pstapriv->pstainfo_buf); - for (i = 0; i < NUM_STA; i++) { - _init_stainfo(psta); - INIT_LIST_HEAD(&(pstapriv->sta_hash[i])); - list_add_tail(&psta->list, &pstapriv->free_sta_queue.queue); - psta++; - } - INIT_LIST_HEAD(&pstapriv->asoc_list); - INIT_LIST_HEAD(&pstapriv->auth_list); - return 0; -} - -/* this function is used to free the memory of lock || sema for all stainfos */ -static void mfree_all_stainfo(struct sta_priv *pstapriv) -{ - unsigned long irqL; - struct list_head *plist, *phead; - - spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); - phead = &pstapriv->free_sta_queue.queue; - plist = phead->next; - while (!end_of_queue_search(phead, plist)) - plist = plist->next; - - spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); -} - -void _r8712_free_sta_priv(struct sta_priv *pstapriv) -{ - if (pstapriv) { - /* be done before free sta_hash_lock */ - mfree_all_stainfo(pstapriv); - kfree(pstapriv->pallocated_stainfo_buf); - } -} - -struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) -{ - s32 index; - struct list_head *phash_list; - struct sta_info *psta; - struct __queue *pfree_sta_queue; - struct recv_reorder_ctrl *preorder_ctrl; - int i = 0; - u16 wRxSeqInitialValue = 0xffff; - unsigned long flags; - - pfree_sta_queue = &pstapriv->free_sta_queue; - spin_lock_irqsave(&pfree_sta_queue->lock, flags); - psta = list_first_entry_or_null(&pfree_sta_queue->queue, - struct sta_info, list); - if (psta) { - list_del_init(&psta->list); - _init_stainfo(psta); - memcpy(psta->hwaddr, hwaddr, ETH_ALEN); - index = wifi_mac_hash(hwaddr); - if (index >= NUM_STA) { - psta = NULL; - goto exit; - } - phash_list = &pstapriv->sta_hash[index]; - list_add_tail(&psta->hash_list, phash_list); - pstapriv->asoc_sta_count++; - -/* For the SMC router, the sequence number of first packet of WPS handshake - * will be 0. In this case, this packet will be dropped by recv_decache function - * if we use the 0x00 as the default value for tid_rxseq variable. So, we - * initialize the tid_rxseq variable as the 0xffff. - */ - for (i = 0; i < 16; i++) - memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], - &wRxSeqInitialValue, 2); - /* for A-MPDU Rx reordering buffer control */ - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - preorder_ctrl->padapter = pstapriv->padapter; - preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->wend_b = 0xffff; - preorder_ctrl->wsize_b = 64; - _init_queue(&preorder_ctrl->pending_recvframe_queue); - r8712_init_recv_timer(preorder_ctrl); - } - } -exit: - spin_unlock_irqrestore(&pfree_sta_queue->lock, flags); - return psta; -} - -/* using pstapriv->sta_hash_lock to protect */ -void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta) -{ - int i; - unsigned long irqL0; - struct __queue *pfree_sta_queue; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_xmit_priv *pstaxmitpriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - if (!psta) - return; - pfree_sta_queue = &pstapriv->free_sta_queue; - pstaxmitpriv = &psta->sta_xmitpriv; - spin_lock_irqsave(&(pxmitpriv->vo_pending.lock), irqL0); - r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&(pstaxmitpriv->vo_q.tx_pending)); - spin_unlock_irqrestore(&(pxmitpriv->vo_pending.lock), irqL0); - spin_lock_irqsave(&(pxmitpriv->vi_pending.lock), irqL0); - r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&(pstaxmitpriv->vi_q.tx_pending)); - spin_unlock_irqrestore(&(pxmitpriv->vi_pending.lock), irqL0); - spin_lock_irqsave(&(pxmitpriv->bk_pending.lock), irqL0); - r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&(pstaxmitpriv->bk_q.tx_pending)); - spin_unlock_irqrestore(&(pxmitpriv->bk_pending.lock), irqL0); - spin_lock_irqsave(&(pxmitpriv->be_pending.lock), irqL0); - r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); - list_del_init(&(pstaxmitpriv->be_q.tx_pending)); - spin_unlock_irqrestore(&(pxmitpriv->be_pending.lock), irqL0); - list_del_init(&psta->hash_list); - pstapriv->asoc_sta_count--; - /* re-init sta_info; 20061114 */ - _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); - _r8712_init_sta_recv_priv(&psta->sta_recvpriv); - /* for A-MPDU Rx reordering buffer control, - * cancel reordering_ctrl_timer - */ - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - del_timer(&preorder_ctrl->reordering_ctrl_timer); - } - spin_lock(&(pfree_sta_queue->lock)); - /* insert into free_sta_queue; 20061114 */ - list_add_tail(&psta->list, &pfree_sta_queue->queue); - spin_unlock(&(pfree_sta_queue->lock)); -} - -/* free all stainfo which in sta_hash[all] */ -void r8712_free_all_stainfo(struct _adapter *padapter) -{ - unsigned long irqL; - struct list_head *plist, *phead; - s32 index; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *pbcmc_stainfo = r8712_get_bcmc_stainfo(padapter); - - if (pstapriv->asoc_sta_count == 1) - return; - spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); - for (index = 0; index < NUM_STA; index++) { - phead = &(pstapriv->sta_hash[index]); - plist = phead->next; - while (!end_of_queue_search(phead, plist)) { - psta = container_of(plist, - struct sta_info, hash_list); - plist = plist->next; - if (pbcmc_stainfo != psta) - r8712_free_stainfo(padapter, psta); - } - } - spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); -} - -/* any station allocated can be searched by hash list */ -struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) -{ - unsigned long irqL; - struct list_head *plist, *phead; - struct sta_info *psta = NULL; - u32 index; - - if (!hwaddr) - return NULL; - index = wifi_mac_hash(hwaddr); - spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); - phead = &(pstapriv->sta_hash[index]); - plist = phead->next; - while (!end_of_queue_search(phead, plist)) { - psta = container_of(plist, struct sta_info, hash_list); - if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) { - /* if found the matched address */ - break; - } - psta = NULL; - plist = plist->next; - } - spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); - return psta; -} - -void r8712_init_bcmc_stainfo(struct _adapter *padapter) -{ - unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - struct sta_priv *pstapriv = &padapter->stapriv; - - r8712_alloc_stainfo(pstapriv, bcast_addr); -} - -struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - return r8712_get_stainfo(pstapriv, bc_addr); -} - -u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr) -{ - return true; -} diff --git a/drivers/staging/rtl8712/rtl871x_wlan_sme.h b/drivers/staging/rtl8712/rtl871x_wlan_sme.h deleted file mode 100644 index 97ea1451426c05c6c675c3b8c14f880c8ff0691c..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_wlan_sme.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871X_WLAN_SME_H_ -#define _RTL871X_WLAN_SME_H_ - -#define MSR_APMODE 0x0C -#define MSR_STAMODE 0x08 -#define MSR_ADHOCMODE 0x04 -#define MSR_NOLINKMODE 0x00 -#define _1M_RATE_ 0 -#define _2M_RATE_ 1 -#define _5M_RATE_ 2 -#define _11M_RATE_ 3 -#define _6M_RATE_ 4 -#define _9M_RATE_ 5 -#define _12M_RATE_ 6 -#define _18M_RATE_ 7 -#define _24M_RATE_ 8 -#define _36M_RATE_ 9 -#define _48M_RATE_ 10 -#define _54M_RATE_ 11 - -#endif - diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c deleted file mode 100644 index 408616e9afcfffe134e2da881cac587ae6e2b0f3..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ /dev/null @@ -1,1056 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * rtl871x_xmit.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _RTL871X_XMIT_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" -#include "usb_ops.h" - -#include <linux/usb.h> -#include <linux/ieee80211.h> - -static const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8}; -static const u8 RFC1042_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0x00}; -static void init_hwxmits(struct hw_xmit *phwxmit, sint entry); -static void alloc_hwxmits(struct _adapter *padapter); -static void free_hwxmits(struct _adapter *padapter); - -static void _init_txservq(struct tx_servq *ptxservq) -{ - INIT_LIST_HEAD(&ptxservq->tx_pending); - _init_queue(&ptxservq->sta_pending); - ptxservq->qcnt = 0; -} - -void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) -{ - memset((unsigned char *)psta_xmitpriv, 0, - sizeof(struct sta_xmit_priv)); - spin_lock_init(&psta_xmitpriv->lock); - _init_txservq(&psta_xmitpriv->be_q); - _init_txservq(&psta_xmitpriv->bk_q); - _init_txservq(&psta_xmitpriv->vi_q); - _init_txservq(&psta_xmitpriv->vo_q); - INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz); - INIT_LIST_HEAD(&psta_xmitpriv->apsd); -} - -int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter) -{ - sint i; - struct xmit_buf *pxmitbuf; - struct xmit_frame *pxframe; - int j; - - memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv)); - spin_lock_init(&pxmitpriv->lock); - /* - *Please insert all the queue initialization using _init_queue below - */ - pxmitpriv->adapter = padapter; - _init_queue(&pxmitpriv->be_pending); - _init_queue(&pxmitpriv->bk_pending); - _init_queue(&pxmitpriv->vi_pending); - _init_queue(&pxmitpriv->vo_pending); - _init_queue(&pxmitpriv->bm_pending); - _init_queue(&pxmitpriv->legacy_dz_queue); - _init_queue(&pxmitpriv->apsd_queue); - _init_queue(&pxmitpriv->free_xmit_queue); - /* - * Please allocate memory with sz = (struct xmit_frame) * NR_XMITFRAME, - * and initialize free_xmit_frame below. - * Please also apply free_txobj to link_up all the xmit_frames... - */ - pxmitpriv->pallocated_frame_buf = - kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4, - GFP_ATOMIC); - if (!pxmitpriv->pallocated_frame_buf) { - pxmitpriv->pxmit_frame_buf = NULL; - return -ENOMEM; - } - pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - - ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3); - pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf; - for (i = 0; i < NR_XMITFRAME; i++) { - INIT_LIST_HEAD(&(pxframe->list)); - pxframe->padapter = padapter; - pxframe->frame_tag = DATA_FRAMETAG; - pxframe->pkt = NULL; - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - list_add_tail(&(pxframe->list), - &(pxmitpriv->free_xmit_queue.queue)); - pxframe++; - } - pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME; - /* - * init xmit hw_txqueue - */ - _r8712_init_hw_txqueue(&pxmitpriv->be_txqueue, BE_QUEUE_INX); - _r8712_init_hw_txqueue(&pxmitpriv->bk_txqueue, BK_QUEUE_INX); - _r8712_init_hw_txqueue(&pxmitpriv->vi_txqueue, VI_QUEUE_INX); - _r8712_init_hw_txqueue(&pxmitpriv->vo_txqueue, VO_QUEUE_INX); - _r8712_init_hw_txqueue(&pxmitpriv->bmc_txqueue, BMC_QUEUE_INX); - pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; - pxmitpriv->txirp_cnt = 1; - /*per AC pending irp*/ - pxmitpriv->beq_cnt = 0; - pxmitpriv->bkq_cnt = 0; - pxmitpriv->viq_cnt = 0; - pxmitpriv->voq_cnt = 0; - /*init xmit_buf*/ - _init_queue(&pxmitpriv->free_xmitbuf_queue); - _init_queue(&pxmitpriv->pending_xmitbuf_queue); - pxmitpriv->pxmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf), GFP_ATOMIC); - if (!pxmitpriv->pxmitbuf) - goto clean_up_frame_buf; - pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; - for (i = 0; i < NR_XMITBUFF; i++) { - INIT_LIST_HEAD(&pxmitbuf->list); - pxmitbuf->pallocated_buf = - kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC); - if (!pxmitbuf->pallocated_buf) { - j = 0; - goto clean_up_alloc_buf; - } - pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ - - ((addr_t) (pxmitbuf->pallocated_buf) & - (XMITBUF_ALIGN_SZ - 1)); - if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) { - j = 1; - goto clean_up_alloc_buf; - } - list_add_tail(&pxmitbuf->list, - &(pxmitpriv->free_xmitbuf_queue.queue)); - pxmitbuf++; - } - pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF; - INIT_WORK(&padapter->wk_filter_rx_ff0, r8712_SetFilter); - alloc_hwxmits(padapter); - init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); - tasklet_setup(&pxmitpriv->xmit_tasklet, r8712_xmit_bh); - return 0; - -clean_up_alloc_buf: - if (j) { - /* failure happened in r8712_xmit_resource_alloc() - * delete extra pxmitbuf->pallocated_buf - */ - kfree(pxmitbuf->pallocated_buf); - } - for (j = 0; j < i; j++) { - int k; - - pxmitbuf--; /* reset pointer */ - kfree(pxmitbuf->pallocated_buf); - for (k = 0; k < 8; k++) /* delete xmit urb's */ - usb_free_urb(pxmitbuf->pxmit_urb[k]); - } - kfree(pxmitpriv->pxmitbuf); - pxmitpriv->pxmitbuf = NULL; -clean_up_frame_buf: - kfree(pxmitpriv->pallocated_frame_buf); - pxmitpriv->pallocated_frame_buf = NULL; - return -ENOMEM; -} - -void _free_xmit_priv(struct xmit_priv *pxmitpriv) -{ - int i; - struct _adapter *padapter = pxmitpriv->adapter; - struct xmit_frame *pxmitframe = (struct xmit_frame *) - pxmitpriv->pxmit_frame_buf; - struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; - - if (!pxmitpriv->pxmit_frame_buf) - return; - for (i = 0; i < NR_XMITFRAME; i++) { - r8712_xmit_complete(padapter, pxmitframe); - pxmitframe++; - } - for (i = 0; i < NR_XMITBUFF; i++) { - r8712_xmit_resource_free(padapter, pxmitbuf); - kfree(pxmitbuf->pallocated_buf); - pxmitbuf++; - } - kfree(pxmitpriv->pallocated_frame_buf); - kfree(pxmitpriv->pxmitbuf); - free_hwxmits(padapter); -} - -int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib) -{ - struct pkt_file pktfile; - struct sta_info *psta = NULL; - struct ethhdr etherhdr; - - struct tx_cmd txdesc; - - bool bmcast; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - - _r8712_open_pktfile(pkt, &pktfile); - - _r8712_pktfile_read(&pktfile, (unsigned char *)ðerhdr, ETH_HLEN); - - pattrib->ether_type = ntohs(etherhdr.h_proto); - - /* - * If driver xmit ARP packet, driver can set ps mode to initial - * setting. It stands for getting DHCP or fix IP. - */ - if (pattrib->ether_type == 0x0806) { - if (padapter->pwrctrlpriv.pwr_mode != - padapter->registrypriv.power_mgnt) { - del_timer_sync(&pmlmepriv->dhcp_timer); - r8712_set_ps_mode(padapter, - padapter->registrypriv.power_mgnt, - padapter->registrypriv.smart_ps); - } - } - - memcpy(pattrib->dst, ðerhdr.h_dest, ETH_ALEN); - memcpy(pattrib->src, ðerhdr.h_source, ETH_ALEN); - pattrib->pctrl = 0; - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN); - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - /*firstly, filter packet not belongs to mp*/ - if (pattrib->ether_type != 0x8712) - return -EINVAL; - /* for mp storing the txcmd per packet, - * according to the info of txcmd to update pattrib - */ - /*get MP_TXDESC_SIZE bytes txcmd per packet*/ - _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE); - memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); - memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - pattrib->pctrl = 1; - } - /* r8712_xmitframe_coalesce() overwrite this!*/ - pattrib->pktlen = pktfile.pkt_len; - if (pattrib->ether_type == ETH_P_IP) { - /* The following is for DHCP and ARP packet, we use cck1M to - * tx these packets and let LPS awake some time - * to prevent DHCP protocol fail - */ - u8 tmp[24]; - - _r8712_pktfile_read(&pktfile, &tmp[0], 24); - pattrib->dhcp_pkt = 0; - if (pktfile.pkt_len > 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/ - if (pattrib->ether_type == ETH_P_IP) {/* IP header*/ - if (((tmp[21] == 68) && (tmp[23] == 67)) || - ((tmp[21] == 67) && (tmp[23] == 68))) { - /* 68 : UDP BOOTP client - * 67 : UDP BOOTP server - * Use low rate to send DHCP packet. - */ - pattrib->dhcp_pkt = 1; - } - } - } - } - bmcast = is_multicast_ether_addr(pattrib->ra); - /* get sta_info*/ - if (bmcast) { - psta = r8712_get_bcmc_stainfo(padapter); - pattrib->mac_id = 4; - } else { - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - psta = r8712_get_stainfo(pstapriv, - get_bssid(pmlmepriv)); - pattrib->mac_id = 5; - } else { - psta = r8712_get_stainfo(pstapriv, pattrib->ra); - if (!psta) /* drop the pkt */ - return -ENOMEM; - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - pattrib->mac_id = 5; - else - pattrib->mac_id = psta->mac_id; - } - } - - if (psta) { - pattrib->psta = psta; - } else { - /* if we cannot get psta => drrp the pkt */ - return -ENOMEM; - } - - pattrib->ack_policy = 0; - /* get ether_hdr_len */ - pattrib->pkt_hdrlen = ETH_HLEN; - - if (pqospriv->qos_option) { - r8712_set_qos(&pktfile, pattrib); - } else { - pattrib->hdrlen = WLAN_HDR_A3_LEN; - pattrib->subtype = IEEE80211_FTYPE_DATA; - pattrib->priority = 0; - } - if (psta->ieee8021x_blocked) { - pattrib->encrypt = 0; - if ((pattrib->ether_type != 0x888e) && - !check_fwstate(pmlmepriv, WIFI_MP_STATE)) - return -EINVAL; - } else { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - } - switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - pattrib->iv_len = 4; - pattrib->icv_len = 4; - break; - case _TKIP_: - pattrib->iv_len = 8; - pattrib->icv_len = 4; - if (padapter->securitypriv.busetkipkey == _FAIL) - return -EINVAL; - break; - case _AES_: - pattrib->iv_len = 8; - pattrib->icv_len = 8; - break; - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - if (pattrib->encrypt && - (padapter->securitypriv.sw_encrypt || - !psecuritypriv->hw_decrypted)) - pattrib->bswenc = true; - else - pattrib->bswenc = false; - /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite - * some settings above. - */ - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) - pattrib->priority = - (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f; - return 0; -} - -static int xmitframe_addmic(struct _adapter *padapter, - struct xmit_frame *pxmitframe) -{ - u32 curfragnum, length; - u8 *pframe, *payload, mic[8]; - struct mic_data micdata; - struct sta_info *stainfo; - struct qos_priv *pqospriv = &(padapter->mlmepriv.qospriv); - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecpriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - u8 priority[4] = {}; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) - stainfo = pattrib->psta; - else - stainfo = r8712_get_stainfo(&padapter->stapriv, - &pattrib->ra[0]); - if (pattrib->encrypt == _TKIP_) { - /*encode mic code*/ - if (stainfo) { - u8 null_key[16] = {}; - - pframe = pxmitframe->buf_addr + TXDESC_OFFSET; - if (bmcst) { - if (!memcmp(psecpriv->XGrptxmickey - [psecpriv->XGrpKeyid].skey, - null_key, 16)) - return -ENOMEM; - /*start to calculate the mic code*/ - r8712_secmicsetkey(&micdata, - psecpriv->XGrptxmickey - [psecpriv->XGrpKeyid].skey); - } else { - if (!memcmp(&stainfo->tkiptxmickey.skey[0], - null_key, 16)) - return -ENOMEM; - /* start to calculate the mic code */ - r8712_secmicsetkey(&micdata, - &stainfo->tkiptxmickey.skey[0]); - } - if (pframe[1] & 1) { /* ToDS==1 */ - r8712_secmicappend(&micdata, - &pframe[16], 6); /*DA*/ - if (pframe[1] & 2) /* From Ds==1 */ - r8712_secmicappend(&micdata, - &pframe[24], 6); - else - r8712_secmicappend(&micdata, - &pframe[10], 6); - } else { /* ToDS==0 */ - r8712_secmicappend(&micdata, - &pframe[4], 6); /* DA */ - if (pframe[1] & 2) /* From Ds==1 */ - r8712_secmicappend(&micdata, - &pframe[16], 6); - else - r8712_secmicappend(&micdata, - &pframe[10], 6); - } - if (pqospriv->qos_option == 1) - priority[0] = (u8)pxmitframe->attrib.priority; - r8712_secmicappend(&micdata, &priority[0], 4); - payload = pframe; - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - payload = (u8 *)RND4((addr_t)(payload)); - payload += pattrib->hdrlen + pattrib->iv_len; - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - ((psecpriv->sw_encrypt) - ? pattrib->icv_len : 0); - r8712_secmicappend(&micdata, payload, - length); - payload = payload + length; - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - pattrib->iv_len - - ((psecpriv->sw_encrypt) ? - pattrib->icv_len : 0); - r8712_secmicappend(&micdata, payload, - length); - payload = payload + length + - pattrib->icv_len; - } - } - r8712_secgetmic(&micdata, &(mic[0])); - /* add mic code and add the mic code length in - * last_txcmdsz - */ - memcpy(payload, &(mic[0]), 8); - pattrib->last_txcmdsz += 8; - payload = payload - pattrib->last_txcmdsz + 8; - } - } - return 0; -} - -static sint xmitframe_swencrypt(struct _adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - if (pattrib->bswenc) { - switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - r8712_wep_encrypt(padapter, (u8 *)pxmitframe); - break; - case _TKIP_: - r8712_tkip_encrypt(padapter, (u8 *)pxmitframe); - break; - case _AES_: - r8712_aes_encrypt(padapter, (u8 *)pxmitframe); - break; - default: - break; - } - } - return _SUCCESS; -} - -static int make_wlanhdr(struct _adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) -{ - u16 *qc; - - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv = &pmlmepriv->qospriv; - __le16 *fctrl = &pwlanhdr->frame_control; - u8 *bssid; - - memset(hdr, 0, WLANHDR_OFFSET); - SetFrameSubType(fctrl, pattrib->subtype); - if (!(pattrib->subtype & IEEE80211_FTYPE_DATA)) - return 0; - - bssid = get_bssid(pmlmepriv); - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* to_ds = 1, fr_ds = 0; */ - SetToDs(fctrl); - ether_addr_copy(pwlanhdr->addr1, bssid); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, pattrib->dst); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* to_ds = 0, fr_ds = 1; */ - SetFrDs(fctrl); - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, bssid); - ether_addr_copy(pwlanhdr->addr3, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, bssid); - } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, bssid); - } else { - return -EINVAL; - } - - if (pattrib->encrypt) - SetPrivacy(fctrl); - if (pqospriv->qos_option) { - qc = (unsigned short *)(hdr + pattrib->hdrlen - 2); - if (pattrib->priority) - SetPriority(qc, pattrib->priority); - SetAckpolicy(qc, pattrib->ack_policy); - } - /* TODO: fill HT Control Field */ - /* Update Seq Num will be handled by f/w */ - { - struct sta_info *psta; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) - psta = pattrib->psta; - else if (bmcst) - psta = r8712_get_bcmc_stainfo(padapter); - else - psta = r8712_get_stainfo(&padapter->stapriv, - pattrib->ra); - - if (psta) { - u16 *txtid = psta->sta_xmitpriv.txseq_tid; - - txtid[pattrib->priority]++; - txtid[pattrib->priority] &= 0xFFF; - pattrib->seqnum = txtid[pattrib->priority]; - SetSeqNum(hdr, pattrib->seqnum); - } - } - - return 0; -} - -static sint r8712_put_snap(u8 *data, u16 h_proto) -{ - struct ieee80211_snap_hdr *snap; - const u8 *oui; - - snap = (struct ieee80211_snap_hdr *)data; - snap->dsap = 0xaa; - snap->ssap = 0xaa; - snap->ctrl = 0x03; - if (h_proto == 0x8137 || h_proto == 0x80f3) - oui = P802_1H_OUI; - else - oui = RFC1042_OUI; - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; - *(__be16 *)(data + SNAP_SIZE) = htons(h_proto); - return SNAP_SIZE + sizeof(u16); -} - -/* - * This sub-routine will perform all the following: - * 1. remove 802.3 header. - * 2. create wlan_header, based on the info in pxmitframe - * 3. append sta's iv/ext-iv - * 4. append LLC - * 5. move frag chunk from pframe to pxmitframe->mem - * 6. apply sw-encrypt, if necessary. - */ -sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, - struct xmit_frame *pxmitframe) -{ - struct pkt_file pktfile; - - sint frg_len, mpdu_len, llc_sz; - u32 mem_sz; - u8 frg_inx; - addr_t addr; - u8 *pframe, *mem_start, *ptxdesc; - struct sta_info *psta; - struct security_priv *psecpriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - u8 *pbuf_start; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - - if (!pattrib->psta) - return _FAIL; - psta = pattrib->psta; - if (!pxmitframe->buf_addr) - return _FAIL; - pbuf_start = pxmitframe->buf_addr; - ptxdesc = pbuf_start; - mem_start = pbuf_start + TXDESC_OFFSET; - if (make_wlanhdr(padapter, mem_start, pattrib)) - return _FAIL; - _r8712_open_pktfile(pkt, &pktfile); - _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen); - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - /* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */ - if (pattrib->ether_type == 0x8712) { - /* take care - update_txdesc overwrite this */ - _r8712_pktfile_read(&pktfile, ptxdesc, TXDESC_SIZE); - } - } - pattrib->pktlen = pktfile.pkt_len; - frg_inx = 0; - frg_len = pxmitpriv->frag_len - 4; - while (1) { - llc_sz = 0; - mpdu_len = frg_len; - pframe = mem_start; - SetMFrag(mem_start); - pframe += pattrib->hdrlen; - mpdu_len -= pattrib->hdrlen; - /* adding icv, if necessary...*/ - if (pattrib->iv_len) { - if (psta) { - switch (pattrib->encrypt) { - case _WEP40_: - case _WEP104_: - WEP_IV(pattrib->iv, psta->txpn, - (u8)psecpriv->PrivacyKeyIndex); - break; - case _TKIP_: - if (bmcst) - TKIP_IV(pattrib->iv, - psta->txpn, - (u8)psecpriv->XGrpKeyid); - else - TKIP_IV(pattrib->iv, psta->txpn, - 0); - break; - case _AES_: - if (bmcst) - AES_IV(pattrib->iv, psta->txpn, - (u8)psecpriv->XGrpKeyid); - else - AES_IV(pattrib->iv, psta->txpn, - 0); - break; - } - } - memcpy(pframe, pattrib->iv, pattrib->iv_len); - pframe += pattrib->iv_len; - mpdu_len -= pattrib->iv_len; - } - if (frg_inx == 0) { - llc_sz = r8712_put_snap(pframe, pattrib->ether_type); - pframe += llc_sz; - mpdu_len -= llc_sz; - } - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) - mpdu_len -= pattrib->icv_len; - if (bmcst) - mem_sz = _r8712_pktfile_read(&pktfile, pframe, - pattrib->pktlen); - else - mem_sz = _r8712_pktfile_read(&pktfile, pframe, - mpdu_len); - pframe += mem_sz; - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) { - memcpy(pframe, pattrib->icv, pattrib->icv_len); - pframe += pattrib->icv_len; - } - frg_inx++; - if (bmcst || r8712_endofpktfile(&pktfile)) { - pattrib->nr_frags = frg_inx; - pattrib->last_txcmdsz = pattrib->hdrlen + - pattrib->iv_len + - ((pattrib->nr_frags == 1) ? - llc_sz : 0) + - ((pattrib->bswenc) ? - pattrib->icv_len : 0) + mem_sz; - ClearMFrag(mem_start); - break; - } - addr = (addr_t)(pframe); - mem_start = (unsigned char *)RND4(addr) + TXDESC_OFFSET; - memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen); - } - - if (xmitframe_addmic(padapter, pxmitframe)) - return _FAIL; - xmitframe_swencrypt(padapter, pxmitframe); - return _SUCCESS; -} - -void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len) -{ - uint protection; - u8 *perp; - uint erp_len; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - - switch (pxmitpriv->vcs_setting) { - case DISABLE_VCS: - pxmitpriv->vcs = NONE_VCS; - break; - case ENABLE_VCS: - break; - case AUTO_VCS: - default: - perp = r8712_get_ie(ie, WLAN_EID_ERP_INFO, &erp_len, ie_len); - if (!perp) { - pxmitpriv->vcs = NONE_VCS; - } else { - protection = (*(perp + 2)) & BIT(1); - if (protection) { - if (pregistrypriv->vcs_type == RTS_CTS) - pxmitpriv->vcs = RTS_CTS; - else - pxmitpriv->vcs = CTS_TO_SELF; - } else { - pxmitpriv->vcs = NONE_VCS; - } - } - break; - } -} - -struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf; - struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue, - struct xmit_buf, list); - if (pxmitbuf) { - list_del_init(&pxmitbuf->list); - pxmitpriv->free_xmitbuf_cnt--; - } - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - return pxmitbuf; -} - -void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - if (!pxmitbuf) - return; - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - list_del_init(&pxmitbuf->list); - list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue); - pxmitpriv->free_xmitbuf_cnt++; - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); -} - -/* - * Calling context: - * 1. OS_TXENTRY - * 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - * - * If we turn on USE_RXTHREAD, then, no need for critical section. - * Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - * - * Must be very very cautious... - * - */ -struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv) -{ - /* - * Please remember to use all the osdep_service api, - * and lock/unlock or _enter/_exit critical to protect - * pfree_xmit_queue - */ - unsigned long irqL; - struct xmit_frame *pxframe; - struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - - spin_lock_irqsave(&pfree_xmit_queue->lock, irqL); - pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, - struct xmit_frame, list); - if (pxframe) { - list_del_init(&pxframe->list); - pxmitpriv->free_xmitframe_cnt--; - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - pxframe->attrib.psta = NULL; - pxframe->pkt = NULL; - } - spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL); - return pxframe; -} - -void r8712_free_xmitframe(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe) -{ - unsigned long irqL; - struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - struct _adapter *padapter = pxmitpriv->adapter; - - if (!pxmitframe) - return; - spin_lock_irqsave(&pfree_xmit_queue->lock, irqL); - list_del_init(&pxmitframe->list); - if (pxmitframe->pkt) - pxmitframe->pkt = NULL; - list_add_tail(&pxmitframe->list, &pfree_xmit_queue->queue); - pxmitpriv->free_xmitframe_cnt++; - spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL); - if (netif_queue_stopped(padapter->pnetdev)) - netif_wake_queue(padapter->pnetdev); -} - -void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe) -{ - if (!pxmitframe) - return; - if (pxmitframe->frame_tag == DATA_FRAMETAG) - r8712_free_xmitframe(pxmitpriv, pxmitframe); -} - -void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv, - struct __queue *pframequeue) -{ - unsigned long irqL; - struct list_head *plist, *phead; - struct xmit_frame *pxmitframe; - - spin_lock_irqsave(&(pframequeue->lock), irqL); - phead = &pframequeue->queue; - plist = phead->next; - while (!end_of_queue_search(phead, plist)) { - pxmitframe = container_of(plist, struct xmit_frame, list); - plist = plist->next; - r8712_free_xmitframe(pxmitpriv, pxmitframe); - } - spin_unlock_irqrestore(&(pframequeue->lock), irqL); -} - -static inline struct tx_servq *get_sta_pending(struct _adapter *padapter, - struct __queue **ppstapending, - struct sta_info *psta, sint up) -{ - struct tx_servq *ptxservq; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - - switch (up) { - case 1: - case 2: - ptxservq = &(psta->sta_xmitpriv.bk_q); - *ppstapending = &padapter->xmitpriv.bk_pending; - (phwxmits + 3)->accnt++; - break; - case 4: - case 5: - ptxservq = &(psta->sta_xmitpriv.vi_q); - *ppstapending = &padapter->xmitpriv.vi_pending; - (phwxmits + 1)->accnt++; - break; - case 6: - case 7: - ptxservq = &(psta->sta_xmitpriv.vo_q); - *ppstapending = &padapter->xmitpriv.vo_pending; - (phwxmits + 0)->accnt++; - break; - case 0: - case 3: - default: - ptxservq = &(psta->sta_xmitpriv.be_q); - *ppstapending = &padapter->xmitpriv.be_pending; - (phwxmits + 2)->accnt++; - break; - } - return ptxservq; -} - -/* - * Will enqueue pxmitframe to the proper queue, and indicate it - * to xx_pending list..... - */ -int r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe) -{ - unsigned long irqL0; - struct __queue *pstapending; - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - bool bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - if (bmcst) { - psta = r8712_get_bcmc_stainfo(padapter); - } else { - if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) - psta = r8712_get_stainfo(pstapriv, - get_bssid(pmlmepriv)); - else - psta = r8712_get_stainfo(pstapriv, pattrib->ra); - } - } - if (!psta) - return -EINVAL; - ptxservq = get_sta_pending(padapter, &pstapending, - psta, pattrib->priority); - spin_lock_irqsave(&pstapending->lock, irqL0); - if (list_empty(&ptxservq->tx_pending)) - list_add_tail(&ptxservq->tx_pending, &pstapending->queue); - list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue); - ptxservq->qcnt++; - spin_unlock_irqrestore(&pstapending->lock, irqL0); - return 0; -} - -static void alloc_hwxmits(struct _adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pxmitpriv->hwxmit_entry = HWXMIT_ENTRY; - pxmitpriv->hwxmits = kmalloc_array(pxmitpriv->hwxmit_entry, - sizeof(struct hw_xmit), GFP_ATOMIC); - if (!pxmitpriv->hwxmits) - return; - hwxmits = pxmitpriv->hwxmits; - if (pxmitpriv->hwxmit_entry == 5) { - pxmitpriv->bmc_txqueue.head = 0; - hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; - hwxmits[0] .sta_queue = &pxmitpriv->bm_pending; - pxmitpriv->vo_txqueue.head = 0; - hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; - hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - pxmitpriv->vi_txqueue.head = 0; - hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; - hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; - pxmitpriv->bk_txqueue.head = 0; - hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - pxmitpriv->be_txqueue.head = 0; - hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; - hwxmits[4] .sta_queue = &pxmitpriv->be_pending; - } else if (pxmitpriv->hwxmit_entry == 4) { - pxmitpriv->vo_txqueue.head = 0; - hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; - hwxmits[0] .sta_queue = &pxmitpriv->vo_pending; - pxmitpriv->vi_txqueue.head = 0; - hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; - hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; - pxmitpriv->be_txqueue.head = 0; - hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; - hwxmits[2] .sta_queue = &pxmitpriv->be_pending; - pxmitpriv->bk_txqueue.head = 0; - hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - } -} - -static void free_hwxmits(struct _adapter *padapter) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - kfree(pxmitpriv->hwxmits); -} - -static void init_hwxmits(struct hw_xmit *phwxmit, sint entry) -{ - sint i; - - for (i = 0; i < entry; i++, phwxmit++) { - spin_lock_init(&phwxmit->xmit_lock); - INIT_LIST_HEAD(&phwxmit->pending); - phwxmit->txcmdcnt = 0; - phwxmit->accnt = 0; - } -} - -void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe, - struct xmit_buf *pxmitbuf) -{ - /* pxmitbuf attach to pxmitframe */ - pxmitframe->pxmitbuf = pxmitbuf; - /* urb and irp connection */ - pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; - /* buffer addr assoc */ - pxmitframe->buf_addr = pxmitbuf->pbuf; - /* pxmitframe attach to pxmitbuf */ - pxmitbuf->priv_data = pxmitframe; -} - -/* - * tx_action == 0 == no frames to transmit - * tx_action > 0 ==> we have frames to transmit - * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough - * to transmit 1 frame. - */ - -int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe) -{ - unsigned long irqL; - int ret; - struct xmit_buf *pxmitbuf = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - r8712_do_queue_select(padapter, pattrib); - spin_lock_irqsave(&pxmitpriv->lock, irqL); - if (r8712_txframes_sta_ac_pending(padapter, pattrib) > 0) { - ret = false; - r8712_xmit_enqueue(padapter, pxmitframe); - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - return ret; - } - pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); - if (!pxmitbuf) { /*enqueue packet*/ - ret = false; - r8712_xmit_enqueue(padapter, pxmitframe); - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - } else { /*dump packet directly*/ - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - ret = true; - xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); - r8712_xmit_direct(padapter, pxmitframe); - } - return ret; -} diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h deleted file mode 100644 index 784172c385e37c4dc182f15351784f288116a322..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ /dev/null @@ -1,287 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _RTL871X_XMIT_H_ -#define _RTL871X_XMIT_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "xmit_osdep.h" - -#ifdef CONFIG_R8712_TX_AGGR -#define MAX_XMITBUF_SZ (16384) -#else -#define MAX_XMITBUF_SZ (2048) -#endif - -#define NR_XMITBUFF (4) - -#ifdef CONFIG_R8712_TX_AGGR -#define AGGR_NR_HIGH_BOUND (4) /*(8) */ -#define AGGR_NR_LOW_BOUND (2) -#endif - -#define XMITBUF_ALIGN_SZ 512 -#define TX_GUARD_BAND 5 -#define MAX_NUMBLKS (1) - -/* Fixed the Big Endian bug when using the software driver encryption.*/ -#define WEP_IV(pattrib_iv, txpn, keyidx)\ -do { \ - pattrib_iv[0] = txpn._byte_.TSC0;\ - pattrib_iv[1] = txpn._byte_.TSC1;\ - pattrib_iv[2] = txpn._byte_.TSC2;\ - pattrib_iv[3] = ((keyidx & 0x3) << 6);\ - txpn.val = (txpn.val == 0xffffff) ? 0 : (txpn.val + 1);\ -} while (0) - -/* Fixed the Big Endian bug when doing the Tx. - * The Linksys WRH54G will check this. - */ -#define TKIP_IV(pattrib_iv, txpn, keyidx)\ -do { \ - pattrib_iv[0] = txpn._byte_.TSC1;\ - pattrib_iv[1] = (txpn._byte_.TSC1 | 0x20) & 0x7f;\ - pattrib_iv[2] = txpn._byte_.TSC0;\ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\ - pattrib_iv[4] = txpn._byte_.TSC2;\ - pattrib_iv[5] = txpn._byte_.TSC3;\ - pattrib_iv[6] = txpn._byte_.TSC4;\ - pattrib_iv[7] = txpn._byte_.TSC5;\ - txpn.val = txpn.val == 0xffffffffffffULL ? 0 : \ - (txpn.val + 1);\ -} while (0) - -#define AES_IV(pattrib_iv, txpn, keyidx)\ -do { \ - pattrib_iv[0] = txpn._byte_.TSC0;\ - pattrib_iv[1] = txpn._byte_.TSC1;\ - pattrib_iv[2] = 0;\ - pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\ - pattrib_iv[4] = txpn._byte_.TSC2;\ - pattrib_iv[5] = txpn._byte_.TSC3;\ - pattrib_iv[6] = txpn._byte_.TSC4;\ - pattrib_iv[7] = txpn._byte_.TSC5;\ - txpn.val = txpn.val == 0xffffffffffffULL ? 0 : \ - (txpn.val + 1);\ -} while (0) - -struct hw_xmit { - spinlock_t xmit_lock; - struct list_head pending; - struct __queue *sta_queue; - struct hw_txqueue *phwtxqueue; - sint txcmdcnt; - int accnt; -}; - -struct pkt_attrib { - u8 type; - u8 subtype; - u8 bswenc; - u8 dhcp_pkt; - - u16 seqnum; - u16 ether_type; - u16 pktlen; /* the original 802.3 pkt raw_data len - * (not include ether_hdr data) - */ - u16 last_txcmdsz; - - u8 pkt_hdrlen; /*the original 802.3 pkt header len*/ - u8 hdrlen; /*the WLAN Header Len*/ - u8 nr_frags; - u8 ack_policy; - u8 mac_id; - u8 vcs_mode; /*virtual carrier sense method*/ - u8 pctrl;/*per packet txdesc control enable*/ - u8 qsel; - - u8 priority; - u8 encrypt; /* when 0 indicate no encrypt. when non-zero, - * indicate the encrypt algorithm - */ - u8 iv_len; - u8 icv_len; - unsigned char iv[8]; - unsigned char icv[8]; - u8 dst[ETH_ALEN] __aligned(2); /* for ether_addr_copy */ - u8 src[ETH_ALEN]; - u8 ta[ETH_ALEN]; - u8 ra[ETH_ALEN]; - struct sta_info *psta; -}; - -#define WLANHDR_OFFSET 64 -#define DATA_FRAMETAG 0x01 -#define L2_FRAMETAG 0x02 -#define MGNT_FRAMETAG 0x03 -#define AMSDU_FRAMETAG 0x04 -#define EII_FRAMETAG 0x05 -#define IEEE8023_FRAMETAG 0x06 -#define MP_FRAMETAG 0x07 -#define TXAGG_FRAMETAG 0x08 - -struct xmit_buf { - struct list_head list; - - u8 *pallocated_buf; - u8 *pbuf; - void *priv_data; - struct urb *pxmit_urb[8]; - u32 aggr_nr; -}; - -struct xmit_frame { - struct list_head list; - struct pkt_attrib attrib; - _pkt *pkt; - int frame_tag; - struct _adapter *padapter; - u8 *buf_addr; - struct xmit_buf *pxmitbuf; - u8 *mem_addr; - u16 sz[8]; - struct urb *pxmit_urb[8]; - u8 bpending[8]; - u8 last[8]; -}; - -struct tx_servq { - struct list_head tx_pending; - struct __queue sta_pending; - int qcnt; -}; - -struct sta_xmit_priv { - spinlock_t lock; - sint option; - sint apsd_setting; /* When bit mask is on, the associated edca - * queue supports APSD. - */ - struct tx_servq be_q; /* priority == 0,3 */ - struct tx_servq bk_q; /* priority == 1,2*/ - struct tx_servq vi_q; /*priority == 4,5*/ - struct tx_servq vo_q; /*priority == 6,7*/ - struct list_head legacy_dz; - struct list_head apsd; - u16 txseq_tid[16]; - uint sta_tx_bytes; - u64 sta_tx_pkts; - uint sta_tx_fail; -}; - -struct hw_txqueue { - sint head; - sint tail; - sint free_sz; /* in units of 64 bytes */ - sint free_cmdsz; - sint txsz[8]; - uint ff_hwaddr; - uint cmd_hwaddr; - sint ac_tag; -}; - -struct xmit_priv { - spinlock_t lock; - struct __queue be_pending; - struct __queue bk_pending; - struct __queue vi_pending; - struct __queue vo_pending; - struct __queue bm_pending; - struct __queue legacy_dz_queue; - struct __queue apsd_queue; - u8 *pallocated_frame_buf; - u8 *pxmit_frame_buf; - uint free_xmitframe_cnt; - uint mapping_addr; - uint pkt_sz; - struct __queue free_xmit_queue; - struct hw_txqueue be_txqueue; - struct hw_txqueue bk_txqueue; - struct hw_txqueue vi_txqueue; - struct hw_txqueue vo_txqueue; - struct hw_txqueue bmc_txqueue; - uint frag_len; - struct _adapter *adapter; - u8 vcs_setting; - u8 vcs; - u8 vcs_type; - u16 rts_thresh; - uint tx_bytes; - u64 tx_pkts; - uint tx_drop; - struct hw_xmit *hwxmits; - u8 hwxmit_entry; - u8 txirp_cnt; - struct tasklet_struct xmit_tasklet; - struct work_struct xmit_pipe4_reset_wi; - struct work_struct xmit_pipe6_reset_wi; - struct work_struct xmit_piped_reset_wi; - /*per AC pending irp*/ - int beq_cnt; - int bkq_cnt; - int viq_cnt; - int voq_cnt; - struct __queue free_amsdu_xmit_queue; - u8 *pallocated_amsdu_frame_buf; - u8 *pxmit_amsdu_frame_buf; - uint free_amsdu_xmitframe_cnt; - struct __queue free_txagg_xmit_queue; - u8 *pallocated_txagg_frame_buf; - u8 *pxmit_txagg_frame_buf; - uint free_txagg_xmitframe_cnt; - int cmdseq; - struct __queue free_xmitbuf_queue; - struct __queue pending_xmitbuf_queue; - u8 *pxmitbuf; - uint free_xmitbuf_cnt; -}; - -void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); -struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv); -void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len); -struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv); -void r8712_free_xmitframe(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe); -void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv, - struct __queue *pframequeue); -int r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe); -sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, - struct xmit_frame *pxmitframe); -sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); -void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv); -int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib); -int r8712_txframes_sta_ac_pending(struct _adapter *padapter, - struct pkt_attrib *pattrib); -int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter); -void _free_xmit_priv(struct xmit_priv *pxmitpriv); -void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, - struct xmit_frame *pxmitframe); -int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe); -int r8712_xmit_enqueue(struct _adapter *padapter, - struct xmit_frame *pxmitframe); -void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); -void r8712_xmit_bh(struct tasklet_struct *t); - -void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe, - struct xmit_buf *pxmitbuf); - -#include "rtl8712_xmit.h" - -#endif /*_RTL871X_XMIT_H_*/ - diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h deleted file mode 100644 index 6286c622475e59ace9a25064044df22db60ab632..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/sta_info.h +++ /dev/null @@ -1,132 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __STA_INFO_H_ -#define __STA_INFO_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "wifi.h" - -#define NUM_STA 32 -#define NUM_ACL 64 - -/* if mode ==0, then the sta is allowed once the addr is hit. - * if mode ==1, then the sta is rejected once the addr is non-hit. - */ -struct wlan_acl_node { - struct list_head list; - u8 addr[ETH_ALEN]; - u8 mode; -}; - -struct wlan_acl_pool { - struct wlan_acl_node aclnode[NUM_ACL]; -}; - -struct stainfo_stats { - uint rx_pkts; - uint rx_bytes; - u64 tx_pkts; - uint tx_bytes; -}; - -struct sta_info { - spinlock_t lock; - struct list_head list; /*free_sta_queue*/ - struct list_head hash_list; /*sta_hash*/ - struct sta_xmit_priv sta_xmitpriv; - struct sta_recv_priv sta_recvpriv; - uint state; - uint aid; - uint mac_id; - uint qos_option; - u8 hwaddr[ETH_ALEN]; - uint ieee8021x_blocked; /*0: allowed, 1:blocked */ - uint XPrivacy; /*aes, tkip...*/ - union Keytype tkiptxmickey; - union Keytype tkiprxmickey; - union Keytype x_UncstKey; - union pn48 txpn; /* PN48 used for Unicast xmit.*/ - union pn48 rxpn; /* PN48 used for Unicast recv.*/ - u8 bssrateset[16]; - uint bssratelen; - s32 rssi; - s32 signal_quality; - struct stainfo_stats sta_stats; - /*for A-MPDU Rx reordering buffer control */ - struct recv_reorder_ctrl recvreorder_ctrl[16]; - struct ht_priv htpriv; - /* Notes: - * STA_Mode: - * curr_network(mlme_priv/security_priv/qos/ht) - * + sta_info: (STA & AP) CAP/INFO - * scan_q: AP CAP/INFO - * AP_Mode: - * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO - * sta_info: (AP & STA) CAP/INFO - */ - struct list_head asoc_list; - struct list_head auth_list; - unsigned int expire_to; - unsigned int auth_seq; - unsigned int authalg; - unsigned char chg_txt[128]; - unsigned int tx_ra_bitmap; -}; - -struct sta_priv { - u8 *pallocated_stainfo_buf; - u8 *pstainfo_buf; - struct __queue free_sta_queue; - spinlock_t sta_hash_lock; - struct list_head sta_hash[NUM_STA]; - int asoc_sta_count; - struct __queue sleep_q; - struct __queue wakeup_q; - struct _adapter *padapter; - struct list_head asoc_list; - struct list_head auth_list; - unsigned int auth_to; /* sec, time to expire in authenticating. */ - unsigned int assoc_to; /* sec, time to expire before associating. */ - unsigned int expire_to; /* sec , time to expire after associated. */ -}; - -static inline u32 wifi_mac_hash(u8 *mac) -{ - u32 x; - - x = mac[0]; - x = (x << 2) ^ mac[1]; - x = (x << 2) ^ mac[2]; - x = (x << 2) ^ mac[3]; - x = (x << 2) ^ mac[4]; - x = (x << 2) ^ mac[5]; - x ^= x >> 8; - x = x & (NUM_STA - 1); - return x; -} - -int _r8712_init_sta_priv(struct sta_priv *pstapriv); -void _r8712_free_sta_priv(struct sta_priv *pstapriv); -struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, - u8 *hwaddr); -void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta); -void r8712_free_all_stainfo(struct _adapter *padapter); -struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr); -void r8712_init_bcmc_stainfo(struct _adapter *padapter); -struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter); -u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr); - -#endif /* _STA_INFO_H_ */ - diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c deleted file mode 100644 index 313c569748e99b5db4e845479321c985e9f00bf5..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/usb_halinit.c +++ /dev/null @@ -1,307 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * usb_halinit.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _HCI_HAL_INIT_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "usb_ops.h" -#include "usb_osintf.h" - -u8 r8712_usb_hal_bus_init(struct _adapter *adapter) -{ - u8 val8 = 0; - u8 ret = _SUCCESS; - int PollingCnt = 20; - struct registry_priv *registrypriv = &adapter->registrypriv; - - if (registrypriv->chip_version == RTL8712_FPGA) { - val8 = 0x01; - /* switch to 80M clock */ - r8712_write8(adapter, SYS_CLKR, val8); - val8 = r8712_read8(adapter, SPS1_CTRL); - val8 = val8 | 0x01; - /* enable VSPS12 LDO Macro block */ - r8712_write8(adapter, SPS1_CTRL, val8); - val8 = r8712_read8(adapter, AFE_MISC); - val8 = val8 | 0x01; - /* Enable AFE Macro Block's Bandgap */ - r8712_write8(adapter, AFE_MISC, val8); - val8 = r8712_read8(adapter, LDOA15_CTRL); - val8 = val8 | 0x01; - /* enable LDOA15 block */ - r8712_write8(adapter, LDOA15_CTRL, val8); - val8 = r8712_read8(adapter, SPS1_CTRL); - val8 = val8 | 0x02; - /* Enable VSPS12_SW Macro Block */ - r8712_write8(adapter, SPS1_CTRL, val8); - val8 = r8712_read8(adapter, AFE_MISC); - val8 = val8 | 0x02; - /* Enable AFE Macro Block's Mbias */ - r8712_write8(adapter, AFE_MISC, val8); - val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1); - val8 = val8 | 0x08; - /* isolate PCIe Analog 1.2V to PCIe 3.3V and PCIE Digital */ - r8712_write8(adapter, SYS_ISO_CTRL + 1, val8); - val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1); - val8 = val8 & 0xEF; - /* attach AFE PLL to MACTOP/BB/PCIe Digital */ - r8712_write8(adapter, SYS_ISO_CTRL + 1, val8); - val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1); - val8 = val8 & 0xFB; - /* enable AFE clock */ - r8712_write8(adapter, AFE_XTAL_CTRL + 1, val8); - val8 = r8712_read8(adapter, AFE_PLL_CTRL); - val8 = val8 | 0x01; - /* Enable AFE PLL Macro Block */ - r8712_write8(adapter, AFE_PLL_CTRL, val8); - val8 = 0xEE; - /* release isolation AFE PLL & MD */ - r8712_write8(adapter, SYS_ISO_CTRL, val8); - val8 = r8712_read8(adapter, SYS_CLKR + 1); - val8 = val8 | 0x08; - /* enable MAC clock */ - r8712_write8(adapter, SYS_CLKR + 1, val8); - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - val8 = val8 | 0x08; - /* enable Core digital and enable IOREG R/W */ - r8712_write8(adapter, SYS_FUNC_EN + 1, val8); - val8 = val8 | 0x80; - /* enable REG_EN */ - r8712_write8(adapter, SYS_FUNC_EN + 1, val8); - val8 = r8712_read8(adapter, SYS_CLKR + 1); - val8 = (val8 | 0x80) & 0xBF; - /* switch the control path */ - r8712_write8(adapter, SYS_CLKR + 1, val8); - val8 = 0xFC; - r8712_write8(adapter, CR, val8); - val8 = 0x37; - r8712_write8(adapter, CR + 1, val8); - /* reduce EndPoint & init it */ - r8712_write8(adapter, 0x102500ab, r8712_read8(adapter, - 0x102500ab) | BIT(6) | BIT(7)); - /* consideration of power consumption - init */ - r8712_write8(adapter, 0x10250008, r8712_read8(adapter, - 0x10250008) & 0xfffffffb); - } else if (registrypriv->chip_version == RTL8712_1stCUT) { - /* Initialization for power on sequence, */ - r8712_write8(adapter, SPS0_CTRL + 1, 0x53); - r8712_write8(adapter, SPS0_CTRL, 0x57); - /* Enable AFE Macro Block's Bandgap and Enable AFE Macro - * Block's Mbias - */ - val8 = r8712_read8(adapter, AFE_MISC); - r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN | - AFE_MISC_MBEN)); - /* Enable LDOA15 block */ - val8 = r8712_read8(adapter, LDOA15_CTRL); - r8712_write8(adapter, LDOA15_CTRL, (val8 | LDA15_EN)); - val8 = r8712_read8(adapter, SPS1_CTRL); - r8712_write8(adapter, SPS1_CTRL, (val8 | SPS1_LDEN)); - msleep(20); - /* Enable Switch Regulator Block */ - val8 = r8712_read8(adapter, SPS1_CTRL); - r8712_write8(adapter, SPS1_CTRL, (val8 | SPS1_SWEN)); - r8712_write32(adapter, SPS1_CTRL, 0x00a7b267); - val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1); - r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 | 0x08)); - /* Engineer Packet CP test Enable */ - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x20)); - val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1); - r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 & 0x6F)); - /* Enable AFE clock */ - val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1); - r8712_write8(adapter, AFE_XTAL_CTRL + 1, (val8 & 0xfb)); - /* Enable AFE PLL Macro Block */ - val8 = r8712_read8(adapter, AFE_PLL_CTRL); - r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11)); - /* Attach AFE PLL to MACTOP/BB/PCIe Digital */ - val8 = r8712_read8(adapter, SYS_ISO_CTRL); - r8712_write8(adapter, SYS_ISO_CTRL, (val8 & 0xEE)); - /* Switch to 40M clock */ - val8 = r8712_read8(adapter, SYS_CLKR); - r8712_write8(adapter, SYS_CLKR, val8 & (~SYS_CLKSEL)); - /* SSC Disable */ - val8 = r8712_read8(adapter, SYS_CLKR); - /* Enable MAC clock */ - val8 = r8712_read8(adapter, SYS_CLKR + 1); - r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x18)); - /* Revised POS, */ - r8712_write8(adapter, PMC_FSM, 0x02); - /* Enable Core digital and enable IOREG R/W */ - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x08)); - /* Enable REG_EN */ - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x80)); - /* Switch the control path to FW */ - val8 = r8712_read8(adapter, SYS_CLKR + 1); - r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x80) & 0xBF); - r8712_write8(adapter, CR, 0xFC); - r8712_write8(adapter, CR + 1, 0x37); - /* Fix the RX FIFO issue(usb error), */ - val8 = r8712_read8(adapter, 0x1025FE5c); - r8712_write8(adapter, 0x1025FE5c, (val8 | BIT(7))); - val8 = r8712_read8(adapter, 0x102500ab); - r8712_write8(adapter, 0x102500ab, (val8 | BIT(6) | BIT(7))); - /* For power save, used this in the bit file after 970621 */ - val8 = r8712_read8(adapter, SYS_CLKR); - r8712_write8(adapter, SYS_CLKR, val8 & (~CPU_CLKSEL)); - } else if (registrypriv->chip_version == RTL8712_2ndCUT || - registrypriv->chip_version == RTL8712_3rdCUT) { - /* Initialization for power on sequence, - * E-Fuse leakage prevention sequence - */ - r8712_write8(adapter, 0x37, 0xb0); - msleep(20); - r8712_write8(adapter, 0x37, 0x30); - /* Set control path switch to HW control and reset Digital Core, - * CPU Core and MAC I/O to solve FW download fail when system - * from resume sate. - */ - val8 = r8712_read8(adapter, SYS_CLKR + 1); - if (val8 & 0x80) { - val8 &= 0x3f; - r8712_write8(adapter, SYS_CLKR + 1, val8); - } - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - val8 &= 0x73; - r8712_write8(adapter, SYS_FUNC_EN + 1, val8); - msleep(20); - /* Revised POS, */ - /* Enable AFE Macro Block's Bandgap and Enable AFE Macro - * Block's Mbias - */ - r8712_write8(adapter, SPS0_CTRL + 1, 0x53); - r8712_write8(adapter, SPS0_CTRL, 0x57); - val8 = r8712_read8(adapter, AFE_MISC); - /*Bandgap*/ - r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN)); - r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN | - AFE_MISC_MBEN | AFE_MISC_I32_EN)); - /* Enable PLL Power (LDOA15V) */ - val8 = r8712_read8(adapter, LDOA15_CTRL); - r8712_write8(adapter, LDOA15_CTRL, (val8 | LDA15_EN)); - /* Enable LDOV12D block */ - val8 = r8712_read8(adapter, LDOV12D_CTRL); - r8712_write8(adapter, LDOV12D_CTRL, (val8 | LDV12_EN)); - val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1); - r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 | 0x08)); - /* Engineer Packet CP test Enable */ - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x20)); - /* Support 64k IMEM */ - val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1); - r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 & 0x68)); - /* Enable AFE clock */ - val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1); - r8712_write8(adapter, AFE_XTAL_CTRL + 1, (val8 & 0xfb)); - /* Enable AFE PLL Macro Block */ - val8 = r8712_read8(adapter, AFE_PLL_CTRL); - r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11)); - /* Some sample will download fw failure. The clock will be - * stable with 500 us delay after reset the PLL - * TODO: When usleep is added to kernel, change next 3 - * udelay(500) to usleep(500) - */ - udelay(500); - r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x51)); - udelay(500); - r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11)); - udelay(500); - /* Attach AFE PLL to MACTOP/BB/PCIe Digital */ - val8 = r8712_read8(adapter, SYS_ISO_CTRL); - r8712_write8(adapter, SYS_ISO_CTRL, (val8 & 0xEE)); - /* Switch to 40M clock */ - r8712_write8(adapter, SYS_CLKR, 0x00); - /* CPU Clock and 80M Clock SSC Disable to overcome FW download - * fail timing issue. - */ - val8 = r8712_read8(adapter, SYS_CLKR); - r8712_write8(adapter, SYS_CLKR, (val8 | 0xa0)); - /* Enable MAC clock */ - val8 = r8712_read8(adapter, SYS_CLKR + 1); - r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x18)); - /* Revised POS, */ - r8712_write8(adapter, PMC_FSM, 0x02); - /* Enable Core digital and enable IOREG R/W */ - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x08)); - /* Enable REG_EN */ - val8 = r8712_read8(adapter, SYS_FUNC_EN + 1); - r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x80)); - /* Switch the control path to FW */ - val8 = r8712_read8(adapter, SYS_CLKR + 1); - r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x80) & 0xBF); - r8712_write8(adapter, CR, 0xFC); - r8712_write8(adapter, CR + 1, 0x37); - /* Fix the RX FIFO issue(usb error), 970410 */ - val8 = r8712_read8(adapter, 0x1025FE5c); - r8712_write8(adapter, 0x1025FE5c, (val8 | BIT(7))); - /* For power save, used this in the bit file after 970621 */ - val8 = r8712_read8(adapter, SYS_CLKR); - r8712_write8(adapter, SYS_CLKR, val8 & (~CPU_CLKSEL)); - /* Revised for 8051 ROM code wrong operation. */ - r8712_write8(adapter, 0x1025fe1c, 0x80); - /* To make sure that TxDMA can ready to download FW. - * We should reset TxDMA if IMEM RPT was not ready. - */ - do { - val8 = r8712_read8(adapter, TCR); - if ((val8 & _TXDMA_INIT_VALUE) == _TXDMA_INIT_VALUE) - break; - udelay(5); /* PlatformStallExecution(5); */ - } while (PollingCnt--); /* Delay 1ms */ - - if (PollingCnt <= 0) { - val8 = r8712_read8(adapter, CR); - r8712_write8(adapter, CR, val8 & (~_TXDMA_EN)); - udelay(2); /* PlatformStallExecution(2); */ - /* Reset TxDMA */ - r8712_write8(adapter, CR, val8 | _TXDMA_EN); - } - } else { - ret = _FAIL; - } - return ret; -} - -unsigned int r8712_usb_inirp_init(struct _adapter *adapter) -{ - u8 i; - struct recv_buf *recvbuf; - struct intf_hdl *intfhdl = &adapter->pio_queue->intf; - struct recv_priv *recvpriv = &(adapter->recvpriv); - - recvpriv->ff_hwaddr = RTL8712_DMA_RX0FF; /* mapping rx fifo address */ - /* issue Rx irp to receive data */ - recvbuf = (struct recv_buf *)recvpriv->precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - if (r8712_usb_read_port(intfhdl, recvpriv->ff_hwaddr, 0, - (unsigned char *)recvbuf) == false) - return _FAIL; - recvbuf++; - recvpriv->free_recv_buf_queue_cnt--; - } - return _SUCCESS; -} - -unsigned int r8712_usb_inirp_deinit(struct _adapter *adapter) -{ - r8712_usb_read_port_cancel(adapter); - return _SUCCESS; -} diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c deleted file mode 100644 index df05213f922f45b031f27b79959e4e08da626dcf..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/usb_intf.c +++ /dev/null @@ -1,638 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * usb_intf.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _HCI_INTF_C_ - -#include <linux/usb.h> -#include <linux/module.h> -#include <linux/firmware.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "recv_osdep.h" -#include "xmit_osdep.h" -#include "rtl8712_efuse.h" -#include "usb_ops.h" -#include "usb_osintf.h" - -static struct usb_interface *pintf; - -static int r871xu_drv_init(struct usb_interface *pusb_intf, - const struct usb_device_id *pdid); - -static void r871xu_dev_remove(struct usb_interface *pusb_intf); - -static const struct usb_device_id rtl871x_usb_id_tbl[] = { -/* RTL8188SU */ - /* Realtek */ - {USB_DEVICE(0x0BDA, 0x8171)}, - {USB_DEVICE(0x0bda, 0x8173)}, - {USB_DEVICE(0x0bda, 0x8712)}, - {USB_DEVICE(0x0bda, 0x8713)}, - {USB_DEVICE(0x0bda, 0xC512)}, - /* Abocom */ - {USB_DEVICE(0x07B8, 0x8188)}, - /* ASUS */ - {USB_DEVICE(0x0B05, 0x1786)}, - {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ - /* Belkin */ - {USB_DEVICE(0x050D, 0x945A)}, - /* ISY IWL - Belkin clone */ - {USB_DEVICE(0x050D, 0x11F1)}, - /* Corega */ - {USB_DEVICE(0x07AA, 0x0047)}, - /* D-Link */ - {USB_DEVICE(0x2001, 0x3306)}, - {USB_DEVICE(0x07D1, 0x3306)}, /* 11n mode disable */ - /* Edimax */ - {USB_DEVICE(0x7392, 0x7611)}, - /* EnGenius */ - {USB_DEVICE(0x1740, 0x9603)}, - /* Hawking */ - {USB_DEVICE(0x0E66, 0x0016)}, - /* Hercules */ - {USB_DEVICE(0x06F8, 0xE034)}, - {USB_DEVICE(0x06F8, 0xE032)}, - /* Logitec */ - {USB_DEVICE(0x0789, 0x0167)}, - /* PCI */ - {USB_DEVICE(0x2019, 0xAB28)}, - {USB_DEVICE(0x2019, 0xED16)}, - /* Sitecom */ - {USB_DEVICE(0x0DF6, 0x0057)}, - {USB_DEVICE(0x0DF6, 0x0045)}, - {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */ - {USB_DEVICE(0x0DF6, 0x004B)}, - {USB_DEVICE(0x0DF6, 0x005B)}, - {USB_DEVICE(0x0DF6, 0x005D)}, - {USB_DEVICE(0x0DF6, 0x0063)}, - /* Sweex */ - {USB_DEVICE(0x177F, 0x0154)}, - /* Thinkware */ - {USB_DEVICE(0x0BDA, 0x5077)}, - /* Toshiba */ - {USB_DEVICE(0x1690, 0x0752)}, - /* - */ - {USB_DEVICE(0x20F4, 0x646B)}, - {USB_DEVICE(0x083A, 0xC512)}, - {USB_DEVICE(0x25D4, 0x4CA1)}, - {USB_DEVICE(0x25D4, 0x4CAB)}, - -/* RTL8191SU */ - /* Realtek */ - {USB_DEVICE(0x0BDA, 0x8172)}, - {USB_DEVICE(0x0BDA, 0x8192)}, - /* Amigo */ - {USB_DEVICE(0x0EB0, 0x9061)}, - /* ASUS/EKB */ - {USB_DEVICE(0x13D3, 0x3323)}, - {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */ - {USB_DEVICE(0x13D3, 0x3342)}, - /* ASUS/EKBLenovo */ - {USB_DEVICE(0x13D3, 0x3333)}, - {USB_DEVICE(0x13D3, 0x3334)}, - {USB_DEVICE(0x13D3, 0x3335)}, /* 11n mode disable */ - {USB_DEVICE(0x13D3, 0x3336)}, /* 11n mode disable */ - /* ASUS/Media BOX */ - {USB_DEVICE(0x13D3, 0x3309)}, - /* Belkin */ - {USB_DEVICE(0x050D, 0x815F)}, - /* D-Link */ - {USB_DEVICE(0x07D1, 0x3302)}, - {USB_DEVICE(0x07D1, 0x3300)}, - {USB_DEVICE(0x07D1, 0x3303)}, - /* Edimax */ - {USB_DEVICE(0x7392, 0x7612)}, - /* EnGenius */ - {USB_DEVICE(0x1740, 0x9605)}, - /* Guillemot */ - {USB_DEVICE(0x06F8, 0xE031)}, - /* Hawking */ - {USB_DEVICE(0x0E66, 0x0015)}, - /* Mediao */ - {USB_DEVICE(0x13D3, 0x3306)}, - /* PCI */ - {USB_DEVICE(0x2019, 0xED18)}, - {USB_DEVICE(0x2019, 0x4901)}, - /* Sitecom */ - {USB_DEVICE(0x0DF6, 0x0058)}, - {USB_DEVICE(0x0DF6, 0x0049)}, - {USB_DEVICE(0x0DF6, 0x004C)}, - {USB_DEVICE(0x0DF6, 0x006C)}, - {USB_DEVICE(0x0DF6, 0x0064)}, - /* Skyworth */ - {USB_DEVICE(0x14b2, 0x3300)}, - {USB_DEVICE(0x14b2, 0x3301)}, - {USB_DEVICE(0x14B2, 0x3302)}, - /* - */ - {USB_DEVICE(0x04F2, 0xAFF2)}, - {USB_DEVICE(0x04F2, 0xAFF5)}, - {USB_DEVICE(0x04F2, 0xAFF6)}, - {USB_DEVICE(0x13D3, 0x3339)}, - {USB_DEVICE(0x13D3, 0x3340)}, /* 11n mode disable */ - {USB_DEVICE(0x13D3, 0x3341)}, /* 11n mode disable */ - {USB_DEVICE(0x13D3, 0x3310)}, - {USB_DEVICE(0x13D3, 0x3325)}, - -/* RTL8192SU */ - /* Realtek */ - {USB_DEVICE(0x0BDA, 0x8174)}, - /* Belkin */ - {USB_DEVICE(0x050D, 0x845A)}, - /* Corega */ - {USB_DEVICE(0x07AA, 0x0051)}, - /* Edimax */ - {USB_DEVICE(0x7392, 0x7622)}, - /* NEC */ - {USB_DEVICE(0x0409, 0x02B6)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, rtl871x_usb_id_tbl); - -static struct specific_device_id specific_device_id_tbl[] = { - {.idVendor = 0x0b05, .idProduct = 0x1791, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x0df6, .idProduct = 0x0059, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x13d3, .idProduct = 0x3306, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x13D3, .idProduct = 0x3311, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x13d3, .idProduct = 0x3335, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x13d3, .idProduct = 0x3336, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x13d3, .idProduct = 0x3340, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {.idVendor = 0x13d3, .idProduct = 0x3341, - .flags = SPEC_DEV_ID_DISABLE_HT}, - {} -}; - -struct drv_priv { - struct usb_driver r871xu_drv; - int drv_registered; -}; - -#ifdef CONFIG_PM -static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state) -{ - struct net_device *pnetdev = usb_get_intfdata(pusb_intf); - struct _adapter *padapter = netdev_priv(pnetdev); - - netdev_info(pnetdev, "Suspending...\n"); - padapter->suspended = true; - rtl871x_intf_stop(padapter); - if (pnetdev->netdev_ops->ndo_stop) - pnetdev->netdev_ops->ndo_stop(pnetdev); - mdelay(10); - netif_device_detach(pnetdev); - return 0; -} - -static void rtl871x_intf_resume(struct _adapter *padapter) -{ - if (padapter->dvobjpriv.inirp_init) - padapter->dvobjpriv.inirp_init(padapter); -} - -static int r871x_resume(struct usb_interface *pusb_intf) -{ - struct net_device *pnetdev = usb_get_intfdata(pusb_intf); - struct _adapter *padapter = netdev_priv(pnetdev); - - netdev_info(pnetdev, "Resuming...\n"); - netif_device_attach(pnetdev); - if (pnetdev->netdev_ops->ndo_open) - pnetdev->netdev_ops->ndo_open(pnetdev); - padapter->suspended = false; - rtl871x_intf_resume(padapter); - return 0; -} -#endif - -static struct drv_priv drvpriv = { - .r871xu_drv.name = "r8712u", - .r871xu_drv.id_table = rtl871x_usb_id_tbl, - .r871xu_drv.probe = r871xu_drv_init, - .r871xu_drv.disconnect = r871xu_dev_remove, -#ifdef CONFIG_PM - .r871xu_drv.suspend = r871x_suspend, - .r871xu_drv.resume = r871x_resume, -#endif -}; - -static uint r8712_usb_dvobj_init(struct _adapter *padapter) -{ - uint status = _SUCCESS; - struct usb_host_interface *phost_iface; - struct usb_interface_descriptor *piface_desc; - struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv; - struct usb_device *pusbd = pdvobjpriv->pusbdev; - - pdvobjpriv->padapter = padapter; - padapter->eeprom_address_size = 6; - phost_iface = pintf->cur_altsetting; - piface_desc = &phost_iface->desc; - pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; - if (pusbd->speed == USB_SPEED_HIGH) { - pdvobjpriv->ishighspeed = true; - dev_info(&pusbd->dev, "r8712u: USB_SPEED_HIGH with %d endpoints\n", - pdvobjpriv->nr_endpoint); - } else { - pdvobjpriv->ishighspeed = false; - dev_info(&pusbd->dev, "r8712u: USB_SPEED_LOW with %d endpoints\n", - pdvobjpriv->nr_endpoint); - } - if ((r8712_alloc_io_queue(padapter)) == _FAIL) - status = _FAIL; - return status; -} - -static void r8712_usb_dvobj_deinit(struct _adapter *padapter) -{ - r8712_free_io_queue(padapter); -} - -void rtl871x_intf_stop(struct _adapter *padapter) -{ - /*disable_hw_interrupt*/ - if (!padapter->surprise_removed) { - /*device still exists, so driver can do i/o operation - * TODO: - */ - } - - /* cancel in irp */ - if (padapter->dvobjpriv.inirp_deinit) - padapter->dvobjpriv.inirp_deinit(padapter); - /* cancel out irp */ - r8712_usb_write_port_cancel(padapter); - /* TODO:cancel other irps */ -} - -void r871x_dev_unload(struct _adapter *padapter) -{ - if (padapter->bup) { - /*s1.*/ - padapter->driver_stopped = true; - - /*s3.*/ - rtl871x_intf_stop(padapter); - - /*s4.*/ - r8712_stop_drv_threads(padapter); - - /*s5.*/ - if (!padapter->surprise_removed) { - padapter->hw_init_completed = false; - rtl8712_hal_deinit(padapter); - } - - padapter->bup = false; - } -} - -static void disable_ht_for_spec_devid(const struct usb_device_id *pdid, - struct _adapter *padapter) -{ - u16 vid, pid; - u32 flags; - int i; - int num = ARRAY_SIZE(specific_device_id_tbl); - - for (i = 0; i < num; i++) { - vid = specific_device_id_tbl[i].idVendor; - pid = specific_device_id_tbl[i].idProduct; - flags = specific_device_id_tbl[i].flags; - - if ((pdid->idVendor == vid) && (pdid->idProduct == pid) && - (flags & SPEC_DEV_ID_DISABLE_HT)) { - padapter->registrypriv.ht_enable = 0; - padapter->registrypriv.cbw40_enable = 0; - padapter->registrypriv.ampdu_enable = 0; - } - } -} - -static const struct device_type wlan_type = { - .name = "wlan", -}; - -/* - * drv_init() - a device potentially for us - * - * notes: drv_init() is called when the bus driver has located a card for us - * to support. We accept the new device by returning 0. - */ -static int r871xu_drv_init(struct usb_interface *pusb_intf, - const struct usb_device_id *pdid) -{ - uint status; - struct _adapter *padapter = NULL; - struct dvobj_priv *pdvobjpriv; - struct net_device *pnetdev; - struct usb_device *udev; - - /* In this probe function, O.S. will provide the usb interface pointer - * to driver. We have to increase the reference count of the usb device - * structure by using the usb_get_dev function. - */ - udev = interface_to_usbdev(pusb_intf); - usb_get_dev(udev); - pintf = pusb_intf; - /* step 1. */ - pnetdev = r8712_init_netdev(); - if (!pnetdev) - goto put_dev; - padapter = netdev_priv(pnetdev); - disable_ht_for_spec_devid(pdid, padapter); - pdvobjpriv = &padapter->dvobjpriv; - pdvobjpriv->padapter = padapter; - padapter->dvobjpriv.pusbdev = udev; - padapter->pusb_intf = pusb_intf; - usb_set_intfdata(pusb_intf, pnetdev); - SET_NETDEV_DEV(pnetdev, &pusb_intf->dev); - pnetdev->dev.type = &wlan_type; - /* step 2. */ - padapter->dvobj_init = r8712_usb_dvobj_init; - padapter->dvobj_deinit = r8712_usb_dvobj_deinit; - padapter->halpriv.hal_bus_init = r8712_usb_hal_bus_init; - padapter->dvobjpriv.inirp_init = r8712_usb_inirp_init; - padapter->dvobjpriv.inirp_deinit = r8712_usb_inirp_deinit; - /* step 3. - * initialize the dvobj_priv - */ - - status = padapter->dvobj_init(padapter); - if (status != _SUCCESS) - goto free_netdev; - - /* step 4. */ - status = r8712_init_drv_sw(padapter); - if (status) - goto dvobj_deinit; - /* step 5. read efuse/eeprom data and get mac_addr */ - { - int i, offset; - u8 mac[6]; - u8 tmpU1b, AutoloadFail, eeprom_CustomerID; - u8 *pdata = padapter->eeprompriv.efuse_eeprom_data; - - tmpU1b = r8712_read8(padapter, EE_9346CR);/*CR9346*/ - - /* To check system boot selection.*/ - dev_info(&udev->dev, "r8712u: Boot from %s: Autoload %s\n", - (tmpU1b & _9356SEL) ? "EEPROM" : "EFUSE", - (tmpU1b & _EEPROM_EN) ? "OK" : "Failed"); - - /* To check autoload success or not.*/ - if (tmpU1b & _EEPROM_EN) { - AutoloadFail = true; - /* The following operations prevent Efuse leakage by - * turning on 2.5V. - */ - tmpU1b = r8712_read8(padapter, EFUSE_TEST + 3); - r8712_write8(padapter, EFUSE_TEST + 3, tmpU1b | 0x80); - msleep(20); - r8712_write8(padapter, EFUSE_TEST + 3, - (tmpU1b & (~BIT(7)))); - - /* Retrieve Chip version. - * Recognize IC version by Reg0x4 BIT15. - */ - tmpU1b = (u8)((r8712_read32(padapter, PMC_FSM) >> 15) & - 0x1F); - if (tmpU1b == 0x3) - padapter->registrypriv.chip_version = - RTL8712_3rdCUT; - else - padapter->registrypriv.chip_version = - (tmpU1b >> 1) + 1; - switch (padapter->registrypriv.chip_version) { - case RTL8712_1stCUT: - case RTL8712_2ndCUT: - case RTL8712_3rdCUT: - break; - default: - padapter->registrypriv.chip_version = - RTL8712_2ndCUT; - break; - } - - for (i = 0, offset = 0; i < 128; i += 8, offset++) - r8712_efuse_pg_packet_read(padapter, offset, - &pdata[i]); - - if (!r8712_initmac || !mac_pton(r8712_initmac, mac)) { - /* Use the mac address stored in the Efuse - * offset = 0x12 for usb in efuse - */ - ether_addr_copy(mac, &pdata[0x12]); - } - eeprom_CustomerID = pdata[0x52]; - switch (eeprom_CustomerID) { - case EEPROM_CID_ALPHA: - padapter->eeprompriv.CustomerID = - RT_CID_819x_ALPHA; - break; - case EEPROM_CID_CAMEO: - padapter->eeprompriv.CustomerID = - RT_CID_819x_CAMEO; - break; - case EEPROM_CID_SITECOM: - padapter->eeprompriv.CustomerID = - RT_CID_819x_Sitecom; - break; - case EEPROM_CID_COREGA: - padapter->eeprompriv.CustomerID = - RT_CID_COREGA; - break; - case EEPROM_CID_Senao: - padapter->eeprompriv.CustomerID = - RT_CID_819x_Senao; - break; - case EEPROM_CID_EDIMAX_BELKIN: - padapter->eeprompriv.CustomerID = - RT_CID_819x_Edimax_Belkin; - break; - case EEPROM_CID_SERCOMM_BELKIN: - padapter->eeprompriv.CustomerID = - RT_CID_819x_Sercomm_Belkin; - break; - case EEPROM_CID_WNC_COREGA: - padapter->eeprompriv.CustomerID = - RT_CID_819x_WNC_COREGA; - break; - case EEPROM_CID_WHQL: - break; - case EEPROM_CID_NetCore: - padapter->eeprompriv.CustomerID = - RT_CID_819x_Netcore; - break; - case EEPROM_CID_CAMEO1: - padapter->eeprompriv.CustomerID = - RT_CID_819x_CAMEO1; - break; - case EEPROM_CID_CLEVO: - padapter->eeprompriv.CustomerID = - RT_CID_819x_CLEVO; - break; - default: - padapter->eeprompriv.CustomerID = - RT_CID_DEFAULT; - break; - } - dev_info(&udev->dev, "r8712u: CustomerID = 0x%.4x\n", - padapter->eeprompriv.CustomerID); - /* Led mode */ - switch (padapter->eeprompriv.CustomerID) { - case RT_CID_DEFAULT: - case RT_CID_819x_ALPHA: - case RT_CID_819x_CAMEO: - padapter->ledpriv.LedStrategy = SW_LED_MODE1; - padapter->ledpriv.bRegUseLed = true; - break; - case RT_CID_819x_Sitecom: - padapter->ledpriv.LedStrategy = SW_LED_MODE2; - padapter->ledpriv.bRegUseLed = true; - break; - case RT_CID_COREGA: - case RT_CID_819x_Senao: - padapter->ledpriv.LedStrategy = SW_LED_MODE3; - padapter->ledpriv.bRegUseLed = true; - break; - case RT_CID_819x_Edimax_Belkin: - padapter->ledpriv.LedStrategy = SW_LED_MODE4; - padapter->ledpriv.bRegUseLed = true; - break; - case RT_CID_819x_Sercomm_Belkin: - padapter->ledpriv.LedStrategy = SW_LED_MODE5; - padapter->ledpriv.bRegUseLed = true; - break; - case RT_CID_819x_WNC_COREGA: - padapter->ledpriv.LedStrategy = SW_LED_MODE6; - padapter->ledpriv.bRegUseLed = true; - break; - default: - padapter->ledpriv.LedStrategy = SW_LED_MODE0; - padapter->ledpriv.bRegUseLed = false; - break; - } - } else { - AutoloadFail = false; - } - if ((!AutoloadFail) || - ((mac[0] == 0xff) && (mac[1] == 0xff) && - (mac[2] == 0xff) && (mac[3] == 0xff) && - (mac[4] == 0xff) && (mac[5] == 0xff)) || - ((mac[0] == 0x00) && (mac[1] == 0x00) && - (mac[2] == 0x00) && (mac[3] == 0x00) && - (mac[4] == 0x00) && (mac[5] == 0x00))) { - mac[0] = 0x00; - mac[1] = 0xe0; - mac[2] = 0x4c; - mac[3] = 0x87; - mac[4] = 0x00; - mac[5] = 0x00; - } - if (r8712_initmac) { - /* Make sure the user did not select a multicast - * address by setting bit 1 of first octet. - */ - mac[0] &= 0xFE; - dev_info(&udev->dev, - "r8712u: MAC Address from user = %pM\n", mac); - } else { - dev_info(&udev->dev, - "r8712u: MAC Address from efuse = %pM\n", mac); - } - eth_hw_addr_set(pnetdev, mac); - } - /* step 6. Load the firmware asynchronously */ - if (rtl871x_load_fw(padapter)) - goto deinit_drv_sw; - init_completion(&padapter->rx_filter_ready); - return 0; - -deinit_drv_sw: - r8712_free_drv_sw(padapter); -dvobj_deinit: - padapter->dvobj_deinit(padapter); -free_netdev: - free_netdev(pnetdev); -put_dev: - usb_put_dev(udev); - usb_set_intfdata(pusb_intf, NULL); - return -ENODEV; -} - -/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() - * => how to recognize both - */ -static void r871xu_dev_remove(struct usb_interface *pusb_intf) -{ - struct net_device *pnetdev = usb_get_intfdata(pusb_intf); - struct usb_device *udev = interface_to_usbdev(pusb_intf); - struct _adapter *padapter = netdev_priv(pnetdev); - - /* never exit with a firmware callback pending */ - wait_for_completion(&padapter->rtl8712_fw_ready); - if (pnetdev->reg_state != NETREG_UNINITIALIZED) - unregister_netdev(pnetdev); /* will call netdev_close() */ - usb_set_intfdata(pusb_intf, NULL); - release_firmware(padapter->fw); - if (drvpriv.drv_registered) - padapter->surprise_removed = true; - r8712_flush_rwctrl_works(padapter); - r8712_flush_led_works(padapter); - udelay(1); - /* Stop driver mlme relation timer */ - r8712_stop_drv_timers(padapter); - r871x_dev_unload(padapter); - if (padapter->dvobj_deinit) - padapter->dvobj_deinit(padapter); - r8712_free_drv_sw(padapter); - free_netdev(pnetdev); - - /* decrease the reference count of the usb device structure - * when disconnect - */ - usb_put_dev(udev); - - /* If we didn't unplug usb dongle and remove/insert module, driver - * fails on sitesurvey for the first time when device is up. - * Reset usb port for sitesurvey fail issue. - */ - if (udev->state != USB_STATE_NOTATTACHED) - usb_reset_device(udev); -} - -static int __init r8712u_drv_entry(void) -{ - drvpriv.drv_registered = true; - return usb_register(&drvpriv.r871xu_drv); -} - -static void __exit r8712u_drv_halt(void) -{ - drvpriv.drv_registered = false; - usb_deregister(&drvpriv.r871xu_drv); -} - -module_init(r8712u_drv_entry); -module_exit(r8712u_drv_halt); diff --git a/drivers/staging/rtl8712/usb_ops.c b/drivers/staging/rtl8712/usb_ops.c deleted file mode 100644 index af9966d03979c6f0221e11b5469cddf838081b2a..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/usb_ops.c +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * usb_ops.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _HCI_OPS_C_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" -#include "usb_ops.h" -#include "recv_osdep.h" - -static u8 usb_read8(struct intf_hdl *intfhdl, u32 addr) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - int status; - __le32 data = 0; - struct intf_priv *intfpriv = intfhdl->pintfpriv; - - request = 0x05; - requesttype = 0x01; /* read_in */ - index = 0; - wvalue = (u16)(addr & 0x0000ffff); - len = 1; - status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, - &data, len, requesttype); - if (status < 0) - return 0; - return (u8)(le32_to_cpu(data) & 0x0ff); -} - -static u16 usb_read16(struct intf_hdl *intfhdl, u32 addr) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - int status; - __le32 data = 0; - struct intf_priv *intfpriv = intfhdl->pintfpriv; - - request = 0x05; - requesttype = 0x01; /* read_in */ - index = 0; - wvalue = (u16)(addr & 0x0000ffff); - len = 2; - status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, - &data, len, requesttype); - if (status < 0) - return 0; - return (u16)(le32_to_cpu(data) & 0xffff); -} - -static u32 usb_read32(struct intf_hdl *intfhdl, u32 addr) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - int status; - __le32 data = 0; - struct intf_priv *intfpriv = intfhdl->pintfpriv; - - request = 0x05; - requesttype = 0x01; /* read_in */ - index = 0; - wvalue = (u16)(addr & 0x0000ffff); - len = 4; - status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, - &data, len, requesttype); - if (status < 0) - return 0; - return le32_to_cpu(data); -} - -static void usb_write8(struct intf_hdl *intfhdl, u32 addr, u8 val) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - __le32 data; - struct intf_priv *intfpriv = intfhdl->pintfpriv; - - request = 0x05; - requesttype = 0x00; /* write_out */ - index = 0; - wvalue = (u16)(addr & 0x0000ffff); - len = 1; - data = cpu_to_le32((u32)val & 0x000000ff); - r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len, - requesttype); -} - -static void usb_write16(struct intf_hdl *intfhdl, u32 addr, u16 val) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - __le32 data; - struct intf_priv *intfpriv = intfhdl->pintfpriv; - - request = 0x05; - requesttype = 0x00; /* write_out */ - index = 0; - wvalue = (u16)(addr & 0x0000ffff); - len = 2; - data = cpu_to_le32((u32)val & 0x0000ffff); - r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len, - requesttype); -} - -static void usb_write32(struct intf_hdl *intfhdl, u32 addr, u32 val) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - __le32 data; - struct intf_priv *intfpriv = intfhdl->pintfpriv; - - request = 0x05; - requesttype = 0x00; /* write_out */ - index = 0; - wvalue = (u16)(addr & 0x0000ffff); - len = 4; - data = cpu_to_le32(val); - r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len, - requesttype); -} - -void r8712_usb_set_intf_option(u32 *option) -{ - *option = ((*option) | _INTF_ASYNC_); -} - -static void usb_intf_hdl_init(u8 *priv) -{ -} - -static void usb_intf_hdl_unload(u8 *priv) -{ -} - -static void usb_intf_hdl_open(u8 *priv) -{ -} - -static void usb_intf_hdl_close(u8 *priv) -{ -} - -void r8712_usb_set_intf_funs(struct intf_hdl *intfhdl) -{ - intfhdl->intf_hdl_init = usb_intf_hdl_init; - intfhdl->intf_hdl_unload = usb_intf_hdl_unload; - intfhdl->intf_hdl_open = usb_intf_hdl_open; - intfhdl->intf_hdl_close = usb_intf_hdl_close; -} - -void r8712_usb_set_intf_ops(struct _io_ops *ops) -{ - memset((u8 *)ops, 0, sizeof(struct _io_ops)); - ops->_read8 = usb_read8; - ops->_read16 = usb_read16; - ops->_read32 = usb_read32; - ops->_read_port = r8712_usb_read_port; - ops->_write8 = usb_write8; - ops->_write16 = usb_write16; - ops->_write32 = usb_write32; - ops->_write_mem = r8712_usb_write_mem; - ops->_write_port = r8712_usb_write_port; -} diff --git a/drivers/staging/rtl8712/usb_ops.h b/drivers/staging/rtl8712/usb_ops.h deleted file mode 100644 index 7a6b619b73fabe6bb2f1f966ed620ed91fdb2e71..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/usb_ops.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __USB_OPS_H_ -#define __USB_OPS_H_ - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" - -void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, - u32 cnt, u8 *wmem); -u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, - u32 cnt, u8 *wmem); -u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, - u32 cnt, u8 *rmem); -void r8712_usb_set_intf_option(u32 *poption); -void r8712_usb_set_intf_funs(struct intf_hdl *pintf_hdl); -uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv); -void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv); -void r8712_usb_set_intf_ops(struct _io_ops *pops); -void r8712_usb_read_port_cancel(struct _adapter *padapter); -void r8712_usb_write_port_cancel(struct _adapter *padapter); -int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value, - u16 index, void *pdata, u16 len, u8 requesttype); - -#endif - diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c deleted file mode 100644 index 4a34824830e39de1d7a298ccc5846f316adc2a22..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/usb_ops_linux.c +++ /dev/null @@ -1,508 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * usb_ops_linux.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _HCI_OPS_OS_C_ - -#include <linux/usb.h> - -#include "osdep_service.h" -#include "drv_types.h" -#include "osdep_intf.h" -#include "usb_ops.h" - -#define RTL871X_VENQT_READ 0xc0 -#define RTL871X_VENQT_WRITE 0x40 - -uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv) -{ - pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!pintfpriv->piorw_urb) - return _FAIL; - init_completion(&pintfpriv->io_retevt_comp); - return _SUCCESS; -} - -void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv) -{ - if (pintfpriv->piorw_urb) { - usb_kill_urb(pintfpriv->piorw_urb); - usb_free_urb(pintfpriv->piorw_urb); - } -} - -static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr) -{ - unsigned int pipe = 0; - struct usb_device *pusbd = pdvobj->pusbdev; - - if (pdvobj->nr_endpoint == 11) { - switch (addr) { - case RTL8712_DMA_BKQ: - pipe = usb_sndbulkpipe(pusbd, 0x07); - break; - case RTL8712_DMA_BEQ: - pipe = usb_sndbulkpipe(pusbd, 0x06); - break; - case RTL8712_DMA_VIQ: - pipe = usb_sndbulkpipe(pusbd, 0x05); - break; - case RTL8712_DMA_VOQ: - pipe = usb_sndbulkpipe(pusbd, 0x04); - break; - case RTL8712_DMA_BCNQ: - pipe = usb_sndbulkpipe(pusbd, 0x0a); - break; - case RTL8712_DMA_BMCQ: /* HI Queue */ - pipe = usb_sndbulkpipe(pusbd, 0x0b); - break; - case RTL8712_DMA_MGTQ: - pipe = usb_sndbulkpipe(pusbd, 0x0c); - break; - case RTL8712_DMA_RX0FF: - pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */ - break; - case RTL8712_DMA_C2HCMD: - pipe = usb_rcvbulkpipe(pusbd, 0x09); /* in */ - break; - case RTL8712_DMA_H2CCMD: - pipe = usb_sndbulkpipe(pusbd, 0x0d); - break; - } - } else if (pdvobj->nr_endpoint == 6) { - switch (addr) { - case RTL8712_DMA_BKQ: - pipe = usb_sndbulkpipe(pusbd, 0x07); - break; - case RTL8712_DMA_BEQ: - pipe = usb_sndbulkpipe(pusbd, 0x06); - break; - case RTL8712_DMA_VIQ: - pipe = usb_sndbulkpipe(pusbd, 0x05); - break; - case RTL8712_DMA_VOQ: - pipe = usb_sndbulkpipe(pusbd, 0x04); - break; - case RTL8712_DMA_RX0FF: - case RTL8712_DMA_C2HCMD: - pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */ - break; - case RTL8712_DMA_H2CCMD: - case RTL8712_DMA_BCNQ: - case RTL8712_DMA_BMCQ: - case RTL8712_DMA_MGTQ: - pipe = usb_sndbulkpipe(pusbd, 0x0d); - break; - } - } else if (pdvobj->nr_endpoint == 4) { - switch (addr) { - case RTL8712_DMA_BEQ: - pipe = usb_sndbulkpipe(pusbd, 0x06); - break; - case RTL8712_DMA_VOQ: - pipe = usb_sndbulkpipe(pusbd, 0x04); - break; - case RTL8712_DMA_RX0FF: - case RTL8712_DMA_C2HCMD: - pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */ - break; - case RTL8712_DMA_H2CCMD: - case RTL8712_DMA_BCNQ: - case RTL8712_DMA_BMCQ: - case RTL8712_DMA_MGTQ: - pipe = usb_sndbulkpipe(pusbd, 0x0d); - break; - } - } else { - pipe = 0; - } - return pipe; -} - -static void usb_write_mem_complete(struct urb *purb) -{ - struct io_queue *pio_q = (struct io_queue *)purb->context; - struct intf_hdl *pintf = &(pio_q->intf); - struct intf_priv *pintfpriv = pintf->pintfpriv; - struct _adapter *padapter = (struct _adapter *)pintf->adapter; - - if (purb->status != 0) { - if (purb->status == (-ESHUTDOWN)) - padapter->driver_stopped = true; - else - padapter->surprise_removed = true; - } - complete(&pintfpriv->io_retevt_comp); -} - -void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) -{ - unsigned int pipe; - struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter; - struct intf_priv *pintfpriv = pintfhdl->pintfpriv; - struct io_queue *pio_queue = padapter->pio_queue; - struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev; - struct usb_device *pusbd = pdvobj->pusbdev; - struct urb *piorw_urb = pintfpriv->piorw_urb; - - if ((padapter->driver_stopped) || (padapter->surprise_removed) || - (padapter->pwrctrlpriv.pnp_bstop_trx)) - return; - /* translate DMA FIFO addr to pipehandle */ - pipe = ffaddr2pipehdl(pdvobj, addr); - if (pipe == 0) - return; - usb_fill_bulk_urb(piorw_urb, pusbd, pipe, - wmem, cnt, usb_write_mem_complete, - pio_queue); - usb_submit_urb(piorw_urb, GFP_ATOMIC); - wait_for_completion_interruptible(&pintfpriv->io_retevt_comp); -} - -static void r8712_usb_read_port_complete(struct urb *purb) -{ - uint isevt; - __le32 *pbuf; - struct recv_buf *precvbuf = (struct recv_buf *)purb->context; - struct _adapter *padapter = (struct _adapter *)precvbuf->adapter; - struct recv_priv *precvpriv = &padapter->recvpriv; - - if (padapter->surprise_removed || padapter->driver_stopped) - return; - if (purb->status == 0) { /* SUCCESS */ - if ((purb->actual_length > (MAX_RECVBUF_SZ)) || - (purb->actual_length < RXDESC_SIZE)) { - r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, - (unsigned char *)precvbuf); - } else { - _pkt *pskb = precvbuf->pskb; - - precvbuf->transfer_len = purb->actual_length; - pbuf = (__le32 *)precvbuf->pbuf; - isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff; - if ((isevt & 0x1ff) == 0x1ff) { - r8712_rxcmd_event_hdl(padapter, pbuf); - skb_queue_tail(&precvpriv->rx_skb_queue, pskb); - r8712_read_port(padapter, precvpriv->ff_hwaddr, - 0, (unsigned char *)precvbuf); - } else { - skb_put(pskb, purb->actual_length); - skb_queue_tail(&precvpriv->rx_skb_queue, pskb); - tasklet_hi_schedule(&precvpriv->recv_tasklet); - r8712_read_port(padapter, precvpriv->ff_hwaddr, - 0, (unsigned char *)precvbuf); - } - } - } else { - switch (purb->status) { - case -EINVAL: - case -EPIPE: - case -ENODEV: - case -ESHUTDOWN: - padapter->driver_stopped = true; - break; - case -ENOENT: - if (!padapter->suspended) { - padapter->driver_stopped = true; - break; - } - fallthrough; - case -EPROTO: - r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, - (unsigned char *)precvbuf); - break; - case -EINPROGRESS: - netdev_err(padapter->pnetdev, "ERROR: URB IS IN PROGRESS!\n"); - break; - default: - break; - } - } -} - -u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem) -{ - unsigned int pipe; - int err; - u32 tmpaddr = 0; - int alignment = 0; - u32 ret = _SUCCESS; - struct urb *purb = NULL; - struct recv_buf *precvbuf = (struct recv_buf *)rmem; - struct intf_priv *pintfpriv = pintfhdl->pintfpriv; - struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev; - struct _adapter *adapter = pdvobj->padapter; - struct recv_priv *precvpriv = &adapter->recvpriv; - struct usb_device *pusbd = pdvobj->pusbdev; - - if (adapter->driver_stopped || adapter->surprise_removed || - adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf) - return _FAIL; - r8712_init_recvbuf(adapter, precvbuf); - /* Try to use skb from the free queue */ - precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue); - - if (!precvbuf->pskb) { - precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, - MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ); - if (!precvbuf->pskb) - return _FAIL; - tmpaddr = (addr_t)precvbuf->pskb->data; - alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); - skb_reserve(precvbuf->pskb, - (RECVBUFF_ALIGN_SZ - alignment)); - precvbuf->phead = precvbuf->pskb->head; - precvbuf->pdata = precvbuf->pskb->data; - precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); - precvbuf->pend = skb_end_pointer(precvbuf->pskb); - precvbuf->pbuf = precvbuf->pskb->data; - } else { /* skb is reused */ - precvbuf->phead = precvbuf->pskb->head; - precvbuf->pdata = precvbuf->pskb->data; - precvbuf->ptail = skb_tail_pointer(precvbuf->pskb); - precvbuf->pend = skb_end_pointer(precvbuf->pskb); - precvbuf->pbuf = precvbuf->pskb->data; - } - purb = precvbuf->purb; - /* translate DMA FIFO addr to pipehandle */ - pipe = ffaddr2pipehdl(pdvobj, addr); - usb_fill_bulk_urb(purb, pusbd, pipe, - precvbuf->pbuf, MAX_RECVBUF_SZ, - r8712_usb_read_port_complete, - precvbuf); - err = usb_submit_urb(purb, GFP_ATOMIC); - if ((err) && (err != (-EPERM))) - ret = _FAIL; - return ret; -} - -void r8712_usb_read_port_cancel(struct _adapter *padapter) -{ - int i; - struct recv_buf *precvbuf; - - precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf; - for (i = 0; i < NR_RECVBUFF; i++) { - if (precvbuf->purb) - usb_kill_urb(precvbuf->purb); - precvbuf++; - } -} - -void r8712_xmit_bh(struct tasklet_struct *t) -{ - int ret = false; - struct _adapter *padapter = from_tasklet(padapter, t, - xmitpriv.xmit_tasklet); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter->driver_stopped || - padapter->surprise_removed) { - netdev_err(padapter->pnetdev, "xmit_bh => driver_stopped or surprise_removed\n"); - return; - } - ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL); - if (!ret) - return; - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); -} - -static void usb_write_port_complete(struct urb *purb) -{ - int i; - struct xmit_frame *pxmitframe = (struct xmit_frame *)purb->context; - struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf; - struct _adapter *padapter = pxmitframe->padapter; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - switch (pattrib->priority) { - case 1: - case 2: - pxmitpriv->bkq_cnt--; - break; - case 4: - case 5: - pxmitpriv->viq_cnt--; - break; - case 6: - case 7: - pxmitpriv->voq_cnt--; - break; - case 0: - case 3: - default: - pxmitpriv->beq_cnt--; - break; - } - pxmitpriv->txirp_cnt--; - for (i = 0; i < 8; i++) { - if (purb == pxmitframe->pxmit_urb[i]) { - pxmitframe->bpending[i] = false; - break; - } - } - if (padapter->surprise_removed) - return; - switch (purb->status) { - case 0: - break; - default: - netdev_warn(padapter->pnetdev, - "r8712u: pipe error: (%d)\n", purb->status); - break; - } - /* not to consider tx fragment */ - r8712_free_xmitframe_ex(pxmitpriv, pxmitframe); - r8712_free_xmitbuf(pxmitpriv, pxmitbuf); - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); -} - -u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem) -{ - unsigned long irqL; - int i, status; - unsigned int pipe; - u32 ret, bwritezero; - struct urb *purb = NULL; - struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter; - struct dvobj_priv *pdvobj = &padapter->dvobjpriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe = (struct xmit_frame *)wmem; - struct usb_device *pusbd = pdvobj->pusbdev; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - if ((padapter->driver_stopped) || (padapter->surprise_removed) || - (padapter->pwrctrlpriv.pnp_bstop_trx)) - return _FAIL; - for (i = 0; i < 8; i++) { - if (!pxmitframe->bpending[i]) { - spin_lock_irqsave(&pxmitpriv->lock, irqL); - pxmitpriv->txirp_cnt++; - pxmitframe->bpending[i] = true; - switch (pattrib->priority) { - case 1: - case 2: - pxmitpriv->bkq_cnt++; - break; - case 4: - case 5: - pxmitpriv->viq_cnt++; - break; - case 6: - case 7: - pxmitpriv->voq_cnt++; - break; - case 0: - case 3: - default: - pxmitpriv->beq_cnt++; - break; - } - spin_unlock_irqrestore(&pxmitpriv->lock, irqL); - pxmitframe->sz[i] = (u16)cnt; - purb = pxmitframe->pxmit_urb[i]; - break; - } - } - bwritezero = false; - if (pdvobj->ishighspeed) { - if (cnt > 0 && cnt % 512 == 0) - bwritezero = true; - } else { - if (cnt > 0 && cnt % 64 == 0) - bwritezero = true; - } - /* translate DMA FIFO addr to pipehandle */ - pipe = ffaddr2pipehdl(pdvobj, addr); - if (pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0) - purb->transfer_flags &= (~URB_NO_INTERRUPT); - else - purb->transfer_flags |= URB_NO_INTERRUPT; - if (bwritezero) - cnt += 8; - usb_fill_bulk_urb(purb, pusbd, pipe, - pxmitframe->mem_addr, - cnt, usb_write_port_complete, - pxmitframe); /* context is xmit_frame */ - status = usb_submit_urb(purb, GFP_ATOMIC); - if (!status) - ret = _SUCCESS; - else - ret = _FAIL; - return ret; -} - -void r8712_usb_write_port_cancel(struct _adapter *padapter) -{ - int i, j; - struct xmit_buf *pxmitbuf = (struct xmit_buf *) - padapter->xmitpriv.pxmitbuf; - - for (i = 0; i < NR_XMITBUFF; i++) { - for (j = 0; j < 8; j++) { - if (pxmitbuf->pxmit_urb[j]) - usb_kill_urb(pxmitbuf->pxmit_urb[j]); - } - pxmitbuf++; - } -} - -int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value, - u16 index, void *pdata, u16 len, u8 requesttype) -{ - unsigned int pipe; - int status; - u8 reqtype; - struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *) - pintfpriv->intf_dev; - struct usb_device *udev = pdvobjpriv->pusbdev; - /* For mstar platform, mstar suggests the address for USB IO - * should be 16 bytes alignment. Trying to fix it here. - */ - u8 *palloc_buf, *pIo_buf; - - palloc_buf = kmalloc((u32)len + 16, GFP_ATOMIC); - if (!palloc_buf) - return -ENOMEM; - pIo_buf = palloc_buf + 16 - ((addr_t)(palloc_buf) & 0x0f); - if (requesttype == 0x01) { - pipe = usb_rcvctrlpipe(udev, 0); /* read_in */ - reqtype = RTL871X_VENQT_READ; - } else { - pipe = usb_sndctrlpipe(udev, 0); /* write_out */ - reqtype = RTL871X_VENQT_WRITE; - memcpy(pIo_buf, pdata, len); - } - status = usb_control_msg(udev, pipe, request, reqtype, value, index, - pIo_buf, len, 500); - if (status < 0) - goto free; - if (status != len) { - status = -EREMOTEIO; - goto free; - } - /* Success this control transfer. */ - if (requesttype == 0x01) { - /* For Control read transfer, we have to copy the read - * data from pIo_buf to pdata. - */ - memcpy(pdata, pIo_buf, status); - } - -free: - kfree(palloc_buf); - return status; -} diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h deleted file mode 100644 index 2e512b4a564c2119e570ef3b4e2287640bf9e0ee..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/usb_osintf.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __USB_OSINTF_H -#define __USB_OSINTF_H - -#include "osdep_service.h" -#include "drv_types.h" - -extern char *r8712_initmac; - -unsigned int r8712_usb_inirp_init(struct _adapter *padapter); -unsigned int r8712_usb_inirp_deinit(struct _adapter *padapter); -uint rtl871x_hal_init(struct _adapter *padapter); -uint rtl8712_hal_deinit(struct _adapter *padapter); - -void rtl871x_intf_stop(struct _adapter *padapter); -void r871x_dev_unload(struct _adapter *padapter); -void r8712_stop_drv_threads(struct _adapter *padapter); -void r8712_stop_drv_timers(struct _adapter *padapter); -int r8712_init_drv_sw(struct _adapter *padapter); -void r8712_free_drv_sw(struct _adapter *padapter); -struct net_device *r8712_init_netdev(void); - -#endif diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h deleted file mode 100644 index 498e6dec7e67f6efbc78ea19b4b34bf9f3515d17..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/wifi.h +++ /dev/null @@ -1,196 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef _WIFI_H_ -#define _WIFI_H_ - -#include <linux/compiler.h> -#include <linux/ieee80211.h> - -#define WLAN_HDR_A3_LEN 24 -#define WLAN_HDR_A3_QOS_LEN 26 - -enum WIFI_FRAME_TYPE { - WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /*!< QoS Data */ -}; - -#define SetToDs(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS); \ -}) - -#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0) - -#define ClearToDs(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_TODS)); \ -}) - -#define SetFrDs(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS); \ -}) - -#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0) - -#define ClearFrDs(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_FROMDS)); \ -}) - -static inline unsigned char get_tofr_ds(unsigned char *pframe) -{ - return ((GetToDs(pframe) << 1) | GetFrDs(pframe)); -} - -#define SetMFrag(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); \ -}) - -#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0) - -#define ClearMFrag(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)); \ -}) - -#define SetRetry(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY); \ -}) - -#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0) - -#define ClearRetry(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_RETRY)); \ -}) - -#define SetPwrMgt(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM); \ -}) - -#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(IEEE80211_FCTL_PM)) != 0) - -#define ClearPwrMgt(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_PM)); \ -}) - -#define SetMData(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); \ -}) - -#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0) - -#define ClearMData(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREDATA)); \ -}) - -#define SetPrivacy(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); \ -}) - -#define GetPrivacy(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0) - -#define GetOrder(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0) - -#define GetFrameType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \ - (BIT(3) | BIT(2))) - -#define SetFrameType(pbuf, type) \ - do { \ - *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(3) | \ - BIT(2))); \ - *(__le16 *)(pbuf) |= cpu_to_le16(type); \ - } while (0) - -#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \ - (BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | \ - BIT(2))) - -#define SetFrameSubType(pbuf, type) \ - do { \ - *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \ - BIT(5) | BIT(4) | BIT(3) | BIT(2))); \ - *(__le16 *)(pbuf) |= cpu_to_le16(type); \ - } while (0) - -#define GetSequence(pbuf) (le16_to_cpu(*(__le16 *)\ - ((addr_t)(pbuf) + 22)) >> 4) - -#define GetFragNum(pbuf) (le16_to_cpu(*(__le16 *)((addr_t)\ - (pbuf) + 22)) & 0x0f) - -#define SetSeqNum(pbuf, num) ({ \ - *(__le16 *)((addr_t)(pbuf) + 22) = \ - cpu_to_le16((le16_to_cpu(*(__le16 *)((addr_t)(pbuf) + 22)) & \ - 0x000f) | (0xfff0 & (num << 4))); \ -}) - -#define SetPriority(pbuf, tid) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf); \ -}) - -#define GetPriority(pbuf) ((le16_to_cpu(*(__le16 *)(pbuf))) & 0xf) - -#define SetAckpolicy(pbuf, ack) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5); \ -}) - -#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3) - -#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1) - -#define GetAddr1Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 4)) - -#define GetAddr2Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 10)) - -#define GetAddr3Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 16)) - -#define GetAddr4Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 24)) - -static inline unsigned char *get_hdr_bssid(unsigned char *pframe) -{ - unsigned char *sa; - unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); - - switch (to_fr_ds) { - case 0x00: /* ToDs=0, FromDs=0 */ - sa = GetAddr3Ptr(pframe); - break; - case 0x01: /* ToDs=0, FromDs=1 */ - sa = GetAddr2Ptr(pframe); - break; - case 0x02: /* ToDs=1, FromDs=0 */ - sa = GetAddr1Ptr(pframe); - break; - default: /* ToDs=1, FromDs=1 */ - sa = NULL; - break; - } - return sa; -} - -/* --------------------------------------------------------------------------- - * Below is the fixed elements... - * --------------------------------------------------------------------------- - */ -#define _BEACON_ITERVAL_ 2 -#define _CAPABILITY_ 2 -#define _TIMESTAMP_ 8 - -/*----------------------------------------------------------------------------- - * Below is the definition for WMM - *------------------------------------------------------------------------------ - */ -#define _WMM_IE_Length_ 7 /* for WMM STA */ - -#endif /* _WIFI_H_ */ - diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h deleted file mode 100644 index ec3749813728d9b6a8611a4e010e2f08abe098bc..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/wlan_bssdef.h +++ /dev/null @@ -1,223 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __WLAN_BSSDEF_H__ -#define __WLAN_BSSDEF_H__ - -#define MAX_IE_SZ 768 - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -struct ndis_802_11_ssid { - u32 SsidLength; - u8 Ssid[32]; -}; - -enum NDIS_802_11_NETWORK_TYPE { - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11NetworkTypeMax /* not a real type, defined as an upper bound*/ -}; - -struct NDIS_802_11_CONFIGURATION_FH { - u32 Length; /* Length of structure */ - u32 HopPattern; /* As defined by 802.11, MSB set */ - u32 HopSet; /* to one if non-802.11 */ - u32 DwellTime; /* units are Kusec */ -}; - -/* - * FW will only save the channel number in DSConfig. - * ODI Handler will convert the channel number to freq. number. - */ -struct NDIS_802_11_CONFIGURATION { - u32 Length; /* Length of structure */ - u32 BeaconPeriod; /* units are Kusec */ - u32 ATIMWindow; /* units are Kusec */ - u32 DSConfig; /* Frequency, units are kHz */ - struct NDIS_802_11_CONFIGURATION_FH FHConfig; -}; - -enum NDIS_802_11_NETWORK_INFRASTRUCTURE { - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax, /*Not a real value,defined as upper bound*/ - Ndis802_11APMode -}; - -struct NDIS_802_11_FIXED_IEs { - u8 Timestamp[8]; - u16 BeaconInterval; - u16 Capabilities; -}; - -struct wlan_bssid_ex { - u32 Length; - unsigned char MacAddress[6]; - u8 Reserved[2]; - struct ndis_802_11_ssid Ssid; - __le32 Privacy; - s32 Rssi; - enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - struct NDIS_802_11_CONFIGURATION Configuration; - enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - u8 rates[NDIS_802_11_LENGTH_RATES_EX]; - /* number of content bytes in EIs, which varies */ - u32 IELength; - /*(timestamp, beacon interval, and capability information) */ - u8 IEs[MAX_IE_SZ]; -}; - -enum NDIS_802_11_AUTHENTICATION_MODE { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeMax /* Not a real mode, defined as upper bound */ -}; - -enum { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent -}; - -#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 -#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 -#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 - -#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 -#define NDIS_802_11_AI_RESFI_STATUSCODE 2 -#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 - -struct NDIS_802_11_AI_REQFI { - u16 Capabilities; - u16 ListenInterval; - unsigned char CurrentAPAddress[6]; -}; - -struct NDIS_802_11_AI_RESFI { - u16 Capabilities; - u16 StatusCode; - u16 AssociationId; -}; - -struct NDIS_802_11_ASSOCIATION_INFORMATION { - u32 Length; - u16 AvailableRequestFixedIEs; - struct NDIS_802_11_AI_REQFI RequestFixedIEs; - u32 RequestIELength; - u32 OffsetRequestIEs; - u16 AvailableResponseFixedIEs; - struct NDIS_802_11_AI_RESFI ResponseFixedIEs; - u32 ResponseIELength; - u32 OffsetResponseIEs; -}; - -/* Key mapping keys require a BSSID*/ -struct NDIS_802_11_KEY { - u32 Length; /* Length of this structure */ - u32 KeyIndex; - u32 KeyLength; /* length of key in bytes */ - unsigned char BSSID[6]; - unsigned long long KeyRSC; - u8 KeyMaterial[32]; /* variable length */ -}; - -struct NDIS_802_11_REMOVE_KEY { - u32 Length; /* Length of this structure */ - u32 KeyIndex; - unsigned char BSSID[6]; -}; - -struct NDIS_802_11_WEP { - u32 Length; /* Length of this structure */ - u32 KeyIndex; /* 0 is the per-client key, - * 1-N are the global keys - */ - u32 KeyLength; /* length of key in bytes */ - u8 KeyMaterial[16]; /* variable length depending on above field */ -}; - -/* mask for authentication/integrity fields */ -#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -/* MIC check time, 60 seconds. */ -#define MIC_CHECK_TIME 60000000 - -#ifndef Ndis802_11APMode -#define Ndis802_11APMode (Ndis802_11InfrastructureMax + 1) -#endif - -struct wlan_network { - struct list_head list; - int network_type; /*refer to ieee80211.h for WIRELESS_11A/B/G */ - int fixed; /* set to fixed when not to be removed asi - * site-surveying - */ - unsigned int last_scanned; /*timestamp for the network */ - int aid; /*will only be valid when a BSS is joined. */ - int join_res; - struct wlan_bssid_ex network; /*must be the last item */ -}; - -enum VRTL_CARRIER_SENSE { - DISABLE_VCS, - ENABLE_VCS, - AUTO_VCS -}; - -enum VCS_TYPE { - NONE_VCS, - RTS_CTS, - CTS_TO_SELF -}; - -#define PWR_CAM 0 -#define PWR_MINPS 1 -#define PWR_MAXPS 2 -#define PWR_UAPSD 3 -#define PWR_VOIP 4 - -enum UAPSD_MAX_SP { - NO_LIMIT, - TWO_MSDU, - FOUR_MSDU, - SIX_MSDU -}; - -#define NUM_PRE_AUTH_KEY 16 -#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY - -#endif /* #ifndef WLAN_BSSDEF_H_ */ - diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c deleted file mode 100644 index ceb6b590b310fdd59b33ffc2372a1348076bd2bf..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/xmit_linux.c +++ /dev/null @@ -1,181 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * xmit_linux.c - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * Linux device driver for RTL8192SU - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ - -#define _XMIT_OSDEP_C_ - -#include <linux/usb.h> -#include <linux/ip.h> -#include <linux/if_ether.h> -#include <linux/kmemleak.h> - -#include "osdep_service.h" -#include "drv_types.h" - -#include "wifi.h" -#include "mlme_osdep.h" -#include "xmit_osdep.h" -#include "osdep_intf.h" - -static uint remainder_len(struct pkt_file *pfile) -{ - return (uint)(pfile->buf_len - ((addr_t)(pfile->cur_addr) - - (addr_t)(pfile->buf_start))); -} - -void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile) -{ - pfile->pkt = pktptr; - pfile->cur_addr = pfile->buf_start = pktptr->data; - pfile->pkt_len = pfile->buf_len = pktptr->len; - pfile->cur_buffer = pfile->buf_start; -} - -uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen) -{ - uint len; - - len = remainder_len(pfile); - len = (rlen > len) ? len : rlen; - if (rmem) - skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, - rmem, len); - pfile->cur_addr += len; - pfile->pkt_len -= len; - return len; -} - -sint r8712_endofpktfile(struct pkt_file *pfile) -{ - return (pfile->pkt_len == 0); -} - -void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) -{ - struct ethhdr etherhdr; - struct iphdr ip_hdr; - u16 user_priority = 0; - - _r8712_open_pktfile(ppktfile->pkt, ppktfile); - _r8712_pktfile_read(ppktfile, (unsigned char *)ðerhdr, ETH_HLEN); - - /* get user_priority from IP hdr*/ - if (pattrib->ether_type == 0x0800) { - _r8712_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr)); - /*user_priority = (ntohs(ip_hdr.tos) >> 5) & 0x3 ;*/ - user_priority = ip_hdr.tos >> 5; - } else { - /* "When priority processing of data frames is supported, - * a STA's SME should send EAPOL-Key frames at the highest - * priority." - */ - - if (pattrib->ether_type == 0x888e) - user_priority = 7; - } - pattrib->priority = user_priority; - pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN; - pattrib->subtype = WIFI_QOS_DATA_TYPE; -} - -void r8712_SetFilter(struct work_struct *work) -{ - struct _adapter *adapter = container_of(work, struct _adapter, - wk_filter_rx_ff0); - u8 oldvalue = 0x00, newvalue = 0x00; - - oldvalue = r8712_read8(adapter, 0x117); - newvalue = oldvalue & 0xfe; - r8712_write8(adapter, 0x117, newvalue); - - wait_for_completion(&adapter->rx_filter_ready); - r8712_write8(adapter, 0x117, oldvalue); -} - -int r8712_xmit_resource_alloc(struct _adapter *padapter, - struct xmit_buf *pxmitbuf) -{ - int i; - - for (i = 0; i < 8; i++) { - pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!pxmitbuf->pxmit_urb[i]) { - int k; - - for (k = i - 1; k >= 0; k--) { - /* handle allocation errors part way through loop */ - usb_free_urb(pxmitbuf->pxmit_urb[k]); - } - netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n"); - return -ENOMEM; - } - kmemleak_not_leak(pxmitbuf->pxmit_urb[i]); - } - return 0; -} - -void r8712_xmit_resource_free(struct _adapter *padapter, - struct xmit_buf *pxmitbuf) -{ - int i; - - for (i = 0; i < 8; i++) { - if (pxmitbuf->pxmit_urb[i]) { - usb_kill_urb(pxmitbuf->pxmit_urb[i]); - usb_free_urb(pxmitbuf->pxmit_urb[i]); - } - } -} - -void r8712_xmit_complete(struct _adapter *padapter, struct xmit_frame *pxframe) -{ - if (pxframe->pkt) - dev_kfree_skb_any(pxframe->pkt); - pxframe->pkt = NULL; -} - -netdev_tx_t r8712_xmit_entry(_pkt *pkt, struct net_device *netdev) -{ - struct xmit_frame *xmitframe = NULL; - struct _adapter *adapter = netdev_priv(netdev); - struct xmit_priv *xmitpriv = &(adapter->xmitpriv); - - if (!r8712_if_up(adapter)) - goto _xmit_entry_drop; - - xmitframe = r8712_alloc_xmitframe(xmitpriv); - if (!xmitframe) - goto _xmit_entry_drop; - - if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib)) - goto _xmit_entry_drop; - - adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX); - xmitframe->pkt = pkt; - if (r8712_pre_xmit(adapter, xmitframe)) { - /*dump xmitframe directly or drop xframe*/ - dev_kfree_skb_any(pkt); - xmitframe->pkt = NULL; - } - xmitpriv->tx_pkts++; - xmitpriv->tx_bytes += xmitframe->attrib.last_txcmdsz; - return NETDEV_TX_OK; -_xmit_entry_drop: - if (xmitframe) - r8712_free_xmitframe(xmitpriv, xmitframe); - xmitpriv->tx_drop++; - dev_kfree_skb_any(pkt); - return NETDEV_TX_OK; -} diff --git a/drivers/staging/rtl8712/xmit_osdep.h b/drivers/staging/rtl8712/xmit_osdep.h deleted file mode 100644 index 1ad42658c8831c7126b1b8b4d973e79304a994c7..0000000000000000000000000000000000000000 --- a/drivers/staging/rtl8712/xmit_osdep.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. - * - * Modifications for inclusion into the Linux staging tree are - * Copyright(c) 2010 Larry Finger. All rights reserved. - * - * Contact information: - * WLAN FAE <wlanfae@realtek.com> - * Larry Finger <Larry.Finger@lwfinger.net> - * - ******************************************************************************/ -#ifndef __XMIT_OSDEP_H_ -#define __XMIT_OSDEP_H_ - -#include "osdep_service.h" -#include "drv_types.h" - -struct pkt_file { - _pkt *pkt; - u32 pkt_len; /*the remainder length of the open_file*/ - _buffer *cur_buffer; - u8 *buf_start; - u8 *cur_addr; - u32 buf_len; -}; - -#define NR_XMITFRAME 256 - -struct xmit_priv; -struct pkt_attrib; -struct sta_xmit_priv; -struct xmit_frame; -struct xmit_buf; - -netdev_tx_t r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev); -void r8712_SetFilter(struct work_struct *work); -int r8712_xmit_resource_alloc(struct _adapter *padapter, - struct xmit_buf *pxmitbuf); -void r8712_xmit_resource_free(struct _adapter *padapter, - struct xmit_buf *pxmitbuf); - -void r8712_set_qos(struct pkt_file *ppktfile, - struct pkt_attrib *pattrib); -void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile); -uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen); -sint r8712_endofpktfile(struct pkt_file *pfile); -void r8712_xmit_complete(struct _adapter *padapter, - struct xmit_frame *pxframe); - -#endif diff --git a/drivers/staging/rtl8723bs/TODO b/drivers/staging/rtl8723bs/TODO index 4c413f9d3df00fde36ee377fbb79d3712b88da6c..050dcd0bffab59d80760d8c7820515211844f01c 100644 --- a/drivers/staging/rtl8723bs/TODO +++ b/drivers/staging/rtl8723bs/TODO @@ -6,6 +6,3 @@ TODO: of them will require refactoring - merge Realtek's bugfixes and new features into the driver - switch to use MAC80211 - -Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>, -Hans de Goede <hdegoede@redhat.com> and Larry Finger <Larry.Finger@lwfinger.net>. diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index 84ce7307d8f3dfe1a1733d1ff65e8f523171a4e4..64ce33c6fba17210c6932ec225b838b33e6c9737 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c @@ -382,7 +382,7 @@ int rtw_cmd_thread(void *context) struct cmd_priv *pcmdpriv = &padapter->cmdpriv; struct drvextra_cmd_parm *extra_parm = NULL; - thread_enter("RTW_CMD_THREAD"); + allow_signal(SIGTERM); pcmdbuf = pcmdpriv->cmd_buf; @@ -1258,8 +1258,7 @@ static void dynamic_chk_wk_hdl(struct adapter *padapter) /* always call rtw_ps_processor() at last one. */ - if (is_primary_adapter(padapter)) - rtw_ps_processor(padapter); + rtw_ps_processor(padapter); } void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type); @@ -1465,6 +1464,7 @@ u8 rtw_ps_cmd(struct adapter *padapter) struct drvextra_cmd_parm *pdrvextra_cmd_parm; struct cmd_priv *pcmdpriv = &padapter->cmdpriv; u8 res = _SUCCESS; + ppscmd = rtw_zmalloc(sizeof(struct cmd_obj)); if (!ppscmd) { res = _FAIL; diff --git a/drivers/staging/rtl8723bs/core/rtw_efuse.c b/drivers/staging/rtl8723bs/core/rtw_efuse.c index 8b671f8a79659f106fd13faf1b3e5a44b9c37cb7..7a74b011dedc2afaee67b278cfe864e3d61d8bd9 100644 --- a/drivers/staging/rtl8723bs/core/rtw_efuse.c +++ b/drivers/staging/rtl8723bs/core/rtw_efuse.c @@ -77,33 +77,7 @@ struct adapter *padapter, u8 bWrite, u8 PwrState) { - padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState); -} - -/*----------------------------------------------------------------------------- - * Function: Efuse_GetCurrentSize - * - * Overview: Get current efuse size!!! - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/16/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -u16 -Efuse_GetCurrentSize( - struct adapter *padapter, - u8 efuseType, - bool bPseudoTest) -{ - return padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType, - bPseudoTest); + Hal_EfusePowerSwitch(padapter, bWrite, PwrState); } /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */ @@ -159,7 +133,7 @@ efuse_ReadEFuse( bool bPseudoTest ) { - Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest); + Hal_ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest); } void @@ -171,7 +145,7 @@ EFUSE_GetEfuseDefinition( bool bPseudoTest ) { - padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest); + Hal_GetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest); } /*----------------------------------------------------------------------------- @@ -312,68 +286,6 @@ u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoT return bResult; } -int -Efuse_PgPacketRead(struct adapter *padapter, - u8 offset, - u8 *data, - bool bPseudoTest) -{ - return padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data, - bPseudoTest); -} - -int -Efuse_PgPacketWrite(struct adapter *padapter, - u8 offset, - u8 word_en, - u8 *data, - bool bPseudoTest) -{ - return padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en, - data, bPseudoTest); -} - -/*----------------------------------------------------------------------------- - * Function: efuse_WordEnableDataRead - * - * Overview: Read allowed word in current efuse section data. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/16/2008 MHC Create Version 0. - * 11/21/2008 MHC Fix Write bug when we only enable late word. - * - *---------------------------------------------------------------------------*/ -void -efuse_WordEnableDataRead(u8 word_en, - u8 *sourdata, - u8 *targetdata) -{ - if (!(word_en & BIT(0))) { - targetdata[0] = sourdata[0]; - targetdata[1] = sourdata[1]; - } - if (!(word_en & BIT(1))) { - targetdata[2] = sourdata[2]; - targetdata[3] = sourdata[3]; - } - if (!(word_en & BIT(2))) { - targetdata[4] = sourdata[4]; - targetdata[5] = sourdata[5]; - } - if (!(word_en & BIT(3))) { - targetdata[6] = sourdata[6]; - targetdata[7] = sourdata[7]; - } -} - - u8 Efuse_WordEnableDataWrite(struct adapter *padapter, u16 efuse_addr, diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c index cbdb134278d37bfd0bc45f25e295edcfef58b8c1..5ded183aa08c49e80c7966444217ab47e3cee847 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c @@ -911,8 +911,7 @@ inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted) { rtw_os_indicate_scan_done(padapter, aborted); - if (is_primary_adapter(padapter) && - (!adapter_to_pwrctl(padapter)->bInSuspend) && + if ((!adapter_to_pwrctl(padapter)->bInSuspend) && (!check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_UNDER_LINKING))) { rtw_set_ips_deny(padapter, 0); @@ -1589,8 +1588,7 @@ void rtw_dynamic_check_timer_handler(struct adapter *adapter) } } else { - if (is_primary_adapter(adapter)) - rtw_dynamic_chk_wk_cmd(adapter); + rtw_dynamic_chk_wk_cmd(adapter); } /* auto site survey */ diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 4d4bec47d1874cd125fc8fdb034c664f7c4efa16..317f3db193971c8202939d8aa88717b600aa695d 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -1870,10 +1870,10 @@ unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv if (0) { int pp; - printk("pattrib->pktlen = %d =>", pattrib->pkt_len); + netdev_dbg(padapter->pnetdev, "pattrib->pktlen = %d =>", pattrib->pkt_len); for (pp = 0; pp < pattrib->pkt_len; pp++) - printk(" %02x ", pframe[pp]); - printk("\n"); + pr_cont(" %02x ", pframe[pp]); + pr_cont("\n"); } return _SUCCESS; @@ -4872,8 +4872,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) /* set_link_timer(pmlmeext, DISCONNECT_TO); */ } - if (get_iface_type(padapter) == IFACE_PORT0) - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); + rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); } /* currently only adhoc mode will go here */ @@ -5638,7 +5637,7 @@ u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true); /* allow multicast packets to driver */ - padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr); + SetHwReg8723BS(padapter, HW_VAR_ON_RCR_AM, null_addr); return H2C_SUCCESS; } diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index dbfcbac3d85554b43940e17c35b4def3f530202b..c60e179bb2e196fcde02903cb9dd03e59d3d2826 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -73,9 +73,6 @@ int ips_leave(struct adapter *padapter) struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); int ret; - if (!is_primary_adapter(padapter)) - return _SUCCESS; - mutex_lock(&pwrpriv->lock); ret = _ips_leave(padapter); mutex_unlock(&pwrpriv->lock); @@ -455,10 +452,6 @@ void LPS_Enter(struct adapter *padapter, const char *msg) if (n_assoc_iface != 1) return; - /* Skip lps enter request for adapter not port0 */ - if (get_iface_type(padapter) != IFACE_PORT0) - return; - if (!PS_RDY_CHECK(dvobj->padapters)) return; diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index f37fec1efaf91c840d0290e9c40457ccedfa0a9e..73c70b016f00972209ca8d638195b53b8d7acf5e 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -290,21 +290,11 @@ inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch) dvobj->oper_channel = ch; } -inline u8 rtw_get_oper_bw(struct adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_bwmode; -} - inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw) { adapter_to_dvobj(adapter)->oper_bwmode = bw; } -inline u8 rtw_get_oper_choffset(struct adapter *adapter) -{ - return adapter_to_dvobj(adapter)->oper_ch_offset; -} - inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset) { adapter_to_dvobj(adapter)->oper_ch_offset = offset; @@ -445,34 +435,6 @@ void invalidate_cam_all(struct adapter *padapter) spin_unlock_bh(&cam_ctl->lock); } -static u32 _ReadCAM(struct adapter *padapter, u32 addr) -{ - u32 count = 0, cmd; - - cmd = CAM_POLLINIG | addr; - rtw_write32(padapter, RWCAM, cmd); - - do { - if (0 == (rtw_read32(padapter, REG_CAMCMD) & CAM_POLLINIG)) - break; - } while (count++ < 100); - - return rtw_read32(padapter, REG_CAMREAD); -} - -void read_cam(struct adapter *padapter, u8 entry, u8 *get_key) -{ - u32 j, addr, cmd; - - addr = entry << 3; - - for (j = 0; j < 6; j++) { - cmd = _ReadCAM(padapter, addr+j); - if (j > 1) /* get key from cam */ - memcpy(get_key+(j-2)*4, &cmd, 4); - } -} - void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key) { unsigned int i, val, addr; @@ -1613,9 +1575,9 @@ void update_wireless_mode(struct adapter *padapter) SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */ /* change this value if having IOT issues. */ - padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer); + SetHwReg8723BS(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer); - padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode)); + SetHwReg8723BS(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode)); if (pmlmeext->cur_wireless_mode & WIRELESS_11B) update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB); @@ -1822,29 +1784,3 @@ void rtw_release_macid(struct adapter *padapter, struct sta_info *psta) } spin_unlock_bh(&pdvobj->lock); } - -/* For 8188E RA */ -u8 rtw_search_max_mac_id(struct adapter *padapter) -{ - u8 max_mac_id = 0; - struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); - int i; - - spin_lock_bh(&pdvobj->lock); - for (i = (NUM_STA-1); i >= 0 ; i--) { - if (pdvobj->macid[i] == true) - break; - } - max_mac_id = i; - spin_unlock_bh(&pdvobj->lock); - - return max_mac_id; -} - -struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj) -{ - if (get_iface_type(dvobj->padapters[i]) != IFACE_PORT0) - return NULL; - - return dvobj->padapters; -} diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c index 3e88f14e3bf78a2a67c3e61b965cd37845398454..699cff7b0ac9559607f6fb07cc028f3063534225 100644 --- a/drivers/staging/rtl8723bs/core/rtw_xmit.c +++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c @@ -2489,7 +2489,7 @@ int rtw_xmit_thread(void *context) err = _SUCCESS; padapter = context; - thread_enter("RTW_XMIT_THREAD"); + allow_signal(SIGTERM); do { err = rtw_hal_xmit_thread_handler(padapter); diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index 719dd116d8076a7cb6cf8d64167f52af10c4bb51..95fb38283c582a3af51a8aafd320cf18ca9110d7 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c @@ -13,23 +13,20 @@ u8 rtw_hal_data_init(struct adapter *padapter) { - if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */ - padapter->hal_data_sz = sizeof(struct hal_com_data); - padapter->HalData = vzalloc(padapter->hal_data_sz); - if (!padapter->HalData) - return _FAIL; - } + padapter->hal_data_sz = sizeof(struct hal_com_data); + padapter->HalData = vzalloc(padapter->hal_data_sz); + if (!padapter->HalData) + return _FAIL; + return _SUCCESS; } void rtw_hal_data_deinit(struct adapter *padapter) { - if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */ - if (padapter->HalData) { - vfree(padapter->HalData); - padapter->HalData = NULL; - padapter->hal_data_sz = 0; - } + if (padapter->HalData) { + vfree(padapter->HalData); + padapter->HalData = NULL; + padapter->hal_data_sz = 0; } } @@ -796,19 +793,6 @@ u8 GetHalDefVar( return bResult; } -void GetHalODMVar( - struct adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, - void *pValue2 -) -{ - switch (eVariable) { - default: - break; - } -} - void SetHalODMVar( struct adapter *Adapter, enum hal_odm_variable eVariable, @@ -883,7 +867,6 @@ void rtw_hal_check_rxfifo_full(struct adapter *adapter) int save_cnt = false; /* switch counter to RX fifo */ - /* printk("8723b or 8192e , MAC_667 set 0xf0\n"); */ rtw_write8(adapter, REG_RXERR_RPT+3, rtw_read8(adapter, REG_RXERR_RPT+3)|0xf0); save_cnt = true; /* todo: other chips */ @@ -910,10 +893,9 @@ void rtw_dump_raw_rssi_info(struct adapter *padapter) for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) { if (!isCCKrate) { - printk(", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n", - psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]); - } else { - printk("\n"); + netdev_dbg(padapter->pnetdev, ", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n", + psample_pkt_rssi->ofdm_pwr[rf_path], + psample_pkt_rssi->ofdm_snr[rf_path]); } } } diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c index 0a3900548fd2ca05d52ccf4acc73f266f2517ebd..0db8f623b8059ad63046f3516b24895ec520e0c4 100644 --- a/drivers/staging/rtl8723bs/hal/hal_intf.c +++ b/drivers/staging/rtl8723bs/hal/hal_intf.c @@ -9,52 +9,37 @@ void rtw_hal_chip_configure(struct adapter *padapter) { - if (padapter->HalFunc.intf_chip_configure) - padapter->HalFunc.intf_chip_configure(padapter); + rtl8723bs_interface_configure(padapter); } void rtw_hal_read_chip_info(struct adapter *padapter) { - if (padapter->HalFunc.read_adapter_info) - padapter->HalFunc.read_adapter_info(padapter); + ReadAdapterInfo8723BS(padapter); } void rtw_hal_read_chip_version(struct adapter *padapter) { - if (padapter->HalFunc.read_chip_version) - padapter->HalFunc.read_chip_version(padapter); + rtl8723b_read_chip_version(padapter); } void rtw_hal_def_value_init(struct adapter *padapter) { - if (is_primary_adapter(padapter)) - if (padapter->HalFunc.init_default_value) - padapter->HalFunc.init_default_value(padapter); + rtl8723bs_init_default_value(padapter); } void rtw_hal_free_data(struct adapter *padapter) { /* free HAL Data */ rtw_hal_data_deinit(padapter); - - if (is_primary_adapter(padapter)) - if (padapter->HalFunc.free_hal_data) - padapter->HalFunc.free_hal_data(padapter); } void rtw_hal_dm_init(struct adapter *padapter) { - if (is_primary_adapter(padapter)) - if (padapter->HalFunc.dm_init) - padapter->HalFunc.dm_init(padapter); + rtl8723b_init_dm_priv(padapter); } void rtw_hal_dm_deinit(struct adapter *padapter) { - /* cancel dm timer */ - if (is_primary_adapter(padapter)) - if (padapter->HalFunc.dm_deinit) - padapter->HalFunc.dm_deinit(padapter); } static void rtw_hal_init_opmode(struct adapter *padapter) @@ -82,7 +67,7 @@ uint rtw_hal_init(struct adapter *padapter) uint status; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - status = padapter->HalFunc.hal_init(padapter); + status = rtl8723bs_hal_init(padapter); if (status == _SUCCESS) { rtw_hal_init_opmode(padapter); @@ -111,7 +96,7 @@ uint rtw_hal_deinit(struct adapter *padapter) uint status = _SUCCESS; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - status = padapter->HalFunc.hal_deinit(padapter); + status = rtl8723bs_hal_deinit(padapter); if (status == _SUCCESS) { padapter = dvobj->padapters; @@ -123,34 +108,27 @@ uint rtw_hal_deinit(struct adapter *padapter) void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val) { - if (padapter->HalFunc.SetHwRegHandler) - padapter->HalFunc.SetHwRegHandler(padapter, variable, val); + SetHwReg8723BS(padapter, variable, val); } void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val) { - if (padapter->HalFunc.GetHwRegHandler) - padapter->HalFunc.GetHwRegHandler(padapter, variable, val); + GetHwReg8723BS(padapter, variable, val); } void rtw_hal_set_hwreg_with_buf(struct adapter *padapter, u8 variable, u8 *pbuf, int len) { - if (padapter->HalFunc.SetHwRegHandlerWithBuf) - padapter->HalFunc.SetHwRegHandlerWithBuf(padapter, variable, pbuf, len); + SetHwRegWithBuf8723B(padapter, variable, pbuf, len); } u8 rtw_hal_set_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue) { - if (padapter->HalFunc.SetHalDefVarHandler) - return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue); - return _FAIL; + return SetHalDefVar8723BSDIO(padapter, eVariable, pValue); } u8 rtw_hal_get_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue) { - if (padapter->HalFunc.GetHalDefVarHandler) - return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue); - return _FAIL; + return GetHalDefVar8723BSDIO(padapter, eVariable, pValue); } void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet) @@ -161,40 +139,27 @@ void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariab void rtw_hal_enable_interrupt(struct adapter *padapter) { - if (padapter->HalFunc.enable_interrupt) - padapter->HalFunc.enable_interrupt(padapter); + EnableInterrupt8723BSdio(padapter); } void rtw_hal_disable_interrupt(struct adapter *padapter) { - if (padapter->HalFunc.disable_interrupt) - padapter->HalFunc.disable_interrupt(padapter); + DisableInterrupt8723BSdio(padapter); } u8 rtw_hal_check_ips_status(struct adapter *padapter) { - u8 val = false; - - if (padapter->HalFunc.check_ips_status) - val = padapter->HalFunc.check_ips_status(padapter); - - return val; + return CheckIPSStatus(padapter); } s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe) { - if (padapter->HalFunc.hal_xmitframe_enqueue) - return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe); - - return false; + return rtl8723bs_hal_xmitframe_enqueue(padapter, pxmitframe); } s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe) { - if (padapter->HalFunc.hal_xmit) - return padapter->HalFunc.hal_xmit(padapter, pxmitframe); - - return false; + return rtl8723bs_hal_xmit(padapter, pxmitframe); } /* @@ -202,8 +167,6 @@ s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe) */ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe) { - s32 ret = _FAIL; - update_mgntframe_attrib_addr(padapter, pmgntframe); /* pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; */ /* pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; */ @@ -220,36 +183,27 @@ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe) rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe); } - if (padapter->HalFunc.mgnt_xmit) - ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe); - return ret; + return rtl8723bs_mgnt_xmit(padapter, pmgntframe); } s32 rtw_hal_init_xmit_priv(struct adapter *padapter) { - if (padapter->HalFunc.init_xmit_priv) - return padapter->HalFunc.init_xmit_priv(padapter); - return _FAIL; + return rtl8723bs_init_xmit_priv(padapter); } void rtw_hal_free_xmit_priv(struct adapter *padapter) { - if (padapter->HalFunc.free_xmit_priv) - padapter->HalFunc.free_xmit_priv(padapter); + rtl8723bs_free_xmit_priv(padapter); } s32 rtw_hal_init_recv_priv(struct adapter *padapter) { - if (padapter->HalFunc.init_recv_priv) - return padapter->HalFunc.init_recv_priv(padapter); - - return _FAIL; + return rtl8723bs_init_recv_priv(padapter); } void rtw_hal_free_recv_priv(struct adapter *padapter) { - if (padapter->HalFunc.free_recv_priv) - padapter->HalFunc.free_recv_priv(padapter); + rtl8723bs_free_recv_priv(padapter); } void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level) @@ -267,91 +221,70 @@ void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level) if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) add_RATid(padapter, psta, rssi_level); else { - if (padapter->HalFunc.UpdateRAMaskHandler) - padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level); + UpdateHalRAMask8723B(padapter, psta->mac_id, rssi_level); } } void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level) { - if (padapter->HalFunc.Add_RateATid) - padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level); + rtl8723b_Add_RateATid(padapter, bitmap, arg, rssi_level); } /*Start specifical interface thread */ void rtw_hal_start_thread(struct adapter *padapter) { - if (padapter->HalFunc.run_thread) - padapter->HalFunc.run_thread(padapter); + rtl8723b_start_thread(padapter); } /*Start specifical interface thread */ void rtw_hal_stop_thread(struct adapter *padapter) { - if (padapter->HalFunc.cancel_thread) - padapter->HalFunc.cancel_thread(padapter); + rtl8723b_stop_thread(padapter); } u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask) { - u32 data = 0; - - if (padapter->HalFunc.read_bbreg) - data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask); - return data; + return PHY_QueryBBReg_8723B(padapter, RegAddr, BitMask); } void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data) { - if (padapter->HalFunc.write_bbreg) - padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data); + PHY_SetBBReg_8723B(padapter, RegAddr, BitMask, Data); } u32 rtw_hal_read_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask) { - u32 data = 0; - - if (padapter->HalFunc.read_rfreg) - data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask); - return data; + return PHY_QueryRFReg_8723B(padapter, eRFPath, RegAddr, BitMask); } void rtw_hal_write_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data) { - if (padapter->HalFunc.write_rfreg) - padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data); + PHY_SetRFReg_8723B(padapter, eRFPath, RegAddr, BitMask, Data); } void rtw_hal_set_chan(struct adapter *padapter, u8 channel) { - if (padapter->HalFunc.set_channel_handler) - padapter->HalFunc.set_channel_handler(padapter, channel); + PHY_SwChnl8723B(padapter, channel); } void rtw_hal_set_chnl_bw(struct adapter *padapter, u8 channel, enum channel_width Bandwidth, u8 Offset40, u8 Offset80) { - if (padapter->HalFunc.set_chnl_bw_handler) - padapter->HalFunc.set_chnl_bw_handler(padapter, channel, - Bandwidth, Offset40, - Offset80); + PHY_SetSwChnlBWMode8723B(padapter, channel, Bandwidth, Offset40, Offset80); } void rtw_hal_dm_watchdog(struct adapter *padapter) { - if (padapter->HalFunc.hal_dm_watchdog) - padapter->HalFunc.hal_dm_watchdog(padapter); + rtl8723b_HalDmWatchDog(padapter); } void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter) { if (adapter_to_pwrctl(padapter)->fw_current_in_ps_mode) { - if (padapter->HalFunc.hal_dm_watchdog_in_lps) - padapter->HalFunc.hal_dm_watchdog_in_lps(padapter); /* this function caller is in interrupt context */ + rtl8723b_HalDmWatchDog_in_LPS(padapter); /* this function caller is in interrupt context */ } } void beacon_timing_control(struct adapter *padapter) { - if (padapter->HalFunc.SetBeaconRelatedRegistersHandler) - padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter); + rtl8723b_SetBeaconRelatedRegisters(padapter); } diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index ea3b4cd3236035c2086b733a826d93600e7fc693..8d6131f0ad47d9eacda674d15136bbbee8d9c59c 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -417,13 +417,11 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm) u8 i; struct adapter *padapter = pDM_Odm->Adapter; - if (padapter->bDriverStopped) { + if (padapter->bDriverStopped) return; - } - if (!pDM_Odm->bUseRAMask) { + if (!pDM_Odm->bUseRAMask) return; - } for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) { PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[i]; @@ -433,7 +431,6 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm) continue; if (true == ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) { - /* printk("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level); */ rtw_hal_update_ra_mask(pstat, pstat->rssi_level); } @@ -461,9 +458,9 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm) static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm) { - if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK)) { + if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK)) return; - } + odm_RefreshRateAdaptiveMaskCE(pDM_Odm); } @@ -512,7 +509,6 @@ bool ODM_RAStateCheck( RATRState = DM_RATR_STA_MIDDLE; else RATRState = DM_RATR_STA_LOW; - /* printk("==>%s, RATRState:0x%02x , RSSI:%d\n", __func__, RATRState, RSSI); */ if (*pRATRState != RATRState || bForceUpdate) { *pRATRState = RATRState; @@ -593,8 +589,6 @@ static void odm_RSSIMonitorCheckCE(struct dm_odm_t *pDM_Odm) } } - /* printk("%s ==> sta_cnt(%d)\n", __func__, sta_cnt); */ - for (i = 0; i < sta_cnt; i++) { if (PWDB_rssi[i] != (0)) { if (pHalData->fw_ractrl == true)/* Report every sta's RSSI to FW */ diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c index 37ebbbf408ecfddbcc4b08bdaa864b399ba10173..e15ec6452fd0619b5e13a7f32f077436f1667003 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c @@ -53,8 +53,6 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize) u8 *bufferPtr = buffer; u32 i = 0, offset = 0; -/* printk("====>%s %d\n", __func__, __LINE__); */ - /* 3 Phase #1 */ blockCount_p1 = buffSize / blockSize_p1; remainSize_p1 = buffSize % blockSize_p1; @@ -62,7 +60,8 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize) for (i = 0; i < blockCount_p1; i++) { ret = rtw_write32(padapter, (FW_8723B_START_ADDRESS + i * blockSize_p1), *((u32 *)(bufferPtr + i * blockSize_p1))); if (ret == _FAIL) { - printk("====>%s %d i:%d\n", __func__, __LINE__, i); + netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n", + __func__, __LINE__, i); goto exit; } } @@ -85,7 +84,8 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize) ret = rtw_write8(padapter, (FW_8723B_START_ADDRESS + offset + i), *(bufferPtr + offset + i)); if (ret == _FAIL) { - printk("====>%s %d i:%d\n", __func__, __LINE__, i); + netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n", + __func__, __LINE__, i); goto exit; } } @@ -127,7 +127,8 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size) ret = _PageWrite(padapter, page, bufferPtr+offset, MAX_DLFW_PAGE_SIZE); if (ret == _FAIL) { - printk("====>%s %d\n", __func__, __LINE__); + netdev_dbg(padapter->pnetdev, "page write failed at %s %d\n", + __func__, __LINE__); goto exit; } } @@ -138,7 +139,8 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size) ret = _PageWrite(padapter, page, bufferPtr+offset, remainSize); if (ret == _FAIL) { - printk("====>%s %d\n", __func__, __LINE__); + netdev_dbg(padapter->pnetdev, "remaining page write failed at %s %d\n", + __func__, __LINE__); goto exit; } } @@ -439,10 +441,6 @@ void rtl8723b_InitializeFirmwareVars(struct adapter *padapter) /* pHalData->H2CStopInsertQueue = false; */ } -static void rtl8723b_free_hal_data(struct adapter *padapter) -{ -} - /* */ /* Efuse related code */ /* */ @@ -492,7 +490,7 @@ static u8 hal_EfuseSwitchToBank( return bRet; } -static void Hal_GetEfuseDefinition( +void Hal_GetEfuseDefinition( struct adapter *padapter, u8 efuseType, u8 type, @@ -604,46 +602,7 @@ static void Hal_GetEfuseDefinition( #define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */ #define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */ -/* */ -static void Hal_BT_EfusePowerSwitch( - struct adapter *padapter, u8 bWrite, u8 PwrState -) -{ - u8 tempval; - if (PwrState) { - /* enable BT power cut */ - /* 0x6A[14] = 1 */ - tempval = rtw_read8(padapter, 0x6B); - tempval |= BIT(6); - rtw_write8(padapter, 0x6B, tempval); - - /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */ - /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */ - msleep(1); - /* disable BT output isolation */ - /* 0x6A[15] = 0 */ - tempval = rtw_read8(padapter, 0x6B); - tempval &= ~BIT(7); - rtw_write8(padapter, 0x6B, tempval); - } else { - /* enable BT output isolation */ - /* 0x6A[15] = 1 */ - tempval = rtw_read8(padapter, 0x6B); - tempval |= BIT(7); - rtw_write8(padapter, 0x6B, tempval); - - /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */ - /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */ - - /* disable BT power cut */ - /* 0x6A[14] = 1 */ - tempval = rtw_read8(padapter, 0x6B); - tempval &= ~BIT(6); - rtw_write8(padapter, 0x6B, tempval); - } - -} -static void Hal_EfusePowerSwitch( +void Hal_EfusePowerSwitch( struct adapter *padapter, u8 bWrite, u8 PwrState ) { @@ -928,7 +887,7 @@ exit: kfree(efuseTbl); } -static void Hal_ReadEFuse( +void Hal_ReadEFuse( struct adapter *padapter, u8 efuseType, u16 _offset, @@ -1069,7 +1028,6 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest) /* only when bank is switched we have to reset the efuse_addr. */ if (bank != startBank) efuse_addr = 0; -#if 1 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { if (efuse_OneByteRead(padapter, efuse_addr, @@ -1098,33 +1056,6 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest) /* read next header */ efuse_addr += (word_cnts*2)+1; } -#else - while ( - bContinual && - efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) && - AVAILABLE_EFUSE_ADDR(efuse_addr) - ) { - if (efuse_data != 0xFF) { - if ((efuse_data&0x1F) == 0x0F) { /* extended header */ - efuse_addr++; - efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest); - if ((efuse_data & 0x0F) == 0x0F) { - efuse_addr++; - continue; - } else { - hworden = efuse_data & 0x0F; - } - } else { - hworden = efuse_data & 0x0F; - } - word_cnts = Efuse_CalculateWordCnts(hworden); - /* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; - } else - bContinual = false; - } -#endif - /* Check if we need to check next bank efuse */ if (efuse_addr < retU2) @@ -1141,7 +1072,7 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest) return retU2; } -static u16 Hal_EfuseGetCurrentSize( +u16 Hal_EfuseGetCurrentSize( struct adapter *padapter, u8 efuseType, bool bPseudoTest ) { @@ -1220,403 +1151,6 @@ static u8 Hal_EfuseWordEnableDataWrite( return badworden; } -static s32 Hal_EfusePgPacketRead( - struct adapter *padapter, - u8 offset, - u8 *data, - bool bPseudoTest -) -{ - u8 efuse_data, word_cnts = 0; - u16 efuse_addr = 0; - u8 hoffset = 0, hworden = 0; - u8 i; - u8 max_section = 0; - s32 ret; - - - if (!data) - return false; - - EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, &max_section, bPseudoTest); - if (offset > max_section) - return false; - - memset(data, 0xFF, PGPKT_DATA_SIZE); - ret = true; - - /* */ - /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ - /* Skip dummy parts to prevent unexpected data read from Efuse. */ - /* By pass right now. 2009.02.19. */ - /* */ - while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { - if (efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest) == false) { - ret = false; - break; - } - - if (efuse_data == 0xFF) - break; - - if (EXT_HEADER(efuse_data)) { - hoffset = GET_HDR_OFFSET_2_0(efuse_data); - efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest); - if (ALL_WORDS_DISABLED(efuse_data)) - continue; - - hoffset |= ((efuse_data & 0xF0) >> 1); - hworden = efuse_data & 0x0F; - } else { - hoffset = (efuse_data>>4) & 0x0F; - hworden = efuse_data & 0x0F; - } - - if (hoffset == offset) { - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - /* Check word enable condition in the section */ - if (!(hworden & (0x01<<i))) { - efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest); - data[i*2] = efuse_data; - - efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest); - data[(i*2)+1] = efuse_data; - } - } - } else { - word_cnts = Efuse_CalculateWordCnts(hworden); - efuse_addr += word_cnts*2; - } - } - - return ret; -} - -static u8 hal_EfusePgCheckAvailableAddr( - struct adapter *padapter, u8 efuseType, u8 bPseudoTest -) -{ - u16 max_available = 0; - u16 current_size; - - - EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &max_available, bPseudoTest); - - current_size = Efuse_GetCurrentSize(padapter, efuseType, bPseudoTest); - if (current_size >= max_available) - return false; - - return true; -} - -static void hal_EfuseConstructPGPkt( - u8 offset, - u8 word_en, - u8 *pData, - struct pgpkt_struct *pTargetPkt -) -{ - memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE); - pTargetPkt->offset = offset; - pTargetPkt->word_en = word_en; - efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); - pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); -} - -static u8 hal_EfusePartialWriteCheck( - struct adapter *padapter, - u8 efuseType, - u16 *pAddr, - struct pgpkt_struct *pTargetPkt, - u8 bPseudoTest -) -{ - struct hal_com_data *pHalData = GET_HAL_DATA(padapter); - struct efuse_hal *pEfuseHal = &pHalData->EfuseHal; - u8 bRet = false; - u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0; - u8 efuse_data = 0; - - EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_max_available_len, bPseudoTest); - EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max, bPseudoTest); - - if (efuseType == EFUSE_WIFI) { - if (bPseudoTest) { -#ifdef HAL_EFUSE_MEMORY - startAddr = (u16)pEfuseHal->fakeEfuseUsedBytes; -#else - startAddr = (u16)fakeEfuseUsedBytes; -#endif - } else - rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr); - } else { - if (bPseudoTest) { -#ifdef HAL_EFUSE_MEMORY - startAddr = (u16)pEfuseHal->fakeBTEfuseUsedBytes; -#else - startAddr = (u16)fakeBTEfuseUsedBytes; -#endif - } else - rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&startAddr); - } - startAddr %= efuse_max; - - while (1) { - if (startAddr >= efuse_max_available_len) { - bRet = false; - break; - } - - if (efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) { -#if 1 - bRet = false; - break; -#else - if (EXT_HEADER(efuse_data)) { - cur_header = efuse_data; - startAddr++; - efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest); - if (ALL_WORDS_DISABLED(efuse_data)) { - bRet = false; - break; - } else { - curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); - curPkt.word_en = efuse_data & 0x0F; - } - } else { - cur_header = efuse_data; - curPkt.offset = (cur_header>>4) & 0x0F; - curPkt.word_en = cur_header & 0x0F; - } - - curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en); - /* if same header is found but no data followed */ - /* write some part of data followed by the header. */ - if ( - (curPkt.offset == pTargetPkt->offset) && - (hal_EfuseCheckIfDatafollowed(padapter, curPkt.word_cnts, startAddr+1, bPseudoTest) == false) && - wordEnMatched(pTargetPkt, &curPkt, &matched_wden) == true - ) { - /* Here to write partial data */ - badworden = Efuse_WordEnableDataWrite(padapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest); - if (badworden != 0x0F) { - u32 PgWriteSuccess = 0; - /* if write fail on some words, write these bad words again */ - if (efuseType == EFUSE_WIFI) - PgWriteSuccess = Efuse_PgPacketWrite(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest); - else - PgWriteSuccess = Efuse_PgPacketWrite_BT(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest); - - if (!PgWriteSuccess) { - bRet = false; /* write fail, return */ - break; - } - } - /* partial write ok, update the target packet for later use */ - for (i = 0; i < 4; i++) { - if ((matched_wden & (0x1<<i)) == 0) { /* this word has been written */ - pTargetPkt->word_en |= (0x1<<i); /* disable the word */ - } - } - pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); - } - /* read from next header */ - startAddr = startAddr + (curPkt.word_cnts*2) + 1; -#endif - } else { - /* not used header, 0xff */ - *pAddr = startAddr; - bRet = true; - break; - } - } - - return bRet; -} - -static u8 hal_EfusePgPacketWrite1ByteHeader( - struct adapter *padapter, - u8 efuseType, - u16 *pAddr, - struct pgpkt_struct *pTargetPkt, - u8 bPseudoTest -) -{ - u8 pg_header = 0, tmp_header = 0; - u16 efuse_addr = *pAddr; - u8 repeatcnt = 0; - - pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en; - - do { - efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest); - efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest); - if (tmp_header != 0xFF) - break; - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) - return false; - - } while (1); - - if (tmp_header != pg_header) - return false; - - *pAddr = efuse_addr; - - return true; -} - -static u8 hal_EfusePgPacketWrite2ByteHeader( - struct adapter *padapter, - u8 efuseType, - u16 *pAddr, - struct pgpkt_struct *pTargetPkt, - u8 bPseudoTest -) -{ - u16 efuse_addr, efuse_max_available_len = 0; - u8 pg_header = 0, tmp_header = 0; - u8 repeatcnt = 0; - - EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &efuse_max_available_len, bPseudoTest); - - efuse_addr = *pAddr; - if (efuse_addr >= efuse_max_available_len) - return false; - - pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F; - - do { - efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest); - efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest); - if (tmp_header != 0xFF) - break; - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) - return false; - - } while (1); - - if (tmp_header != pg_header) - return false; - - /* to write ext_header */ - efuse_addr++; - pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en; - - do { - efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest); - efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest); - if (tmp_header != 0xFF) - break; - if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) - return false; - - } while (1); - - if (tmp_header != pg_header) /* offset PG fail */ - return false; - - *pAddr = efuse_addr; - - return true; -} - -static u8 hal_EfusePgPacketWriteHeader( - struct adapter *padapter, - u8 efuseType, - u16 *pAddr, - struct pgpkt_struct *pTargetPkt, - u8 bPseudoTest -) -{ - u8 bRet = false; - - if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) - bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest); - else - bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest); - - return bRet; -} - -static u8 hal_EfusePgPacketWriteData( - struct adapter *padapter, - u8 efuseType, - u16 *pAddr, - struct pgpkt_struct *pTargetPkt, - u8 bPseudoTest -) -{ - u16 efuse_addr; - u8 badworden; - - - efuse_addr = *pAddr; - badworden = Efuse_WordEnableDataWrite(padapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest); - if (badworden != 0x0F) - return false; - - return true; -} - -static s32 Hal_EfusePgPacketWrite( - struct adapter *padapter, - u8 offset, - u8 word_en, - u8 *pData, - bool bPseudoTest -) -{ - struct pgpkt_struct targetPkt; - u16 startAddr = 0; - u8 efuseType = EFUSE_WIFI; - - if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest)) - return false; - - hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); - - if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) - return false; - - if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) - return false; - - if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) - return false; - - return true; -} - -static bool Hal_EfusePgPacketWrite_BT( - struct adapter *padapter, - u8 offset, - u8 word_en, - u8 *pData, - bool bPseudoTest -) -{ - struct pgpkt_struct targetPkt; - u16 startAddr = 0; - u8 efuseType = EFUSE_BT; - - if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest)) - return false; - - hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); - - if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) - return false; - - if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) - return false; - - if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest)) - return false; - - return true; -} - static struct hal_version ReadChipVersion8723B(struct adapter *padapter) { u32 value32; @@ -1645,15 +1179,15 @@ static struct hal_version ReadChipVersion8723B(struct adapter *padapter) pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0); pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0); pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT); -#if 1 + dump_chip_info(ChipVersion); -#endif + pHalData->VersionID = ChipVersion; return ChipVersion; } -static void rtl8723b_read_chip_version(struct adapter *padapter) +void rtl8723b_read_chip_version(struct adapter *padapter) { ReadChipVersion8723B(padapter); } @@ -1747,7 +1281,7 @@ static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked rtw_write8(padapter, REG_RD_CTRL+1, 0x6F); } -static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter) +void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter) { u8 val8; u32 value32; @@ -1808,16 +1342,6 @@ static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter) rtw_write8(padapter, bcn_ctrl_reg, val8); } -static void rtl8723b_GetHalODMVar( - struct adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, - void *pValue2 -) -{ - GetHalODMVar(Adapter, eVariable, pValue1, pValue2); -} - static void rtl8723b_SetHalODMVar( struct adapter *Adapter, enum hal_odm_variable eVariable, @@ -1836,7 +1360,7 @@ static void hal_notch_filter_8723b(struct adapter *adapter, bool enable) rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1); } -static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level) +void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level) { u32 mask, rate_bitmap; u8 shortGIrate = false; @@ -1876,49 +1400,9 @@ static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_l void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc) { - pHalFunc->free_hal_data = &rtl8723b_free_hal_data; - - pHalFunc->dm_init = &rtl8723b_init_dm_priv; - - pHalFunc->read_chip_version = &rtl8723b_read_chip_version; - - pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8723B; - - pHalFunc->set_bwmode_handler = &PHY_SetBWMode8723B; - pHalFunc->set_channel_handler = &PHY_SwChnl8723B; - pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8723B; - - pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8723B; - pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8723B; - - pHalFunc->hal_dm_watchdog = &rtl8723b_HalDmWatchDog; - pHalFunc->hal_dm_watchdog_in_lps = &rtl8723b_HalDmWatchDog_in_LPS; - - - pHalFunc->SetBeaconRelatedRegistersHandler = &rtl8723b_SetBeaconRelatedRegisters; - - pHalFunc->Add_RateATid = &rtl8723b_Add_RateATid; - - pHalFunc->run_thread = &rtl8723b_start_thread; - pHalFunc->cancel_thread = &rtl8723b_stop_thread; - - pHalFunc->read_bbreg = &PHY_QueryBBReg_8723B; - pHalFunc->write_bbreg = &PHY_SetBBReg_8723B; - pHalFunc->read_rfreg = &PHY_QueryRFReg_8723B; - pHalFunc->write_rfreg = &PHY_SetRFReg_8723B; - /* Efuse related function */ - pHalFunc->BTEfusePowerSwitch = &Hal_BT_EfusePowerSwitch; - pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch; - pHalFunc->ReadEFuse = &Hal_ReadEFuse; - pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition; - pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize; - pHalFunc->Efuse_PgPacketRead = &Hal_EfusePgPacketRead; - pHalFunc->Efuse_PgPacketWrite = &Hal_EfusePgPacketWrite; pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite; - pHalFunc->Efuse_PgPacketWrite_BT = &Hal_EfusePgPacketWrite_BT; - pHalFunc->GetHalODMVarHandler = &rtl8723b_GetHalODMVar; pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar; pHalFunc->xmit_thread_handler = &hal_xmit_handler; diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index 4ff092b7c9c99a5e69d538c4a23473462297fd2f..d8709d40cb33fe95319dcc3ee838e9acf2f55f2c 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -575,10 +575,6 @@ void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 Channel) PHY_SetTxPowerLevelByPath(Adapter, Channel, RFPath); } -void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel) -{ -} - static void phy_SetRegBW_8723B( struct adapter *Adapter, enum channel_width CurrentBW ) @@ -764,17 +760,6 @@ static void PHY_HandleSwChnlAndSetBW8723B( } } -void PHY_SetBWMode8723B( - struct adapter *Adapter, - enum channel_width Bandwidth, /* 20M or 40M */ - unsigned char Offset /* Upper, Lower, or Don't care */ -) -{ - struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - - PHY_HandleSwChnlAndSetBW8723B(Adapter, false, true, pHalData->CurrentChannel, Bandwidth, Offset, Offset, pHalData->CurrentChannel); -} - /* Call after initialization */ void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel) { diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c index 78298e63edce6e51ddcfaf867e5d7593f1ddbc6b..5dc1c12fe03e5727c325b779b159d616871e1f02 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c @@ -411,14 +411,12 @@ int rtl8723bs_xmit_thread(void *context) s32 ret; struct adapter *padapter; struct xmit_priv *pxmitpriv; - u8 thread_name[20]; ret = _SUCCESS; padapter = context; pxmitpriv = &padapter->xmitpriv; - rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter)); - thread_enter(thread_name); + allow_signal(SIGTERM); do { ret = rtl8723bs_xmit_handler(padapter); diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c index d3aae413fc0f929d1c3c3c86be1bb8b60ee41512..af9a2b068796a74d9e328da8322a875b6cbbc366 100644 --- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c +++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c @@ -583,7 +583,7 @@ static bool HalDetectPwrDownMode(struct adapter *Adapter) return pHalData->pwrdown; } /* HalDetectPwrDownMode */ -static u32 rtl8723bs_hal_init(struct adapter *padapter) +u32 rtl8723bs_hal_init(struct adapter *padapter) { s32 ret; struct hal_com_data *pHalData; @@ -884,7 +884,7 @@ static void CardDisableRTL8723BSdio(struct adapter *padapter) HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_disable_flow); } -static u32 rtl8723bs_hal_deinit(struct adapter *padapter) +u32 rtl8723bs_hal_deinit(struct adapter *padapter) { struct dvobj_priv *psdpriv = padapter->dvobj; struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; @@ -937,17 +937,7 @@ static u32 rtl8723bs_hal_deinit(struct adapter *padapter) return _SUCCESS; } -static u32 rtl8723bs_inirp_init(struct adapter *padapter) -{ - return _SUCCESS; -} - -static u32 rtl8723bs_inirp_deinit(struct adapter *padapter) -{ - return _SUCCESS; -} - -static void rtl8723bs_init_default_value(struct adapter *padapter) +void rtl8723bs_init_default_value(struct adapter *padapter) { struct hal_com_data *pHalData; @@ -960,7 +950,7 @@ static void rtl8723bs_init_default_value(struct adapter *padapter) pHalData->SdioRxFIFOCnt = 0; } -static void rtl8723bs_interface_configure(struct adapter *padapter) +void rtl8723bs_interface_configure(struct adapter *padapter) { struct hal_com_data *pHalData = GET_HAL_DATA(padapter); struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); @@ -1142,7 +1132,7 @@ static s32 _ReadAdapterInfo8723BS(struct adapter *padapter) return _SUCCESS; } -static void ReadAdapterInfo8723BS(struct adapter *padapter) +void ReadAdapterInfo8723BS(struct adapter *padapter) { /* Read EEPROM size before call any EEPROM function */ padapter->EepromAddressSize = GetEEPROMSize8723B(padapter); @@ -1154,7 +1144,7 @@ static void ReadAdapterInfo8723BS(struct adapter *padapter) * If variable not handled here, * some variables will be processed in SetHwReg8723B() */ -static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val) +void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val) { u8 val8; @@ -1195,7 +1185,7 @@ static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val) * If variable not handled here, * some variables will be processed in GetHwReg8723B() */ -static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val) +void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val) { switch (variable) { case HW_VAR_CPWM: @@ -1214,7 +1204,7 @@ static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val) } } -static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len) +void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len) { switch (variable) { case HW_VAR_C2H_HANDLE: @@ -1229,7 +1219,7 @@ static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf /* Description: */ /* Query setting of specified variable. */ /* */ -static u8 GetHalDefVar8723BSDIO( +u8 GetHalDefVar8723BSDIO( struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue ) { @@ -1257,8 +1247,7 @@ static u8 GetHalDefVar8723BSDIO( /* Description: */ /* Change default setting of specified variable. */ /* */ -static u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, - enum hal_def_variable eVariable, void *pValue) +u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue) { return SetHalDefVar8723B(Adapter, eVariable, pValue); } @@ -1269,32 +1258,4 @@ void rtl8723bs_set_hal_ops(struct adapter *padapter) rtl8723b_set_hal_ops(pHalFunc); - pHalFunc->hal_init = &rtl8723bs_hal_init; - pHalFunc->hal_deinit = &rtl8723bs_hal_deinit; - - pHalFunc->inirp_init = &rtl8723bs_inirp_init; - pHalFunc->inirp_deinit = &rtl8723bs_inirp_deinit; - - pHalFunc->init_xmit_priv = &rtl8723bs_init_xmit_priv; - pHalFunc->free_xmit_priv = &rtl8723bs_free_xmit_priv; - - pHalFunc->init_recv_priv = &rtl8723bs_init_recv_priv; - pHalFunc->free_recv_priv = &rtl8723bs_free_recv_priv; - - pHalFunc->init_default_value = &rtl8723bs_init_default_value; - pHalFunc->intf_chip_configure = &rtl8723bs_interface_configure; - pHalFunc->read_adapter_info = &ReadAdapterInfo8723BS; - - pHalFunc->enable_interrupt = &EnableInterrupt8723BSdio; - pHalFunc->disable_interrupt = &DisableInterrupt8723BSdio; - pHalFunc->check_ips_status = &CheckIPSStatus; - pHalFunc->SetHwRegHandler = &SetHwReg8723BS; - pHalFunc->GetHwRegHandler = &GetHwReg8723BS; - pHalFunc->SetHwRegHandlerWithBuf = &SetHwRegWithBuf8723B; - pHalFunc->GetHalDefVarHandler = &GetHalDefVar8723BSDIO; - pHalFunc->SetHalDefVarHandler = &SetHalDefVar8723BSDIO; - - pHalFunc->hal_xmit = &rtl8723bs_hal_xmit; - pHalFunc->mgnt_xmit = &rtl8723bs_mgnt_xmit; - pHalFunc->hal_xmitframe_enqueue = &rtl8723bs_hal_xmitframe_enqueue; } diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index 0b35c97843cc7bc027d626df1ce8d9fe5f6d1bdb..7b0e824e05a9a1727be5f7195841416ccdf753f6 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -182,8 +182,6 @@ struct registry_priv { #include <drv_types_sdio.h> -#define is_primary_adapter(adapter) (1) -#define get_iface_type(adapter) (IFACE_PORT0) #define GET_PRIMARY_ADAPTER(padapter) (((struct adapter *)padapter)->dvobj->if1) #define GET_IFACE_NUMS(padapter) (((struct adapter *)padapter)->dvobj->iface_nums) #define GET_ADAPTER(padapter, iface_id) (((struct adapter *)padapter)->dvobj->padapters[iface_id]) @@ -320,14 +318,6 @@ static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj) return &dvobj->intf_data.func->dev; } -struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj); - -enum { - IFACE_PORT0, /* mapping to port0 for C/D series chips */ - IFACE_PORT1, /* mapping to port1 for C/D series chip */ - MAX_IFACE_PORT, -}; - enum { DRIVER_NORMAL = 0, DRIVER_DISAPPEAR = 1, diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h index 17d5cfb66a365fd292eaa64648e94eaf0c504420..4db93484725f0973430c38c7fdbfcc8caf604137 100644 --- a/drivers/staging/rtl8723bs/include/hal_com.h +++ b/drivers/staging/rtl8723bs/include/hal_com.h @@ -158,10 +158,6 @@ void rtw_dump_raw_rssi_info(struct adapter *padapter); void rtw_bb_rf_gain_offset(struct adapter *padapter); -void GetHalODMVar(struct adapter *Adapter, - enum hal_odm_variable eVariable, - void *pValue1, - void *pValue2); void SetHalODMVar( struct adapter *Adapter, enum hal_odm_variable eVariable, diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h index efdd1f912b5d9e3ad5de6d3b1b8088b5cb4f9d8f..282e141616b0a22fb6b81d9959aeb479332252bd 100644 --- a/drivers/staging/rtl8723bs/include/hal_intf.h +++ b/drivers/staging/rtl8723bs/include/hal_intf.h @@ -162,91 +162,9 @@ enum hal_intf_ps_func { typedef s32 (*c2h_id_filter)(u8 *c2h_evt); struct hal_ops { - u32 (*hal_power_on)(struct adapter *padapter); - void (*hal_power_off)(struct adapter *padapter); - u32 (*hal_init)(struct adapter *padapter); - u32 (*hal_deinit)(struct adapter *padapter); - - void (*free_hal_data)(struct adapter *padapter); - - u32 (*inirp_init)(struct adapter *padapter); - u32 (*inirp_deinit)(struct adapter *padapter); - void (*irp_reset)(struct adapter *padapter); - - s32 (*init_xmit_priv)(struct adapter *padapter); - void (*free_xmit_priv)(struct adapter *padapter); - - s32 (*init_recv_priv)(struct adapter *padapter); - void (*free_recv_priv)(struct adapter *padapter); - - void (*dm_init)(struct adapter *padapter); - void (*dm_deinit)(struct adapter *padapter); - void (*read_chip_version)(struct adapter *padapter); - - void (*init_default_value)(struct adapter *padapter); - - void (*intf_chip_configure)(struct adapter *padapter); - - void (*read_adapter_info)(struct adapter *padapter); - - void (*enable_interrupt)(struct adapter *padapter); - void (*disable_interrupt)(struct adapter *padapter); - u8 (*check_ips_status)(struct adapter *padapter); - s32 (*interrupt_handler)(struct adapter *padapter); - void (*clear_interrupt)(struct adapter *padapter); - void (*set_bwmode_handler)(struct adapter *padapter, enum channel_width Bandwidth, u8 Offset); - void (*set_channel_handler)(struct adapter *padapter, u8 channel); - void (*set_chnl_bw_handler)(struct adapter *padapter, u8 channel, enum channel_width Bandwidth, u8 Offset40, u8 Offset80); - - void (*set_tx_power_level_handler)(struct adapter *padapter, u8 channel); - void (*get_tx_power_level_handler)(struct adapter *padapter, s32 *powerlevel); - - void (*hal_dm_watchdog)(struct adapter *padapter); - void (*hal_dm_watchdog_in_lps)(struct adapter *padapter); - - - void (*SetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val); - void (*GetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val); - - void (*SetHwRegHandlerWithBuf)(struct adapter *padapter, u8 variable, u8 *pbuf, int len); - - u8 (*GetHalDefVarHandler)(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue); - u8 (*SetHalDefVarHandler)(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue); - - void (*GetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, void *pValue2); void (*SetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet); - void (*UpdateRAMaskHandler)(struct adapter *padapter, u32 mac_id, u8 rssi_level); - void (*SetBeaconRelatedRegistersHandler)(struct adapter *padapter); - - void (*Add_RateATid)(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level); - - void (*run_thread)(struct adapter *padapter); - void (*cancel_thread)(struct adapter *padapter); - - u8 (*interface_ps_func)(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val); - - s32 (*hal_xmit)(struct adapter *padapter, struct xmit_frame *pxmitframe); - /* - * mgnt_xmit should be implemented to run in interrupt context - */ - s32 (*mgnt_xmit)(struct adapter *padapter, struct xmit_frame *pmgntframe); - s32 (*hal_xmitframe_enqueue)(struct adapter *padapter, struct xmit_frame *pxmitframe); - - u32 (*read_bbreg)(struct adapter *padapter, u32 RegAddr, u32 BitMask); - void (*write_bbreg)(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data); - u32 (*read_rfreg)(struct adapter *padapter, u8 eRFPath, u32 RegAddr, u32 BitMask); - void (*write_rfreg)(struct adapter *padapter, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data); - - void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite, u8 PwrState); - void (*BTEfusePowerSwitch)(struct adapter *padapter, u8 bWrite, u8 PwrState); - void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest); - void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest); - u16 (*EfuseGetCurrentSize)(struct adapter *padapter, u8 efuseType, bool bPseudoTest); - int (*Efuse_PgPacketRead)(struct adapter *padapter, u8 offset, u8 *data, bool bPseudoTest); - int (*Efuse_PgPacketWrite)(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest); u8 (*Efuse_WordEnableDataWrite)(struct adapter *padapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest); - bool (*Efuse_PgPacketWrite_BT)(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest); s32 (*xmit_thread_handler)(struct adapter *padapter); void (*hal_notch_filter)(struct adapter *adapter, bool enable); @@ -357,4 +275,17 @@ s32 rtw_hal_macid_wakeup(struct adapter *padapter, u32 macid); s32 rtw_hal_fill_h2c_cmd(struct adapter *, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer); +void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val); +void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val); +void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len); +u8 GetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue); +u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue); +void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level); +void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter); +void Hal_EfusePowerSwitch(struct adapter *padapter, u8 bWrite, u8 PwrState); +void Hal_ReadEFuse(struct adapter *padapter, u8 efuseType, u16 _offset, + u16 _size_byte, u8 *pbuf, bool bPseudoTest); +void Hal_GetEfuseDefinition(struct adapter *padapter, u8 efuseType, u8 type, + void *pOut, bool bPseudoTest); +u16 Hal_EfuseGetCurrentSize(struct adapter *padapter, u8 efuseType, bool bPseudoTest); #endif /* __HAL_INTF_H__ */ diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index ea494bcf830b81e5e62053eca557b94478abec0c..07bf0a8d019aa9a1beb4888d6d3cf3b8dbe10390 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -49,13 +49,8 @@ void PHY_SetTxPowerIndex(struct adapter *Adapter, u32 PowerIndex, u8 PHY_GetTxPowerIndex(struct adapter *padapter, u8 RFPath, u8 Rate, enum channel_width BandWidth, u8 Channel); -void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel); - void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 channel); -void PHY_SetBWMode8723B(struct adapter *Adapter, enum channel_width Bandwidth, - unsigned char Offset); - /* Call after initialization */ void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel); diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h index 111e0179712ac6e0b8846c65e30f5dd3716618d0..215ece612f71570ebb4f46383b6f4c216fae7f9d 100644 --- a/drivers/staging/rtl8723bs/include/osdep_intf.h +++ b/drivers/staging/rtl8723bs/include/osdep_intf.h @@ -55,9 +55,6 @@ void rtw_unregister_netdevs(struct dvobj_priv *dvobj); u16 rtw_recv_select_queue(struct sk_buff *skb); -int rtw_ndev_notifier_register(void); -void rtw_ndev_notifier_unregister(void); - void rtw_ips_dev_unload(struct adapter *padapter); int rtw_ips_pwr_up(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h index b21267d7ef7209f4e6c7e3bfd21cb24ef9b41c0b..8b1634f4091ec15971bdc6f5209a2c3a46d1b4db 100644 --- a/drivers/staging/rtl8723bs/include/osdep_service.h +++ b/drivers/staging/rtl8723bs/include/osdep_service.h @@ -73,11 +73,6 @@ int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb); extern void _rtw_init_queue(struct __queue *pqueue); -static inline void thread_enter(char *name) -{ - allow_signal(SIGTERM); -} - static inline void flush_signals_thread(void) { if (signal_pending(current)) diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h index a108ce89bce43298d6a154c403737f6b714c457c..783f64de0aec2325c23166dd00969b2d2e7b6852 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h @@ -87,4 +87,9 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter); void rtl8723b_query_rx_phy_status(union recv_frame *prframe, struct phy_stat *pphy_stat); void rtl8723b_process_phy_info(struct adapter *padapter, void *prframe); +void rtl8723b_read_chip_version(struct adapter *padapter); +void rtl8723bs_init_default_value(struct adapter *padapter); +void rtl8723bs_interface_configure(struct adapter *padapter); +void ReadAdapterInfo8723BS(struct adapter *padapter); + #endif diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h index ad2542d0cabe26ac7fc52137cc961e9f94706937..ac4ca7e05b9bf5fbb8b876c6f00c22953239359f 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h @@ -405,6 +405,8 @@ struct txdesc_8723b { void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem); void rtl8723b_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull, u8 bDataFrame); +u32 rtl8723bs_hal_init(struct adapter *padapter); +u32 rtl8723bs_hal_deinit(struct adapter *padapter); s32 rtl8723bs_init_xmit_priv(struct adapter *padapter); void rtl8723bs_free_xmit_priv(struct adapter *padapter); s32 rtl8723bs_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe); diff --git a/drivers/staging/rtl8723bs/include/rtw_efuse.h b/drivers/staging/rtl8723bs/include/rtw_efuse.h index 0cb8c6f6d34dba0f70f74d4225eb4c8cfda76e5d..d6ea8a4a856f13e103b148d1685037c2875ca101 100644 --- a/drivers/staging/rtl8723bs/include/rtw_efuse.h +++ b/drivers/staging/rtl8723bs/include/rtw_efuse.h @@ -90,16 +90,12 @@ extern u8 fakeBTEfuseInitMap[]; extern u8 fakeBTEfuseModifiedMap[]; /*------------------------Export global variable----------------------------*/ -u16 Efuse_GetCurrentSize(struct adapter *padapter, u8 efuseType, bool bPseudoTest); u8 Efuse_CalculateWordCnts(u8 word_en); void EFUSE_GetEfuseDefinition(struct adapter *padapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest); u8 efuse_OneByteRead(struct adapter *padapter, u16 addr, u8 *data, bool bPseudoTest); u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoTest); void Efuse_PowerSwitch(struct adapter *padapter, u8 bWrite, u8 PwrState); -int Efuse_PgPacketRead(struct adapter *padapter, u8 offset, u8 *data, bool bPseudoTest); -int Efuse_PgPacketWrite(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest); -void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata); u8 Efuse_WordEnableDataWrite(struct adapter *padapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest); u8 EFUSE_Read1Byte(struct adapter *padapter, u16 Address); diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 8315399b64fdb56c02d6503fc7127935d2b3a826..2080408743ef72f81ebe76afc31ba149c2caa9cc 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -447,9 +447,7 @@ void Set_MSR(struct adapter *padapter, u8 type); u8 rtw_get_oper_ch(struct adapter *adapter); void rtw_set_oper_ch(struct adapter *adapter, u8 ch); -u8 rtw_get_oper_bw(struct adapter *adapter); void rtw_set_oper_bw(struct adapter *adapter, u8 bw); -u8 rtw_get_oper_choffset(struct adapter *adapter); void rtw_set_oper_choffset(struct adapter *adapter, u8 offset); u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset); unsigned long rtw_get_on_cur_ch_time(struct adapter *adapter); @@ -459,8 +457,6 @@ void r8723bs_select_channel(struct adapter *padapter, unsigned char channel); unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval); -void read_cam(struct adapter *padapter, u8 entry, u8 *get_key); - /* modify HW only */ void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key); void _clear_cam_entry(struct adapter *padapter, u8 entry); @@ -528,7 +524,6 @@ void rtw_camid_free(struct adapter *adapter, u8 cam_id); extern void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta); extern void rtw_release_macid(struct adapter *padapter, struct sta_info *psta); -extern u8 rtw_search_max_mac_id(struct adapter *padapter); void report_join_res(struct adapter *padapter, int res); void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame); diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h index f94bb18479da5da433738fe9b4e07432660e73a2..5a1cbd2ed8515df19c64a0f1296e4bed61215af7 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mp.h +++ b/drivers/staging/rtl8723bs/include/rtw_mp.h @@ -276,10 +276,6 @@ void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u3 u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz); void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz); -u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask); -void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val); -u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr); -void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val); void SetChannel(struct adapter *padapter); void SetBandwidth(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index b63a74e669bcf24bad9b2c273f11b9622f2aa451..c053ee9c1361c48901edcd0c7d5939d12778c3d7 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -581,7 +581,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(txkey, &(param->u.crypt.key[16]), 8); memcpy(rxkey, &(param->u.crypt.key[24]), 8); @@ -626,7 +625,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { psta->dot118021XPrivacy = _TKIP_; - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8); memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8); @@ -657,7 +655,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(txkey, &(param->u.crypt.key[16]), 8); memcpy(rxkey, &(param->u.crypt.key[24]), 8); @@ -785,7 +782,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */ - /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */ memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8); memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8); @@ -806,10 +802,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param } else if (strcmp(param->u.crypt.alg, "BIP") == 0) { /* save the IGTK key, length 16 bytes */ memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - /* - for (no = 0;no<16;no++) - printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]); - */ padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx; padapter->securitypriv.binstallBIPkey = true; } @@ -817,9 +809,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param } pbcmc_sta = rtw_get_bcmc_stainfo(padapter); - if (!pbcmc_sta) { - /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */ - } else { + if (pbcmc_sta) { /* Jeff: don't disable ieee8021x_blocked while clearing key */ if (strcmp(param->u.crypt.alg, "none") != 0) pbcmc_sta->ieee8021x_blocked = false; diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index a9e481e182ad6c6ad8fd5ce7bdbee1cfb3069ab4..793b051536f324a65f43d3c16e828078f472bd5c 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -138,9 +138,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); - if (!psta) { - /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */ - } else { + if (psta) { /* Jeff: don't disable ieee8021x_blocked while clearing key */ if (strcmp(param->u.crypt.alg, "none") != 0) psta->ieee8021x_blocked = false; @@ -154,7 +152,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */ - /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */ memcpy(psta->dot11tkiptxmickey.skey, ¶m->u.crypt.key[16], 8); memcpy(psta->dot11tkiprxmickey.skey, ¶m->u.crypt.key[24], 8); @@ -177,13 +174,8 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true); } else if (strcmp(param->u.crypt.alg, "BIP") == 0) { - /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */ /* save the IGTK key, length 16 bytes */ memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - /*printk("IGTK key below:\n"); - for (no = 0;no<16;no++) - printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]); - printk("\n");*/ padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx; padapter->securitypriv.binstallBIPkey = true; } @@ -191,9 +183,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, } pbcmc_sta = rtw_get_bcmc_stainfo(padapter); - if (!pbcmc_sta) { - /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */ - } else { + if (pbcmc_sta) { /* Jeff: don't disable ieee8021x_blocked while clearing key */ if (strcmp(param->u.crypt.alg, "none") != 0) pbcmc_sta->ieee8021x_blocked = false; @@ -629,7 +619,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(txkey, ¶m->u.crypt.key[16], 8); memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, ¶m->u.crypt.key[24], 8); @@ -674,7 +663,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { psta->dot118021XPrivacy = _TKIP_; - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(psta->dot11tkiptxmickey.skey, ¶m->u.crypt.key[16], 8); memcpy(psta->dot11tkiprxmickey.skey, ¶m->u.crypt.key[24], 8); @@ -703,7 +691,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len)); - /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */ /* set mic key */ memcpy(txkey, ¶m->u.crypt.key[16], 8); memcpy(rxkey, ¶m->u.crypt.key[24], 8); diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index fc9b9c5efb50e183f239cdb2e50a83c0bd5bb9b2..4e1917c054029157b07c6d3c6e2e311c52b0aa7a 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -381,34 +381,6 @@ u16 rtw_recv_select_queue(struct sk_buff *skb) return rtw_1d_to_queue[priority]; } -static int rtw_ndev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr) -{ - struct net_device *dev = netdev_notifier_info_to_dev(ptr); - - if (dev->netdev_ops->ndo_do_ioctl != rtw_ioctl) - return NOTIFY_DONE; - - netdev_dbg(dev, FUNC_NDEV_FMT " state:%lu\n", FUNC_NDEV_ARG(dev), - state); - - return NOTIFY_DONE; -} - -static struct notifier_block rtw_ndev_notifier = { - .notifier_call = rtw_ndev_notifier_call, -}; - -int rtw_ndev_notifier_register(void) -{ - return register_netdevice_notifier(&rtw_ndev_notifier); -} - -void rtw_ndev_notifier_unregister(void) -{ - unregister_netdevice_notifier(&rtw_ndev_notifier); -} - - static int rtw_ndev_init(struct net_device *dev) { struct adapter *adapter = rtw_netdev_priv(dev); @@ -633,8 +605,7 @@ void rtw_reset_drv_sw(struct adapter *padapter) struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); /* hal_priv */ - if (is_primary_adapter(padapter)) - rtw_hal_def_value_init(padapter); + rtw_hal_def_value_init(padapter); RTW_ENABLE_FUNC(padapter, DF_RX_BIT); RTW_ENABLE_FUNC(padapter, DF_TX_BIT); diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index d18fde4e5d6ceaf0c3e8e26a6c605ba2fa883f53..5a7238e661ffbea6b0f0236a730f762a2e7abca2 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -72,7 +72,7 @@ static int sdio_alloc_irq(struct dvobj_priv *dvobj) err = sdio_claim_irq(func, &sd_sync_int_hdl); if (err) { dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++; - printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err); + netdev_crit(dvobj->if1->pnetdev, "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err); } else { dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++; dvobj->irq_alloc = 1; @@ -382,7 +382,6 @@ static int rtw_drv_init( if (sdio_alloc_irq(dvobj) != _SUCCESS) goto free_if1; - rtw_ndev_notifier_register(); status = _SUCCESS; free_if1: @@ -484,22 +483,12 @@ static int rtw_sdio_resume(struct device *dev) static int __init rtw_drv_entry(void) { - int ret; - - ret = sdio_register_driver(&rtl8723bs_sdio_driver); - if (ret != 0) - rtw_ndev_notifier_unregister(); - - return ret; + return sdio_register_driver(&rtl8723bs_sdio_driver); } +module_init(rtw_drv_entry); static void __exit rtw_drv_halt(void) { sdio_unregister_driver(&rtl8723bs_sdio_driver); - - rtw_ndev_notifier_unregister(); } - - -module_init(rtw_drv_entry); module_exit(rtw_drv_halt); diff --git a/drivers/staging/rts5208/Kconfig b/drivers/staging/rts5208/Kconfig deleted file mode 100644 index b864023d3ccb5847c54bab0f93afaf86fdd99ba5..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config RTS5208 - tristate "Realtek PCI-E Card Reader RTS5208/5288 support" - depends on PCI && SCSI - help - Say Y here to include driver code to support the Realtek - PCI-E card reader rts5208/rts5288. - - If this driver is compiled as a module, it will be named rts5208. diff --git a/drivers/staging/rts5208/Makefile b/drivers/staging/rts5208/Makefile deleted file mode 100644 index 3c9e9797d3d936a5f5d14ad8aa24abb4a36fc9b1..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_RTS5208) := rts5208.o - -rts5208-y := rtsx.o rtsx_chip.o rtsx_transport.o rtsx_scsi.o \ - rtsx_card.o general.o sd.o xd.o ms.o spi.o diff --git a/drivers/staging/rts5208/TODO b/drivers/staging/rts5208/TODO deleted file mode 100644 index 9cec0d8dd0b6cad6d8890d9bae1357629a25f6b2..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: -- use kernel coding style -- checkpatch.pl fixes -- We will use the stack in drivers/mmc to implement - rts5208/5288 in the future - -Micky Ching <micky_ching@realsil.com.cn> diff --git a/drivers/staging/rts5208/general.c b/drivers/staging/rts5208/general.c deleted file mode 100644 index 0f912b011064f195203223306d04f1bf7e9a474a..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/general.c +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include "general.h" - -int bit1cnt_long(u32 data) -{ - int i, cnt = 0; - - for (i = 0; i < 32; i++) { - if (data & 0x01) - cnt++; - data >>= 1; - } - return cnt; -} - diff --git a/drivers/staging/rts5208/general.h b/drivers/staging/rts5208/general.h deleted file mode 100644 index 53e2dbabf04b7b57db85bfe576e0158a042ef049..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/general.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __RTSX_GENERAL_H -#define __RTSX_GENERAL_H - -#include "rtsx.h" - -int bit1cnt_long(u32 data); - -#endif /* __RTSX_GENERAL_H */ diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c deleted file mode 100644 index bfeb5873bf3baafb791f38f597b91545e90a5400..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/ms.c +++ /dev/null @@ -1,4311 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/vmalloc.h> - -#include "rtsx.h" -#include "ms.h" - -static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct ms_info *ms_card = &chip->ms_card; - - ms_card->err_code = err_code; -} - -static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct ms_info *ms_card = &chip->ms_card; - - return (ms_card->err_code == err_code); -} - -static int ms_parse_err_code(struct rtsx_chip *chip) -{ - return STATUS_FAIL; -} - -static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, - u8 tpc, u8 cnt, u8 cfg) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - u8 *ptr; - - dev_dbg(rtsx_dev(chip), "%s: tpc = 0x%x\n", __func__, tpc); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, - 0xFF, MS_TRANSFER_START | trans_mode); - rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0); - - retval = rtsx_send_cmd(chip, MS_CARD, 5000); - if (retval < 0) { - rtsx_clear_ms_error(chip); - ms_set_err_code(chip, MS_TO_ERROR); - return ms_parse_err_code(chip); - } - - ptr = rtsx_get_cmd_data(chip) + 1; - - if (!(tpc & 0x08)) { /* Read Packet */ - if (*ptr & MS_CRC16_ERR) { - ms_set_err_code(chip, MS_CRC16_ERROR); - return ms_parse_err_code(chip); - } - } else { /* Write Packet */ - if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) { - if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - return ms_parse_err_code(chip); - } - } - } - - if (*ptr & MS_RDY_TIMEOUT) { - rtsx_clear_ms_error(chip); - ms_set_err_code(chip, MS_TO_ERROR); - return ms_parse_err_code(chip); - } - - return STATUS_SUCCESS; -} - -static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, - u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k, - int use_sg, void *buf, int buf_len) -{ - int retval; - u8 val, err_code = 0; - enum dma_data_direction dir; - - if (!buf || !buf_len) - return STATUS_FAIL; - - if (trans_mode == MS_TM_AUTO_READ) { - dir = DMA_FROM_DEVICE; - err_code = MS_FLASH_READ_ERROR; - } else if (trans_mode == MS_TM_AUTO_WRITE) { - dir = DMA_TO_DEVICE; - err_code = MS_FLASH_WRITE_ERROR; - } else { - return STATUS_FAIL; - } - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rtsx_add_cmd(chip, WRITE_REG_CMD, - MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - - if (mode_2k) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - MS_CFG, MS_2K_SECTOR_MODE, MS_2K_SECTOR_MODE); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, 0); - } - - trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, - MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode); - rtsx_add_cmd(chip, CHECK_REG_CMD, - MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, MS_CARD, buf, buf_len, - use_sg, dir, chip->mspro_timeout); - if (retval < 0) { - ms_set_err_code(chip, err_code); - if (retval == -ETIMEDOUT) - retval = STATUS_TIMEDOUT; - else - retval = STATUS_FAIL; - - return retval; - } - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); - if (retval) - return retval; - - if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_write_bytes(struct rtsx_chip *chip, - u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - - if (!data || data_len < cnt) - return STATUS_ERROR; - - rtsx_init_cmd(chip); - - for (i = 0; i < cnt; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, data[i]); - } - if (cnt % 2) - rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, - MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES); - rtsx_add_cmd(chip, CHECK_REG_CMD, - MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); - - retval = rtsx_send_cmd(chip, MS_CARD, 5000); - if (retval < 0) { - u8 val = 0; - - rtsx_read_register(chip, MS_TRANS_CFG, &val); - dev_dbg(rtsx_dev(chip), "MS_TRANS_CFG: 0x%02x\n", val); - - rtsx_clear_ms_error(chip); - - if (!(tpc & 0x08)) { - if (val & MS_CRC16_ERR) { - ms_set_err_code(chip, MS_CRC16_ERROR); - return ms_parse_err_code(chip); - } - } else { - if (CHK_MSPRO(ms_card) && !(val & 0x80)) { - if (val & (MS_INT_ERR | MS_INT_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - return ms_parse_err_code(chip); - } - } - } - - if (val & MS_RDY_TIMEOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - return ms_parse_err_code(chip); - } - - ms_set_err_code(chip, MS_TO_ERROR); - return ms_parse_err_code(chip); - } - - return STATUS_SUCCESS; -} - -static int ms_read_bytes(struct rtsx_chip *chip, - u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 *ptr; - - if (!data) - return STATUS_ERROR; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_READ_BYTES); - rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - for (i = 0; i < data_len - 1; i++) - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0); - - if (data_len % 2) - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0); - else - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, - 0, 0); - - retval = rtsx_send_cmd(chip, MS_CARD, 5000); - if (retval < 0) { - u8 val = 0; - - rtsx_read_register(chip, MS_TRANS_CFG, &val); - rtsx_clear_ms_error(chip); - - if (!(tpc & 0x08)) { - if (val & MS_CRC16_ERR) { - ms_set_err_code(chip, MS_CRC16_ERROR); - return ms_parse_err_code(chip); - } - } else { - if (CHK_MSPRO(ms_card) && !(val & 0x80)) { - if (val & (MS_INT_ERR | MS_INT_CMDNK)) { - ms_set_err_code(chip, MS_CMD_NK); - return ms_parse_err_code(chip); - } - } - } - - if (val & MS_RDY_TIMEOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - return ms_parse_err_code(chip); - } - - ms_set_err_code(chip, MS_TO_ERROR); - return ms_parse_err_code(chip); - } - - ptr = rtsx_get_cmd_data(chip) + 1; - - for (i = 0; i < data_len; i++) - data[i] = ptr[i]; - - if (tpc == PRO_READ_SHORT_DATA && data_len == 8) { - dev_dbg(rtsx_dev(chip), "Read format progress:\n"); - print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, ptr, - cnt); - } - - return STATUS_SUCCESS; -} - -static int ms_set_rw_reg_addr(struct rtsx_chip *chip, u8 read_start, - u8 read_cnt, u8 write_start, u8 write_cnt) -{ - int retval, i; - u8 data[4]; - - data[0] = read_start; - data[1] = read_cnt; - data[2] = write_start; - data[3] = write_cnt; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, SET_RW_REG_ADRS, 4, - NO_WAIT_INT, data, 4); - if (retval == STATUS_SUCCESS) - return STATUS_SUCCESS; - rtsx_clear_ms_error(chip); - } - - return STATUS_FAIL; -} - -static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg) -{ - u8 data[2]; - - data[0] = cmd; - data[1] = 0; - - return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1); -} - -static int ms_set_init_para(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - - if (CHK_HG8BIT(ms_card)) { - if (chip->asic_code) - ms_card->ms_clock = chip->asic_ms_hg_clk; - else - ms_card->ms_clock = chip->fpga_ms_hg_clk; - - } else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) { - if (chip->asic_code) - ms_card->ms_clock = chip->asic_ms_4bit_clk; - else - ms_card->ms_clock = chip->fpga_ms_4bit_clk; - - } else { - if (chip->asic_code) - ms_card->ms_clock = chip->asic_ms_1bit_clk; - else - ms_card->ms_clock = chip->fpga_ms_1bit_clk; - } - - retval = switch_clock(chip, ms_card->ms_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_switch_clock(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - - retval = select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = switch_clock(chip, ms_card->ms_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_pull_ctl_disable(struct rtsx_chip *chip) -{ - int retval; - - if (CHECK_PID(chip, 0x5208)) { - retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF, - MS_D1_PD | MS_D2_PD | MS_CLK_PD | - MS_D6_PD); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, - MS_D3_PD | MS_D0_PD | MS_BS_PD | - XD_D4_PD); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF, - MS_D7_PD | XD_CE_PD | XD_CLE_PD | - XD_CD_PU); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | - XD_ALE_PD); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | - SD_CMD_PD); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - if (retval) - return retval; - - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - retval = rtsx_write_register(chip, CARD_PULL_CTL1, - 0xFF, 0x55); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL2, - 0xFF, 0x55); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL3, - 0xFF, 0x4B); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_PULL_CTL4, - 0xFF, 0x69); - if (retval) - return retval; - } - } - - return STATUS_SUCCESS; -} - -static int ms_pull_ctl_enable(struct rtsx_chip *chip) -{ - int retval; - - rtsx_init_cmd(chip); - - if (CHECK_PID(chip, 0x5208)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - CARD_PULL_CTL1, 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, - CARD_PULL_CTL2, 0xFF, 0x45); - rtsx_add_cmd(chip, WRITE_REG_CMD, - CARD_PULL_CTL3, 0xFF, 0x4B); - rtsx_add_cmd(chip, WRITE_REG_CMD, - CARD_PULL_CTL4, 0xFF, 0x29); - } - } - - retval = rtsx_send_cmd(chip, MS_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_prepare_reset(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - u8 oc_mask = 0; - - ms_card->ms_type = 0; - ms_card->check_ms_flow = 0; - ms_card->switch_8bit_fail = 0; - ms_card->delay_write.delay_write_flag = 0; - - ms_card->pro_under_formatting = 0; - - retval = ms_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!chip->ft2_fast_mode) - wait_timeout(250); - - retval = enable_card_clock(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (chip->asic_code) { - retval = ms_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_MS_PULL_CTL_BIT | 0x20, 0); - if (retval) - return retval; - } - - if (!chip->ft2_fast_mode) { - retval = card_power_on(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - wait_timeout(150); - -#ifdef SUPPORT_OCP - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) - oc_mask = MS_OC_NOW | MS_OC_EVER; - else - oc_mask = SD_OC_NOW | SD_OC_EVER; - - if (chip->ocp_stat & oc_mask) { - dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - return STATUS_FAIL; - } -#endif - } - - retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, - MS_OUTPUT_EN); - if (retval) - return retval; - - if (chip->asic_code) { - retval = rtsx_write_register(chip, MS_CFG, 0xFF, - SAMPLE_TIME_RISING | - PUSH_TIME_DEFAULT | - NO_EXTEND_TOGGLE | - MS_BUS_WIDTH_1); - if (retval) - return retval; - - } else { - retval = rtsx_write_register(chip, MS_CFG, 0xFF, - SAMPLE_TIME_FALLING | - PUSH_TIME_DEFAULT | - NO_EXTEND_TOGGLE | - MS_BUS_WIDTH_1); - if (retval) - return retval; - } - retval = rtsx_write_register(chip, MS_TRANS_CFG, 0xFF, - NO_WAIT_INT | NO_AUTO_READ_INT_REG); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, - MS_STOP | MS_CLR_ERR); - if (retval) - return retval; - - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 val; - - retval = ms_set_rw_reg_addr(chip, PRO_STATUS_REG, 6, SYSTEM_PARAM, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, - 6, NO_WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - retval = rtsx_read_register(chip, PPBUF_BASE2 + 2, &val); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "Type register: 0x%x\n", val); - if (val != 0x01) { - if (val != 0x02) - ms_card->check_ms_flow = 1; - - return STATUS_FAIL; - } - - retval = rtsx_read_register(chip, PPBUF_BASE2 + 4, &val); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "Category register: 0x%x\n", val); - if (val != 0) { - ms_card->check_ms_flow = 1; - return STATUS_FAIL; - } - - retval = rtsx_read_register(chip, PPBUF_BASE2 + 5, &val); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "Class register: 0x%x\n", val); - if (val == 0) { - retval = rtsx_read_register(chip, PPBUF_BASE2, &val); - if (retval) - return retval; - - if (val & WRT_PRTCT) - chip->card_wp |= MS_CARD; - else - chip->card_wp &= ~MS_CARD; - - } else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) { - chip->card_wp |= MS_CARD; - } else { - ms_card->check_ms_flow = 1; - return STATUS_FAIL; - } - - ms_card->ms_type |= TYPE_MSPRO; - - retval = rtsx_read_register(chip, PPBUF_BASE2 + 3, &val); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "IF Mode register: 0x%x\n", val); - if (val == 0) { - ms_card->ms_type &= 0x0F; - } else if (val == 7) { - if (switch_8bit_bus) - ms_card->ms_type |= MS_HG; - else - ms_card->ms_type &= 0x0F; - - } else { - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int ms_confirm_cpu_startup(struct rtsx_chip *chip) -{ - int retval, i, k; - u8 val; - - /* Confirm CPU StartUp */ - k = 0; - do { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_read_bytes(chip, GET_INT, 1, - NO_WAIT_INT, &val, 1); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - if (k > 100) - return STATUS_FAIL; - - k++; - wait_timeout(100); - } while (!(val & INT_REG_CED)); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - if (val & INT_REG_ERR) { - if (val & INT_REG_CMDNK) - chip->card_wp |= (MS_CARD); - else - return STATUS_FAIL; - } - /* -- end confirm CPU startup */ - - return STATUS_SUCCESS; -} - -static int ms_switch_parallel_bus(struct rtsx_chip *chip) -{ - int retval, i; - u8 data[2]; - - data[0] = PARALLEL_4BIT_IF; - data[1] = 0; - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, - data, 2); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_switch_8bit_bus(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 data[2]; - - data[0] = PARALLEL_8BIT_IF; - data[1] = 0; - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, WRITE_REG, 1, - NO_WAIT_INT, data, 2); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, MS_CFG, 0x98, - MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING); - if (retval) - return retval; - - ms_card->ms_type |= MS_8BIT; - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, - 1, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - - for (i = 0; i < 3; i++) { - retval = ms_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_identify_media_type(chip, switch_8bit_bus); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_confirm_cpu_startup(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_switch_parallel_bus(chip); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - continue; - } else { - break; - } - } - - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - /* Switch MS-PRO into Parallel mode */ - retval = rtsx_write_register(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4); - if (retval) - return retval; - - retval = rtsx_write_register(chip, MS_CFG, PUSH_TIME_ODD, - PUSH_TIME_ODD); - if (retval) - return retval; - - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - /* If MSPro HG Card, We shall try to switch to 8-bit bus */ - if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) { - retval = ms_switch_8bit_bus(chip); - if (retval != STATUS_SUCCESS) { - ms_card->switch_8bit_fail = 1; - return STATUS_FAIL; - } - } - - return STATUS_SUCCESS; -} - -#ifdef XC_POWERCLASS -static int msxc_change_power(struct rtsx_chip *chip, u8 mode) -{ - int retval; - u8 buf[6]; - - ms_cleanup_work(chip); - - retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf[0] = 0; - buf[1] = mode; - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = 0; - - retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_read_register(chip, MS_TRANS_CFG, buf); - if (retval) - return retval; - - if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} -#endif - -static int ms_read_attribute_info(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 val, *buf, class_code, device_type, sub_class, data[16]; - u16 total_blk = 0, blk_size = 0; -#ifdef SUPPORT_MSXC - u32 xc_total_blk = 0, xc_blk_size = 0; -#endif - u32 sys_info_addr = 0, sys_info_size; -#ifdef SUPPORT_PCGL_1P18 - u32 model_name_addr = 0, model_name_size; - int found_sys_info = 0, found_model_name = 0; -#endif - - retval = ms_set_rw_reg_addr(chip, PRO_INT_REG, 2, PRO_SYSTEM_PARAM, 7); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_MS8BIT(ms_card)) - data[0] = PARALLEL_8BIT_IF; - else - data[0] = PARALLEL_4BIT_IF; - - data[1] = 0; - - data[2] = 0x40; - data[3] = 0; - data[4] = 0; - data[5] = 0; - data[6] = 0; - data[7] = 0; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT, - data, 8); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf = kmalloc(64 * 512, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT); - if (retval != STATUS_SUCCESS) - continue; - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - if (!(val & MS_INT_BREQ)) { - kfree(buf); - return STATUS_FAIL; - } - retval = ms_transfer_data(chip, MS_TM_AUTO_READ, - PRO_READ_LONG_DATA, 0x40, WAIT_INT, - 0, 0, buf, 64 * 512); - if (retval == STATUS_SUCCESS) - break; - - rtsx_clear_ms_error(chip); - } - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - i = 0; - do { - retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - if ((val & MS_INT_CED) || !(val & MS_INT_BREQ)) - break; - - retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, - PRO_READ_LONG_DATA, 0, WAIT_INT); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - i++; - } while (i < 1024); - - if (buf[0] != 0xa5 && buf[1] != 0xc3) { - /* Signature code is wrong */ - kfree(buf); - return STATUS_FAIL; - } - - if (buf[4] < 1 || buf[4] > 12) { - kfree(buf); - return STATUS_FAIL; - } - - for (i = 0; i < buf[4]; i++) { - int cur_addr_off = 16 + i * 12; - -#ifdef SUPPORT_MSXC - if (buf[cur_addr_off + 8] == 0x10 || - buf[cur_addr_off + 8] == 0x13) { -#else - if (buf[cur_addr_off + 8] == 0x10) { -#endif - sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) | - ((u32)buf[cur_addr_off + 1] << 16) | - ((u32)buf[cur_addr_off + 2] << 8) | - buf[cur_addr_off + 3]; - sys_info_size = ((u32)buf[cur_addr_off + 4] << 24) | - ((u32)buf[cur_addr_off + 5] << 16) | - ((u32)buf[cur_addr_off + 6] << 8) | - buf[cur_addr_off + 7]; - dev_dbg(rtsx_dev(chip), "sys_info_addr = 0x%x, sys_info_size = 0x%x\n", - sys_info_addr, sys_info_size); - if (sys_info_size != 96) { - kfree(buf); - return STATUS_FAIL; - } - if (sys_info_addr < 0x1A0) { - kfree(buf); - return STATUS_FAIL; - } - if ((sys_info_size + sys_info_addr) > 0x8000) { - kfree(buf); - return STATUS_FAIL; - } - -#ifdef SUPPORT_MSXC - if (buf[cur_addr_off + 8] == 0x13) - ms_card->ms_type |= MS_XC; -#endif -#ifdef SUPPORT_PCGL_1P18 - found_sys_info = 1; -#else - break; -#endif - } -#ifdef SUPPORT_PCGL_1P18 - if (buf[cur_addr_off + 8] == 0x15) { - model_name_addr = ((u32)buf[cur_addr_off + 0] << 24) | - ((u32)buf[cur_addr_off + 1] << 16) | - ((u32)buf[cur_addr_off + 2] << 8) | - buf[cur_addr_off + 3]; - model_name_size = ((u32)buf[cur_addr_off + 4] << 24) | - ((u32)buf[cur_addr_off + 5] << 16) | - ((u32)buf[cur_addr_off + 6] << 8) | - buf[cur_addr_off + 7]; - dev_dbg(rtsx_dev(chip), "model_name_addr = 0x%x, model_name_size = 0x%x\n", - model_name_addr, model_name_size); - if (model_name_size != 48) { - kfree(buf); - return STATUS_FAIL; - } - if (model_name_addr < 0x1A0) { - kfree(buf); - return STATUS_FAIL; - } - if ((model_name_size + model_name_addr) > 0x8000) { - kfree(buf); - return STATUS_FAIL; - } - - found_model_name = 1; - } - - if (found_sys_info && found_model_name) - break; -#endif - } - - if (i == buf[4]) { - kfree(buf); - return STATUS_FAIL; - } - - class_code = buf[sys_info_addr + 0]; - device_type = buf[sys_info_addr + 56]; - sub_class = buf[sys_info_addr + 46]; -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) { - xc_total_blk = ((u32)buf[sys_info_addr + 6] << 24) | - ((u32)buf[sys_info_addr + 7] << 16) | - ((u32)buf[sys_info_addr + 8] << 8) | - buf[sys_info_addr + 9]; - xc_blk_size = ((u32)buf[sys_info_addr + 32] << 24) | - ((u32)buf[sys_info_addr + 33] << 16) | - ((u32)buf[sys_info_addr + 34] << 8) | - buf[sys_info_addr + 35]; - dev_dbg(rtsx_dev(chip), "xc_total_blk = 0x%x, xc_blk_size = 0x%x\n", - xc_total_blk, xc_blk_size); - } else { - total_blk = ((u16)buf[sys_info_addr + 6] << 8) | - buf[sys_info_addr + 7]; - blk_size = ((u16)buf[sys_info_addr + 2] << 8) | - buf[sys_info_addr + 3]; - dev_dbg(rtsx_dev(chip), "total_blk = 0x%x, blk_size = 0x%x\n", - total_blk, blk_size); - } -#else - total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7]; - blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3]; - dev_dbg(rtsx_dev(chip), "total_blk = 0x%x, blk_size = 0x%x\n", - total_blk, blk_size); -#endif - - dev_dbg(rtsx_dev(chip), "class_code = 0x%x, device_type = 0x%x, sub_class = 0x%x\n", - class_code, device_type, sub_class); - - memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96); -#ifdef SUPPORT_PCGL_1P18 - memcpy(ms_card->raw_model_name, buf + model_name_addr, 48); -#endif - - kfree(buf); - -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) { - if (class_code != 0x03) - return STATUS_FAIL; - } else { - if (class_code != 0x02) - return STATUS_FAIL; - } -#else - if (class_code != 0x02) - return STATUS_FAIL; -#endif - - if (device_type != 0x00) { - if (device_type == 0x01 || device_type == 0x02 || - device_type == 0x03) { - chip->card_wp |= MS_CARD; - } else { - return STATUS_FAIL; - } - } - - if (sub_class & 0xC0) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n", - class_code, device_type, sub_class); - -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) { - chip->capacity[chip->card2lun[MS_CARD]] = - ms_card->capacity = xc_total_blk * xc_blk_size; - } else { - chip->capacity[chip->card2lun[MS_CARD]] = - ms_card->capacity = total_blk * blk_size; - } -#else - ms_card->capacity = total_blk * blk_size; - chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity; -#endif - - return STATUS_SUCCESS; -} - -#ifdef SUPPORT_MAGIC_GATE -static int mg_set_tpc_para_sub(struct rtsx_chip *chip, - int type, u8 mg_entry_num); -#endif - -static int reset_ms_pro(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; -#ifdef XC_POWERCLASS - u8 change_power_class; - - if (chip->ms_power_class_en & 0x02) - change_power_class = 2; - else if (chip->ms_power_class_en & 0x01) - change_power_class = 1; - else - change_power_class = 0; -#endif - -#ifdef XC_POWERCLASS -retry: -#endif - retval = ms_pro_reset_flow(chip, 1); - if (retval != STATUS_SUCCESS) { - if (ms_card->switch_8bit_fail) { - retval = ms_pro_reset_flow(chip, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - return STATUS_FAIL; - } - } - - retval = ms_read_attribute_info(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - -#ifdef XC_POWERCLASS - if (CHK_HG8BIT(ms_card)) - change_power_class = 0; - - if (change_power_class && CHK_MSXC(ms_card)) { - u8 power_class_en = chip->ms_power_class_en; - - dev_dbg(rtsx_dev(chip), "power_class_en = 0x%x\n", - power_class_en); - dev_dbg(rtsx_dev(chip), "change_power_class = %d\n", - change_power_class); - - if (change_power_class) - power_class_en &= (1 << (change_power_class - 1)); - else - power_class_en = 0; - - if (power_class_en) { - u8 power_class_mode = - (ms_card->raw_sys_info[46] & 0x18) >> 3; - dev_dbg(rtsx_dev(chip), "power_class_mode = 0x%x", - power_class_mode); - if (change_power_class > power_class_mode) - change_power_class = power_class_mode; - if (change_power_class) { - retval = msxc_change_power(chip, - change_power_class); - if (retval != STATUS_SUCCESS) { - change_power_class--; - goto retry; - } - } - } - } -#endif - -#ifdef SUPPORT_MAGIC_GATE - retval = mg_set_tpc_para_sub(chip, 0, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; -#endif - - if (CHK_HG8BIT(ms_card)) - chip->card_bus_width[chip->card2lun[MS_CARD]] = 8; - else - chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; - - return STATUS_SUCCESS; -} - -static int ms_read_status_reg(struct rtsx_chip *chip) -{ - int retval; - u8 val[2]; - - retval = ms_set_rw_reg_addr(chip, STATUS_REG0, 2, 0, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int ms_read_extra_data(struct rtsx_chip *chip, - u16 block_addr, u8 page_num, u8 *buf, int buf_len) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 val, data[10]; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_MS4BIT(ms_card)) { - /* Parallel interface */ - data[0] = 0x88; - } else { - /* Serial interface */ - data[0] = 0x80; - } - data[1] = 0; - data[2] = (u8)(block_addr >> 8); - data[3] = (u8)block_addr; - data[4] = 0x40; - data[5] = page_num; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, - data, 6); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, - MS_EXTRA_SIZE, SYSTEM_PARAM, - 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - } - - retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, - data, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (buf && buf_len) { - if (buf_len > MS_EXTRA_SIZE) - buf_len = MS_EXTRA_SIZE; - memcpy(buf, data, buf_len); - } - - return STATUS_SUCCESS; -} - -static int ms_write_extra_data(struct rtsx_chip *chip, u16 block_addr, - u8 page_num, u8 *buf, int buf_len) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 val, data[16]; - - if (!buf || buf_len < MS_EXTRA_SIZE) - return STATUS_FAIL; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 6 + MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(block_addr >> 8); - data[3] = (u8)block_addr; - data[4] = 0x40; - data[5] = page_num; - - for (i = 6; i < MS_EXTRA_SIZE + 6; i++) - data[i] = buf[i - 6]; - - retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), - NO_WAIT_INT, data, 16); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - - return STATUS_SUCCESS; -} - -static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - u8 val, data[6]; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(block_addr >> 8); - data[3] = (u8)block_addr; - data[4] = 0x20; - data[5] = page_num; - - retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - return STATUS_FAIL; - } - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - - } else { - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - return STATUS_FAIL; - } - } - } - - retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, - 0, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - u8 val, data[8], extra[MS_EXTRA_SIZE]; - - retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 7); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(phy_blk >> 8); - data[3] = (u8)phy_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = extra[0] & 0x7F; - data[7] = 0xFF; - - retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 7); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - - return STATUS_SUCCESS; -} - -static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i = 0; - u8 val, data[6]; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(phy_blk >> 8); - data[3] = (u8)phy_blk; - data[4] = 0; - data[5] = 0; - - retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - -ERASE_RTY: - retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - if (i < 3) { - i++; - goto ERASE_RTY; - } - - ms_set_err_code(chip, MS_CMD_NK); - ms_set_bad_block(chip, phy_blk); - return STATUS_FAIL; - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - - return STATUS_SUCCESS; -} - -static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len) -{ - if (!extra || extra_len < MS_EXTRA_SIZE) - return; - - memset(extra, 0xFF, MS_EXTRA_SIZE); - - if (type == set_PS_NG) { - /* set page status as 1:NG,and block status keep 1:OK */ - extra[0] = 0xB8; - } else { - /* set page status as 0:Data Error,and block status keep 1:OK */ - extra[0] = 0x98; - } - - extra[2] = (u8)(log_blk >> 8); - extra[3] = (u8)log_blk; -} - -static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, - u8 start_page, u8 end_page) -{ - int retval; - u8 extra[MS_EXTRA_SIZE], i; - - memset(extra, 0xff, MS_EXTRA_SIZE); - - extra[0] = 0xf8; /* Block, page OK, data erased */ - extra[1] = 0xff; - extra[2] = (u8)(log_blk >> 8); - extra[3] = (u8)log_blk; - - for (i = start_page; i < end_page; i++) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - - retval = ms_write_extra_data(chip, phy_blk, i, - extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page, u8 end_page) -{ - struct ms_info *ms_card = &chip->ms_card; - bool uncorrect_flag = false; - int retval, rty_cnt; - u8 extra[MS_EXTRA_SIZE], val, i, j, data[16]; - - dev_dbg(rtsx_dev(chip), "Copy page from 0x%x to 0x%x, logical block is 0x%x\n", - old_blk, new_blk, log_blk); - dev_dbg(rtsx_dev(chip), "start_page = %d, end_page = %d\n", - start_page, end_page); - - retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_read_register(chip, PPBUF_BASE2, &val); - if (retval) - return retval; - - if (val & BUF_FULL) { - retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - - for (i = start_page; i < end_page; i++) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - - retval = ms_read_extra_data(chip, old_blk, i, extra, - MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, - MS_EXTRA_SIZE, SYSTEM_PARAM, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(old_blk >> 8); - data[3] = (u8)old_blk; - data[4] = 0x20; - data[5] = i; - - retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, - data, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) { - uncorrect_flag = true; - dev_dbg(rtsx_dev(chip), "Uncorrectable error\n"); - } else { - uncorrect_flag = false; - } - - retval = ms_transfer_tpc(chip, - MS_TM_NORMAL_READ, - READ_PAGE_DATA, - 0, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (uncorrect_flag) { - ms_set_page_status(log_blk, set_PS_NG, - extra, - MS_EXTRA_SIZE); - if (i == 0) - extra[0] &= 0xEF; - - ms_write_extra_data(chip, old_blk, i, - extra, - MS_EXTRA_SIZE); - dev_dbg(rtsx_dev(chip), "page %d : extra[0] = 0x%x\n", - i, extra[0]); - MS_SET_BAD_BLOCK_FLG(ms_card); - - ms_set_page_status(log_blk, - set_PS_error, extra, - MS_EXTRA_SIZE); - ms_write_extra_data(chip, new_blk, i, - extra, - MS_EXTRA_SIZE); - continue; - } - - for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT; - rty_cnt++) { - retval = ms_transfer_tpc(chip, - MS_TM_NORMAL_WRITE, - WRITE_PAGE_DATA, - 0, NO_WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (rty_cnt == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - } - - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - return STATUS_FAIL; - } - } - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, (6 + MS_EXTRA_SIZE)); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(new_blk >> 8); - data[3] = (u8)new_blk; - data[4] = 0x20; - data[5] = i; - - if ((extra[0] & 0x60) != 0x60) - data[6] = extra[0]; - else - data[6] = 0xF8; - - data[6 + 1] = 0xFF; - data[6 + 2] = (u8)(log_blk >> 8); - data[6 + 3] = (u8)log_blk; - - for (j = 4; j <= MS_EXTRA_SIZE; j++) - data[6 + j] = 0xFF; - - retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), - NO_WAIT_INT, data, 16); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - - if (i == 0) { - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, - MS_EXTRA_SIZE, SYSTEM_PARAM, - 7); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(old_blk >> 8); - data[3] = (u8)old_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = 0xEF; - data[7] = 0xFF; - - retval = ms_write_bytes(chip, WRITE_REG, 7, - NO_WAIT_INT, data, 8); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_read_bytes(chip, GET_INT, 1, - NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - - if (val & INT_REG_CED) { - if (val & INT_REG_ERR) { - ms_set_err_code(chip, - MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - } - } - - return STATUS_SUCCESS; -} - -static int reset_ms(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - u16 i, reg_addr, block_size; - u8 val, extra[MS_EXTRA_SIZE], j, *ptr; -#ifndef SUPPORT_MAGIC_GATE - u16 eblock_cnt; -#endif - - retval = ms_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_card->ms_type |= TYPE_MS; - - retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_read_register(chip, PPBUF_BASE2, &val); - if (retval) - return retval; - - if (val & WRT_PRTCT) - chip->card_wp |= MS_CARD; - else - chip->card_wp &= ~MS_CARD; - - i = 0; - -RE_SEARCH: - /* Search Boot Block */ - while (i < (MAX_DEFECTIVE_BLOCK + 2)) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - - retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) { - i++; - continue; - } - - if (extra[0] & BLOCK_OK) { - if (!(extra[1] & NOT_BOOT_BLOCK)) { - ms_card->boot_block = i; - break; - } - } - i++; - } - - if (i == (MAX_DEFECTIVE_BLOCK + 2)) { - dev_dbg(rtsx_dev(chip), "No boot block found!"); - return STATUS_FAIL; - } - - for (j = 0; j < 3; j++) { - retval = ms_read_page(chip, ms_card->boot_block, j); - if (retval != STATUS_SUCCESS) { - if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) { - i = ms_card->boot_block + 1; - ms_set_err_code(chip, MS_NO_ERROR); - goto RE_SEARCH; - } - } - } - - retval = ms_read_page(chip, ms_card->boot_block, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - /* Read MS system information as sys_info */ - rtsx_init_cmd(chip); - - for (i = 0; i < 96; i++) - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0); - - retval = rtsx_send_cmd(chip, MS_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - ptr = rtsx_get_cmd_data(chip); - memcpy(ms_card->raw_sys_info, ptr, 96); - - /* Read useful block contents */ - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0); - rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0); - - for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - rtsx_add_cmd(chip, READ_REG_CMD, MS_device_type, 0, 0); - rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_support, 0, 0); - - retval = rtsx_send_cmd(chip, MS_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - ptr = rtsx_get_cmd_data(chip); - - dev_dbg(rtsx_dev(chip), "Boot block data:\n"); - dev_dbg(rtsx_dev(chip), "%*ph\n", 16, ptr); - - /* Block ID error - * HEADER_ID0, HEADER_ID1 - */ - if (ptr[0] != 0x00 || ptr[1] != 0x01) { - i = ms_card->boot_block + 1; - goto RE_SEARCH; - } - - /* Page size error - * PAGE_SIZE_0, PAGE_SIZE_1 - */ - if (ptr[12] != 0x02 || ptr[13] != 0x00) { - i = ms_card->boot_block + 1; - goto RE_SEARCH; - } - - if (ptr[14] == 1 || ptr[14] == 3) - chip->card_wp |= MS_CARD; - - /* BLOCK_SIZE_0, BLOCK_SIZE_1 */ - block_size = ((u16)ptr[6] << 8) | ptr[7]; - if (block_size == 0x0010) { - /* Block size 16KB */ - ms_card->block_shift = 5; - ms_card->page_off = 0x1F; - } else if (block_size == 0x0008) { - /* Block size 8KB */ - ms_card->block_shift = 4; - ms_card->page_off = 0x0F; - } - - /* BLOCK_COUNT_0, BLOCK_COUNT_1 */ - ms_card->total_block = ((u16)ptr[8] << 8) | ptr[9]; - -#ifdef SUPPORT_MAGIC_GATE - j = ptr[10]; - - if (ms_card->block_shift == 4) { /* 4MB or 8MB */ - if (j < 2) { /* Effective block for 4MB: 0x1F0 */ - ms_card->capacity = 0x1EE0; - } else { /* Effective block for 8MB: 0x3E0 */ - ms_card->capacity = 0x3DE0; - } - } else { /* 16MB, 32MB, 64MB or 128MB */ - if (j < 5) { /* Effective block for 16MB: 0x3E0 */ - ms_card->capacity = 0x7BC0; - } else if (j < 0xA) { /* Effective block for 32MB: 0x7C0 */ - ms_card->capacity = 0xF7C0; - } else if (j < 0x11) { /* Effective block for 64MB: 0xF80 */ - ms_card->capacity = 0x1EF80; - } else { /* Effective block for 128MB: 0x1F00 */ - ms_card->capacity = 0x3DF00; - } - } -#else - /* EBLOCK_COUNT_0, EBLOCK_COUNT_1 */ - eblock_cnt = ((u16)ptr[10] << 8) | ptr[11]; - - ms_card->capacity = ((u32)eblock_cnt - 2) << ms_card->block_shift; -#endif - - chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity; - - /* Switch I/F Mode */ - if (ptr[15]) { - retval = ms_set_rw_reg_addr(chip, 0, 0, SYSTEM_PARAM, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, PPBUF_BASE2, 0xFF, 0x88); - if (retval) - return retval; - - retval = rtsx_write_register(chip, PPBUF_BASE2 + 1, 0xFF, 0); - if (retval) - return retval; - - retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1, - NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, MS_CFG, - 0x58 | MS_NO_CHECK_INT, - MS_BUS_WIDTH_4 | - PUSH_TIME_ODD | - MS_NO_CHECK_INT); - if (retval) - return retval; - - ms_card->ms_type |= MS_4BIT; - } - - if (CHK_MS4BIT(ms_card)) - chip->card_bus_width[chip->card2lun[MS_CARD]] = 4; - else - chip->card_bus_width[chip->card2lun[MS_CARD]] = 1; - - return STATUS_SUCCESS; -} - -static int ms_init_l2p_tbl(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int size, i, seg_no, retval; - u16 defect_block, reg_addr; - u8 val1, val2; - - ms_card->segment_cnt = ms_card->total_block >> 9; - dev_dbg(rtsx_dev(chip), "ms_card->segment_cnt = %d\n", - ms_card->segment_cnt); - - size = ms_card->segment_cnt * sizeof(struct zone_entry); - ms_card->segment = vzalloc(size); - if (!ms_card->segment) - return STATUS_FAIL; - - retval = ms_read_page(chip, ms_card->boot_block, 1); - if (retval != STATUS_SUCCESS) - goto INIT_FAIL; - - reg_addr = PPBUF_BASE2; - for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) { - int block_no; - - retval = rtsx_read_register(chip, reg_addr++, &val1); - if (retval != STATUS_SUCCESS) - goto INIT_FAIL; - - retval = rtsx_read_register(chip, reg_addr++, &val2); - if (retval != STATUS_SUCCESS) - goto INIT_FAIL; - - defect_block = ((u16)val1 << 8) | val2; - if (defect_block == 0xFFFF) - break; - - seg_no = defect_block / 512; - - block_no = ms_card->segment[seg_no].disable_count++; - ms_card->segment[seg_no].defect_list[block_no] = defect_block; - } - - for (i = 0; i < ms_card->segment_cnt; i++) { - ms_card->segment[i].build_flag = 0; - ms_card->segment[i].l2p_table = NULL; - ms_card->segment[i].free_table = NULL; - ms_card->segment[i].get_index = 0; - ms_card->segment[i].set_index = 0; - ms_card->segment[i].unused_blk_cnt = 0; - - dev_dbg(rtsx_dev(chip), "defective block count of segment %d is %d\n", - i, ms_card->segment[i].disable_count); - } - - return STATUS_SUCCESS; - -INIT_FAIL: - vfree(ms_card->segment); - ms_card->segment = NULL; - - return STATUS_FAIL; -} - -static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off) -{ - struct ms_info *ms_card = &chip->ms_card; - struct zone_entry *segment; - - if (!ms_card->segment) - return 0xFFFF; - - segment = &ms_card->segment[seg_no]; - - if (segment->l2p_table) - return segment->l2p_table[log_off]; - - return 0xFFFF; -} - -static void ms_set_l2p_tbl(struct rtsx_chip *chip, - int seg_no, u16 log_off, u16 phy_blk) -{ - struct ms_info *ms_card = &chip->ms_card; - struct zone_entry *segment; - - if (!ms_card->segment) - return; - - segment = &ms_card->segment[seg_no]; - if (segment->l2p_table) - segment->l2p_table[log_off] = phy_blk; -} - -static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk) -{ - struct ms_info *ms_card = &chip->ms_card; - struct zone_entry *segment; - int seg_no; - - seg_no = (int)phy_blk >> 9; - segment = &ms_card->segment[seg_no]; - - segment->free_table[segment->set_index++] = phy_blk; - if (segment->set_index >= MS_FREE_TABLE_CNT) - segment->set_index = 0; - - segment->unused_blk_cnt++; -} - -static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no) -{ - struct ms_info *ms_card = &chip->ms_card; - struct zone_entry *segment; - u16 phy_blk; - - segment = &ms_card->segment[seg_no]; - - if (segment->unused_blk_cnt <= 0) - return 0xFFFF; - - phy_blk = segment->free_table[segment->get_index]; - segment->free_table[segment->get_index++] = 0xFFFF; - if (segment->get_index >= MS_FREE_TABLE_CNT) - segment->get_index = 0; - - segment->unused_blk_cnt--; - - return phy_blk; -} - -static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478, - 2974, 3470, 3966, 4462, 4958, - 5454, 5950, 6446, 6942, 7438, - 7934}; - -static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, - u16 log_off, u8 us1, u8 us2) -{ - struct ms_info *ms_card = &chip->ms_card; - struct zone_entry *segment; - int seg_no; - u16 tmp_blk; - - seg_no = (int)phy_blk >> 9; - segment = &ms_card->segment[seg_no]; - tmp_blk = segment->l2p_table[log_off]; - - if (us1 != us2) { - if (us1 == 0) { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, tmp_blk); - - ms_set_unused_block(chip, tmp_blk); - segment->l2p_table[log_off] = phy_blk; - } else { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, phy_blk); - - ms_set_unused_block(chip, phy_blk); - } - } else { - if (phy_blk < tmp_blk) { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, phy_blk); - - ms_set_unused_block(chip, phy_blk); - } else { - if (!(chip->card_wp & MS_CARD)) - ms_erase_block(chip, tmp_blk); - - ms_set_unused_block(chip, tmp_blk); - segment->l2p_table[log_off] = phy_blk; - } - } - - return STATUS_SUCCESS; -} - -static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no) -{ - struct ms_info *ms_card = &chip->ms_card; - struct zone_entry *segment; - bool defect_flag; - int retval, table_size, disable_cnt, i; - u16 start, end, phy_blk, log_blk, tmp_blk, idx; - u8 extra[MS_EXTRA_SIZE], us1, us2; - - dev_dbg(rtsx_dev(chip), "%s: %d\n", __func__, seg_no); - - if (!ms_card->segment) { - retval = ms_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) - return retval; - } - - if (ms_card->segment[seg_no].build_flag) { - dev_dbg(rtsx_dev(chip), "l2p table of segment %d has been built\n", - seg_no); - return STATUS_SUCCESS; - } - - if (seg_no == 0) - table_size = 494; - else - table_size = 496; - - segment = &ms_card->segment[seg_no]; - - if (!segment->l2p_table) { - segment->l2p_table = vmalloc(array_size(table_size, 2)); - if (!segment->l2p_table) - goto BUILD_FAIL; - } - memset((u8 *)(segment->l2p_table), 0xff, array_size(table_size, 2)); - - if (!segment->free_table) { - segment->free_table = vmalloc(array_size(MS_FREE_TABLE_CNT, 2)); - if (!segment->free_table) - goto BUILD_FAIL; - } - memset((u8 *)(segment->free_table), 0xff, array_size(MS_FREE_TABLE_CNT, 2)); - - start = (u16)seg_no << 9; - end = (u16)(seg_no + 1) << 9; - - disable_cnt = segment->disable_count; - - segment->get_index = 0; - segment->set_index = 0; - segment->unused_blk_cnt = 0; - - for (phy_blk = start; phy_blk < end; phy_blk++) { - if (disable_cnt) { - defect_flag = false; - for (i = 0; i < segment->disable_count; i++) { - if (phy_blk == segment->defect_list[i]) { - defect_flag = true; - break; - } - } - if (defect_flag) { - disable_cnt--; - continue; - } - } - - retval = ms_read_extra_data(chip, phy_blk, 0, - extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) { - dev_dbg(rtsx_dev(chip), "read extra data fail\n"); - ms_set_bad_block(chip, phy_blk); - continue; - } - - if (seg_no == ms_card->segment_cnt - 1) { - if (!(extra[1] & NOT_TRANSLATION_TABLE)) { - if (!(chip->card_wp & MS_CARD)) { - retval = ms_erase_block(chip, phy_blk); - if (retval != STATUS_SUCCESS) - continue; - extra[2] = 0xff; - extra[3] = 0xff; - } - } - } - - if (!(extra[0] & BLOCK_OK)) - continue; - if (!(extra[1] & NOT_BOOT_BLOCK)) - continue; - if ((extra[0] & PAGE_OK) != PAGE_OK) - continue; - - log_blk = ((u16)extra[2] << 8) | extra[3]; - - if (log_blk == 0xFFFF) { - if (!(chip->card_wp & MS_CARD)) { - retval = ms_erase_block(chip, phy_blk); - if (retval != STATUS_SUCCESS) - continue; - } - ms_set_unused_block(chip, phy_blk); - continue; - } - - if (log_blk < ms_start_idx[seg_no] || - log_blk >= ms_start_idx[seg_no + 1]) { - if (!(chip->card_wp & MS_CARD)) { - retval = ms_erase_block(chip, phy_blk); - if (retval != STATUS_SUCCESS) - continue; - } - ms_set_unused_block(chip, phy_blk); - continue; - } - - idx = log_blk - ms_start_idx[seg_no]; - - if (segment->l2p_table[idx] == 0xFFFF) { - segment->l2p_table[idx] = phy_blk; - continue; - } - - us1 = extra[0] & 0x10; - tmp_blk = segment->l2p_table[idx]; - retval = ms_read_extra_data(chip, tmp_blk, 0, - extra, MS_EXTRA_SIZE); - if (retval != STATUS_SUCCESS) - continue; - us2 = extra[0] & 0x10; - - (void)ms_arbitrate_l2p(chip, phy_blk, - log_blk - ms_start_idx[seg_no], us1, us2); - } - - segment->build_flag = 1; - - dev_dbg(rtsx_dev(chip), "unused block count: %d\n", - segment->unused_blk_cnt); - - /* Logical Address Confirmation Process */ - if (seg_no == ms_card->segment_cnt - 1) { - if (segment->unused_blk_cnt < 2) - chip->card_wp |= MS_CARD; - } else { - if (segment->unused_blk_cnt < 1) - chip->card_wp |= MS_CARD; - } - - if (chip->card_wp & MS_CARD) - return STATUS_SUCCESS; - - for (log_blk = ms_start_idx[seg_no]; - log_blk < ms_start_idx[seg_no + 1]; log_blk++) { - idx = log_blk - ms_start_idx[seg_no]; - if (segment->l2p_table[idx] == 0xFFFF) { - phy_blk = ms_get_unused_block(chip, seg_no); - if (phy_blk == 0xFFFF) { - chip->card_wp |= MS_CARD; - return STATUS_SUCCESS; - } - retval = ms_init_page(chip, phy_blk, log_blk, 0, 1); - if (retval != STATUS_SUCCESS) - goto BUILD_FAIL; - - segment->l2p_table[idx] = phy_blk; - if (seg_no == ms_card->segment_cnt - 1) { - if (segment->unused_blk_cnt < 2) { - chip->card_wp |= MS_CARD; - return STATUS_SUCCESS; - } - } else { - if (segment->unused_blk_cnt < 1) { - chip->card_wp |= MS_CARD; - return STATUS_SUCCESS; - } - } - } - } - - /* Make boot block be the first normal block */ - if (seg_no == 0) { - for (log_blk = 0; log_blk < 494; log_blk++) { - tmp_blk = segment->l2p_table[log_blk]; - if (tmp_blk < ms_card->boot_block) { - dev_dbg(rtsx_dev(chip), "Boot block is not the first normal block.\n"); - - if (chip->card_wp & MS_CARD) - break; - - phy_blk = ms_get_unused_block(chip, 0); - retval = ms_copy_page(chip, tmp_blk, phy_blk, - log_blk, 0, - ms_card->page_off + 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - segment->l2p_table[log_blk] = phy_blk; - - retval = ms_set_bad_block(chip, tmp_blk); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - } - } - - return STATUS_SUCCESS; - -BUILD_FAIL: - segment->build_flag = 0; - vfree(segment->l2p_table); - segment->l2p_table = NULL; - vfree(segment->free_table); - segment->free_table = NULL; - - return STATUS_FAIL; -} - -int reset_ms_card(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int seg_no = ms_card->total_block / 512 - 1; - int retval; - - memset(ms_card, 0, sizeof(struct ms_info)); - - retval = enable_card_clock(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = select_card(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_card->ms_type = 0; - - retval = reset_ms_pro(chip); - if (retval != STATUS_SUCCESS) { - if (ms_card->check_ms_flow) { - retval = reset_ms(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - return STATUS_FAIL; - } - } - - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!CHK_MSPRO(ms_card)) { - /* Build table for the last segment, - * to check if L2P table block exists, erasing it - */ - retval = ms_build_l2p_tbl(chip, seg_no); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - dev_dbg(rtsx_dev(chip), "ms_card->ms_type = 0x%x\n", ms_card->ms_type); - - return STATUS_SUCCESS; -} - -static int mspro_set_rw_cmd(struct rtsx_chip *chip, - u32 start_sec, u16 sec_cnt, u8 cmd) -{ - int retval, i; - u8 data[8]; - - data[0] = cmd; - data[1] = (u8)(sec_cnt >> 8); - data[2] = (u8)sec_cnt; - data[3] = (u8)(start_sec >> 24); - data[4] = (u8)(start_sec >> 16); - data[5] = (u8)(start_sec >> 8); - data[6] = (u8)start_sec; - data[7] = 0; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, - WAIT_INT, data, 8); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -void mspro_stop_seq_mode(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - - if (ms_card->seq_mode) { - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return; - - ms_card->seq_mode = 0; - ms_card->total_sec_cnt = 0; - ms_send_cmd(chip, PRO_STOP, WAIT_INT); - - rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - } -} - -static inline int ms_auto_tune_clock(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - - if (chip->asic_code) { - if (ms_card->ms_clock > 30) - ms_card->ms_clock -= 20; - } else { - if (ms_card->ms_clock == CLK_80) - ms_card->ms_clock = CLK_60; - else if (ms_card->ms_clock == CLK_60) - ms_card->ms_clock = CLK_40; - } - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int mspro_rw_multi_sector(struct scsi_cmnd *srb, - struct rtsx_chip *chip, u32 start_sector, - u16 sector_cnt) -{ - struct ms_info *ms_card = &chip->ms_card; - bool mode_2k = false; - int retval; - u16 count; - u8 val, trans_mode, rw_tpc, rw_cmd; - - ms_set_err_code(chip, MS_NO_ERROR); - - ms_card->cleanup_counter = 0; - - if (CHK_MSHG(ms_card)) { - if ((start_sector % 4) || (sector_cnt % 4)) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rw_tpc = PRO_READ_LONG_DATA; - rw_cmd = PRO_READ_DATA; - } else { - rw_tpc = PRO_WRITE_LONG_DATA; - rw_cmd = PRO_WRITE_DATA; - } - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rw_tpc = PRO_READ_QUAD_DATA; - rw_cmd = PRO_READ_2K_DATA; - } else { - rw_tpc = PRO_WRITE_QUAD_DATA; - rw_cmd = PRO_WRITE_2K_DATA; - } - mode_2k = true; - } - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rw_tpc = PRO_READ_LONG_DATA; - rw_cmd = PRO_READ_DATA; - } else { - rw_tpc = PRO_WRITE_LONG_DATA; - rw_cmd = PRO_WRITE_DATA; - } - } - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (srb->sc_data_direction == DMA_FROM_DEVICE) - trans_mode = MS_TM_AUTO_READ; - else - trans_mode = MS_TM_AUTO_WRITE; - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); - if (retval) - return retval; - - if (ms_card->seq_mode) { - if (ms_card->pre_dir != srb->sc_data_direction || - ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != - start_sector) || - (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) || - (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) || - !(val & MS_INT_BREQ) || - ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) { - ms_card->seq_mode = 0; - ms_card->total_sec_cnt = 0; - if (val & MS_INT_BREQ) { - retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_write_register(chip, RBCTL, RB_FLUSH, - RB_FLUSH); - } - } - } - - if (!ms_card->seq_mode) { - ms_card->total_sec_cnt = 0; - if (sector_cnt >= SEQ_START_CRITERIA) { - if ((ms_card->capacity - start_sector) > 0xFE00) - count = 0xFE00; - else - count = (u16)(ms_card->capacity - start_sector); - - if (count > sector_cnt) { - if (mode_2k) - ms_card->seq_mode = MODE_2K_SEQ; - else - ms_card->seq_mode = MODE_512_SEQ; - } - } else { - count = sector_cnt; - } - retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd); - if (retval != STATUS_SUCCESS) { - ms_card->seq_mode = 0; - return STATUS_FAIL; - } - } - - retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt, - WAIT_INT, mode_2k, scsi_sg_count(srb), - scsi_sglist(srb), scsi_bufflen(srb)); - if (retval != STATUS_SUCCESS) { - ms_card->seq_mode = 0; - rtsx_read_register(chip, MS_TRANS_CFG, &val); - rtsx_clear_ms_error(chip); - - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - chip->rw_need_retry = 0; - dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n", - __func__); - return STATUS_FAIL; - } - - if (val & MS_INT_BREQ) - ms_send_cmd(chip, PRO_STOP, WAIT_INT); - - if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { - dev_dbg(rtsx_dev(chip), "MSPro CRC error, tune clock!\n"); - chip->rw_need_retry = 1; - ms_auto_tune_clock(chip); - } - - return retval; - } - - if (ms_card->seq_mode) { - ms_card->pre_sec_addr = start_sector; - ms_card->pre_sec_cnt = sector_cnt; - ms_card->pre_dir = srb->sc_data_direction; - ms_card->total_sec_cnt += sector_cnt; - } - - return STATUS_SUCCESS; -} - -static int mspro_read_format_progress(struct rtsx_chip *chip, - const int short_data_len) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u32 total_progress, cur_progress; - u8 cnt, tmp; - u8 data[8]; - - dev_dbg(rtsx_dev(chip), "%s, short_data_len = %d\n", __func__, - short_data_len); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp); - if (retval != STATUS_SUCCESS) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - if (!(tmp & MS_INT_BREQ)) { - if ((tmp & (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK | - MS_INT_ERR)) == MS_INT_CED) { - ms_card->format_status = FORMAT_SUCCESS; - return STATUS_SUCCESS; - } - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - if (short_data_len >= 256) - cnt = 0; - else - cnt = (u8)short_data_len; - - retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, - MS_NO_CHECK_INT); - if (retval != STATUS_SUCCESS) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT, - data, 8); - if (retval != STATUS_SUCCESS) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - total_progress = (data[0] << 24) | (data[1] << 16) | - (data[2] << 8) | data[3]; - cur_progress = (data[4] << 24) | (data[5] << 16) | - (data[6] << 8) | data[7]; - - dev_dbg(rtsx_dev(chip), "total_progress = %d, cur_progress = %d\n", - total_progress, cur_progress); - - if (total_progress == 0) { - ms_card->progress = 0; - } else { - u64 ulltmp = (u64)cur_progress * (u64)65535; - - do_div(ulltmp, total_progress); - ms_card->progress = (u16)ulltmp; - } - dev_dbg(rtsx_dev(chip), "progress = %d\n", ms_card->progress); - - for (i = 0; i < 5000; i++) { - retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp); - if (retval != STATUS_SUCCESS) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - if (tmp & (MS_INT_CED | MS_INT_CMDNK | - MS_INT_BREQ | MS_INT_ERR)) - break; - - wait_timeout(1); - } - - retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0); - if (retval != STATUS_SUCCESS) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - if (i == 5000) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) { - ms_card->format_status = FORMAT_FAIL; - return STATUS_FAIL; - } - - if (tmp & MS_INT_CED) { - ms_card->format_status = FORMAT_SUCCESS; - ms_card->pro_under_formatting = 0; - } else if (tmp & MS_INT_BREQ) { - ms_card->format_status = FORMAT_IN_PROGRESS; - } else { - ms_card->format_status = FORMAT_FAIL; - ms_card->pro_under_formatting = 0; - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -void mspro_polling_format_status(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int i; - - if (ms_card->pro_under_formatting && - (rtsx_get_stat(chip) != RTSX_STAT_SS)) { - rtsx_set_stat(chip, RTSX_STAT_RUN); - - for (i = 0; i < 65535; i++) { - mspro_read_format_progress(chip, MS_SHORT_DATA_LEN); - if (ms_card->format_status != FORMAT_IN_PROGRESS) - break; - } - } -} - -int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, - int short_data_len, bool quick_format) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 buf[8], tmp; - u16 para; - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, PRO_TPC_PARM, 0x01); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - memset(buf, 0, 2); - switch (short_data_len) { - case 32: - buf[0] = 0; - break; - case 64: - buf[0] = 1; - break; - case 128: - buf[0] = 2; - break; - case 256: - default: - buf[0] = 3; - break; - } - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, PRO_WRITE_REG, 1, - NO_WAIT_INT, buf, 2); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - if (quick_format) - para = 0x0000; - else - para = 0x0001; - - retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp); - if (retval) - return retval; - - if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) - return STATUS_FAIL; - - if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) { - ms_card->pro_under_formatting = 1; - ms_card->progress = 0; - ms_card->format_status = FORMAT_IN_PROGRESS; - return STATUS_SUCCESS; - } - - if (tmp & MS_INT_CED) { - ms_card->pro_under_formatting = 0; - ms_card->progress = 0; - ms_card->format_status = FORMAT_SUCCESS; - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE); - return STATUS_SUCCESS; - } - - return STATUS_FAIL; -} - -static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, - u16 log_blk, u8 start_page, u8 end_page, - u8 *buf, unsigned int *index, - unsigned int *offset) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6]; - u8 *ptr; - - retval = ms_read_extra_data(chip, phy_blk, start_page, - extra, MS_EXTRA_SIZE); - if (retval == STATUS_SUCCESS) { - if ((extra[1] & 0x30) != 0x30) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - return STATUS_FAIL; - } - } - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(phy_blk >> 8); - data[3] = (u8)phy_blk; - data[4] = 0; - data[5] = start_page; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, - data, 6); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ptr = buf; - - for (page_addr = start_page; page_addr < end_page; page_addr++) { - ms_set_err_code(chip, MS_NO_ERROR); - - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - if (val & INT_REG_ERR) { - if (val & INT_REG_BREQ) { - retval = ms_read_status_reg(chip); - if (retval != STATUS_SUCCESS) { - if (!(chip->card_wp & MS_CARD)) { - reset_ms(chip); - ms_set_page_status - (log_blk, set_PS_NG, - extra, - MS_EXTRA_SIZE); - ms_write_extra_data - (chip, phy_blk, - page_addr, extra, - MS_EXTRA_SIZE); - } - ms_set_err_code(chip, - MS_FLASH_READ_ERROR); - return STATUS_FAIL; - } - } else { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - return STATUS_FAIL; - } - } else { - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - return STATUS_FAIL; - } - } - - if (page_addr == (end_page - 1)) { - if (!(val & INT_REG_CED)) { - retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, - &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, MS_FLASH_READ_ERROR); - return STATUS_FAIL; - } - - trans_cfg = NO_WAIT_INT; - } else { - trans_cfg = WAIT_INT; - } - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, - 0xFF, trans_cfg); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, RING_BUFFER); - - trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_READ); - rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, - scsi_sg_count(chip->srb), - index, offset, - DMA_FROM_DEVICE, - chip->ms_timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - ms_set_err_code(chip, MS_TO_ERROR); - rtsx_clear_ms_error(chip); - return STATUS_TIMEDOUT; - } - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_TO_ERROR); - rtsx_clear_ms_error(chip); - return STATUS_TIMEDOUT; - } - if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) { - ms_set_err_code(chip, MS_CRC16_ERROR); - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - } - - if (scsi_sg_count(chip->srb) == 0) - ptr += 512; - } - - return STATUS_SUCCESS; -} - -static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, - u16 new_blk, u16 log_blk, u8 start_page, - u8 end_page, u8 *buf, unsigned int *index, - unsigned int *offset) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, i; - u8 page_addr, val, data[16]; - u8 *ptr; - - if (!start_page) { - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, 7); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(old_blk >> 8); - data[3] = (u8)old_blk; - data[4] = 0x80; - data[5] = 0; - data[6] = 0xEF; - data[7] = 0xFF; - - retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, - data, 8); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, - NO_WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE, - SYSTEM_PARAM, (6 + MS_EXTRA_SIZE)); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ms_set_err_code(chip, MS_NO_ERROR); - - if (CHK_MS4BIT(ms_card)) - data[0] = 0x88; - else - data[0] = 0x80; - - data[1] = 0; - data[2] = (u8)(new_blk >> 8); - data[3] = (u8)new_blk; - if ((end_page - start_page) == 1) - data[4] = 0x20; - else - data[4] = 0; - - data[5] = start_page; - data[6] = 0xF8; - data[7] = 0xFF; - data[8] = (u8)(log_blk >> 8); - data[9] = (u8)log_blk; - - for (i = 0x0A; i < 0x10; i++) - data[i] = 0xFF; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE, - NO_WAIT_INT, data, 16); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - ptr = buf; - for (page_addr = start_page; page_addr < end_page; page_addr++) { - ms_set_err_code(chip, MS_NO_ERROR); - - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - ms_set_err_code(chip, MS_NO_CARD); - return STATUS_FAIL; - } - - if (val & INT_REG_CMDNK) { - ms_set_err_code(chip, MS_CMD_NK); - return STATUS_FAIL; - } - if (val & INT_REG_ERR) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - if (!(val & INT_REG_BREQ)) { - ms_set_err_code(chip, MS_BREQ_ERROR); - return STATUS_FAIL; - } - - udelay(30); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, - 0xFF, WRITE_PAGE_DATA); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, - 0xFF, WAIT_INT); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, RING_BUFFER); - - trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_WRITE); - rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, - scsi_sg_count(chip->srb), - index, offset, - DMA_TO_DEVICE, - chip->ms_timeout); - if (retval < 0) { - ms_set_err_code(chip, MS_TO_ERROR); - rtsx_clear_ms_error(chip); - - if (retval == -ETIMEDOUT) - return STATUS_TIMEDOUT; - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if ((end_page - start_page) == 1) { - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } else { - if (page_addr == (end_page - 1)) { - if (!(val & INT_REG_CED)) { - retval = ms_send_cmd(chip, BLOCK_END, - WAIT_INT); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, GET_INT, 1, - NO_WAIT_INT, &val, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - if (page_addr == (end_page - 1) || - page_addr == ms_card->page_off) { - if (!(val & INT_REG_CED)) { - ms_set_err_code(chip, - MS_FLASH_WRITE_ERROR); - return STATUS_FAIL; - } - } - } - - if (scsi_sg_count(chip->srb) == 0) - ptr += 512; - } - - return STATUS_SUCCESS; -} - -static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 page_off) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval, seg_no; - - retval = ms_copy_page(chip, old_blk, new_blk, log_blk, - page_off, ms_card->page_off + 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - seg_no = old_blk >> 9; - - if (MS_TST_BAD_BLOCK_FLG(ms_card)) { - MS_CLR_BAD_BLOCK_FLG(ms_card); - ms_set_bad_block(chip, old_blk); - } else { - retval = ms_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) - ms_set_unused_block(chip, old_blk); - } - - ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk); - - return STATUS_SUCCESS; -} - -static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, - u16 log_blk, u8 start_page) -{ - int retval; - - if (start_page) { - retval = ms_copy_page(chip, old_blk, new_blk, log_blk, - 0, start_page); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -#ifdef MS_DELAY_WRITE -int ms_delay_write(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - struct ms_delay_write_tag *delay_write = &ms_card->delay_write; - int retval; - - if (delay_write->delay_write_flag) { - retval = ms_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - delay_write->delay_write_flag = 0; - retval = ms_finish_write(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->logblock, - delay_write->pageoff); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} -#endif - -static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); -} - -static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt) -{ - struct ms_info *ms_card = &chip->ms_card; - unsigned int lun = SCSI_LUN(srb); - int retval, seg_no; - unsigned int index = 0, offset = 0; - u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt; - u8 start_page, end_page = 0, page_cnt; - u8 *ptr; -#ifdef MS_DELAY_WRITE - struct ms_delay_write_tag *delay_write = &ms_card->delay_write; -#endif - - ms_set_err_code(chip, MS_NO_ERROR); - - ms_card->cleanup_counter = 0; - - ptr = (u8 *)scsi_sglist(srb); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) { - ms_rw_fail(srb, chip); - return STATUS_FAIL; - } - - log_blk = (u16)(start_sector >> ms_card->block_shift); - start_page = (u8)(start_sector & ms_card->page_off); - - for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) { - if (log_blk < ms_start_idx[seg_no + 1]) - break; - } - - if (ms_card->segment[seg_no].build_flag == 0) { - retval = ms_build_l2p_tbl(chip, seg_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= MS_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { -#ifdef MS_DELAY_WRITE - if (delay_write->delay_write_flag && - delay_write->logblock == log_blk && - start_page > delay_write->pageoff) { - delay_write->delay_write_flag = 0; - retval = ms_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - log_blk, - delay_write->pageoff, start_page); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page == delay_write->pageoff)) { - delay_write->delay_write_flag = 0; - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else { - retval = ms_delay_write(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } -#endif - old_blk = ms_get_l2p_tbl - (chip, seg_no, - log_blk - ms_start_idx[seg_no]); - new_blk = ms_get_unused_block(chip, seg_no); - if (old_blk == 0xFFFF || new_blk == 0xFFFF) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } - - retval = ms_prepare_write(chip, old_blk, new_blk, - log_blk, start_page); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, MS_CARD) != - STATUS_SUCCESS) { - set_sense_type - (chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } -#ifdef MS_DELAY_WRITE - } -#endif - } else { -#ifdef MS_DELAY_WRITE - retval = ms_delay_write(chip); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return STATUS_FAIL; - } -#endif - old_blk = ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); - if (old_blk == 0xFFFF) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return STATUS_FAIL; - } - } - - dev_dbg(rtsx_dev(chip), "seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", - seg_no, old_blk, new_blk); - - while (total_sec_cnt) { - if ((start_page + total_sec_cnt) > (ms_card->page_off + 1)) - end_page = ms_card->page_off + 1; - else - end_page = start_page + (u8)total_sec_cnt; - - page_cnt = end_page - start_page; - - dev_dbg(rtsx_dev(chip), "start_page = %d, end_page = %d, page_cnt = %d\n", - start_page, end_page, page_cnt); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - retval = ms_read_multiple_pages(chip, - old_blk, log_blk, - start_page, end_page, - ptr, &index, &offset); - } else { - retval = ms_write_multiple_pages(chip, old_blk, new_blk, - log_blk, start_page, - end_page, ptr, &index, - &offset); - } - - if (retval != STATUS_SUCCESS) { - toggle_gpio(chip, 1); - if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - ms_rw_fail(srb, chip); - return STATUS_FAIL; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (end_page == (ms_card->page_off + 1)) { - retval = ms_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) - ms_set_unused_block(chip, old_blk); - - ms_set_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no], - new_blk); - } - } - - total_sec_cnt -= page_cnt; - if (scsi_sg_count(srb) == 0) - ptr += page_cnt * 512; - - if (total_sec_cnt == 0) - break; - - log_blk++; - - for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; - seg_no++) { - if (log_blk < ms_start_idx[seg_no + 1]) - break; - } - - if (ms_card->segment[seg_no].build_flag == 0) { - retval = ms_build_l2p_tbl(chip, seg_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= MS_CARD; - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - } - - old_blk = ms_get_l2p_tbl(chip, seg_no, - log_blk - ms_start_idx[seg_no]); - if (old_blk == 0xFFFF) { - ms_rw_fail(srb, chip); - return STATUS_FAIL; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - new_blk = ms_get_unused_block(chip, seg_no); - if (new_blk == 0xFFFF) { - ms_rw_fail(srb, chip); - return STATUS_FAIL; - } - } - - dev_dbg(rtsx_dev(chip), "seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", - seg_no, old_blk, new_blk); - - start_page = 0; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (end_page < (ms_card->page_off + 1)) { -#ifdef MS_DELAY_WRITE - delay_write->delay_write_flag = 1; - delay_write->old_phyblock = old_blk; - delay_write->new_phyblock = new_blk; - delay_write->logblock = log_blk; - delay_write->pageoff = end_page; -#else - retval = ms_finish_write(chip, old_blk, new_blk, - log_blk, end_page); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, MS_CARD) != - STATUS_SUCCESS) { - set_sense_type - (chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - - ms_rw_fail(srb, chip); - return STATUS_FAIL; - } -#endif - } - } - - scsi_set_resid(srb, 0); - - return STATUS_SUCCESS; -} - -int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - - if (CHK_MSPRO(ms_card)) - retval = mspro_rw_multi_sector(srb, chip, start_sector, - sector_cnt); - else - retval = ms_rw_multi_sector(srb, chip, start_sector, - sector_cnt); - - return retval; -} - -void ms_free_l2p_tbl(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int i = 0; - - if (ms_card->segment) { - for (i = 0; i < ms_card->segment_cnt; i++) { - vfree(ms_card->segment[i].l2p_table); - ms_card->segment[i].l2p_table = NULL; - vfree(ms_card->segment[i].free_table); - ms_card->segment[i].free_table = NULL; - } - vfree(ms_card->segment); - ms_card->segment = NULL; - } -} - -#ifdef SUPPORT_MAGIC_GATE - -#ifdef READ_BYTES_WAIT_INT -static int ms_poll_int(struct rtsx_chip *chip) -{ - int retval; - u8 val; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED); - - retval = rtsx_send_cmd(chip, MS_CARD, 5000); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - val = *rtsx_get_cmd_data(chip); - if (val & MS_INT_ERR) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} -#endif - -#ifdef MS_SAMPLE_INT_ERR -static int check_ms_err(struct rtsx_chip *chip) -{ - int retval; - u8 val; - - retval = rtsx_read_register(chip, MS_TRANSFER, &val); - if (retval != STATUS_SUCCESS) - return 1; - if (val & MS_TRANSFER_ERR) - return 1; - - retval = rtsx_read_register(chip, MS_TRANS_CFG, &val); - if (retval != STATUS_SUCCESS) - return 1; - - if (val & (MS_INT_ERR | MS_INT_CMDNK)) - return 1; - - return 0; -} -#else -static int check_ms_err(struct rtsx_chip *chip) -{ - int retval; - u8 val; - - retval = rtsx_read_register(chip, MS_TRANSFER, &val); - if (retval != STATUS_SUCCESS) - return 1; - if (val & MS_TRANSFER_ERR) - return 1; - - return 0; -} -#endif - -static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num) -{ - int retval, i; - u8 data[8]; - - data[0] = cmd; - data[1] = 0; - data[2] = 0; - data[3] = 0; - data[4] = 0; - data[5] = 0; - data[6] = entry_num; - data[7] = 0; - - for (i = 0; i < MS_MAX_RETRY_COUNT; i++) { - retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, - data, 8); - if (retval == STATUS_SUCCESS) - break; - } - if (i == MS_MAX_RETRY_COUNT) - return STATUS_FAIL; - - if (check_ms_err(chip)) { - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, - u8 mg_entry_num) -{ - int retval; - u8 buf[6]; - - if (type == 0) - retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_TPC_PARM, 1); - else - retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6); - - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf[0] = 0; - buf[1] = 0; - if (type == 1) { - buf[2] = 0; - buf[3] = 0; - buf[4] = 0; - buf[5] = mg_entry_num; - } - retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, - NO_WAIT_INT, buf, 6); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - int i; - unsigned int lun = SCSI_LUN(srb); - u8 buf1[32], buf2[12]; - - if (scsi_bufflen(srb) < 12) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return STATUS_FAIL; - } - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = mg_send_ex_cmd(chip, MG_SET_LID, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - return STATUS_FAIL; - } - - memset(buf1, 0, 32); - rtsx_stor_get_xfer_buf(buf2, min_t(int, 12, scsi_bufflen(srb)), srb); - for (i = 0; i < 8; i++) - buf1[8 + i] = buf2[4 + i]; - - retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, - buf1, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - return STATUS_FAIL; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 *buf = NULL; - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf = kmalloc(1540, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - buf[0] = 0x04; - buf[1] = 0x1A; - buf[2] = 0x00; - buf[3] = 0x00; - - retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - goto free_buffer; - } - - retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 3, WAIT_INT, 0, 0, buf + 4, 1536); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - rtsx_clear_ms_error(chip); - goto free_buffer; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - rtsx_clear_ms_error(chip); - retval = STATUS_FAIL; - goto free_buffer; - } - - bufflen = min_t(int, 1052, scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf, bufflen, srb); - -free_buffer: - kfree(buf); - return retval; -} - -int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - int bufflen; - int i; - unsigned int lun = SCSI_LUN(srb); - u8 buf[32]; - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = mg_send_ex_cmd(chip, MG_GET_ID, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, - buf, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return STATUS_FAIL; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - - memcpy(ms_card->magic_gate_id, buf, 16); - -#ifdef READ_BYTES_WAIT_INT - retval = ms_poll_int(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return STATUS_FAIL; - } -#endif - - retval = mg_send_ex_cmd(chip, MG_SET_RD, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return STATUS_FAIL; - } - - bufflen = min_t(int, 12, scsi_bufflen(srb)); - rtsx_stor_get_xfer_buf(buf, bufflen, srb); - - for (i = 0; i < 8; i++) - buf[i] = buf[4 + i]; - - for (i = 0; i < 24; i++) - buf[8 + i] = 0; - - retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, - 32, WAIT_INT, buf, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return STATUS_FAIL; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - - ms_card->mg_auth = 0; - - return STATUS_SUCCESS; -} - -int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 buf1[32], buf2[36]; - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - return STATUS_FAIL; - } - - retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, - buf1, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - return STATUS_FAIL; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - - buf2[0] = 0x00; - buf2[1] = 0x22; - buf2[2] = 0x00; - buf2[3] = 0x00; - - memcpy(buf2 + 4, ms_card->magic_gate_id, 16); - memcpy(buf2 + 20, buf1, 16); - - bufflen = min_t(int, 36, scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf2, bufflen, srb); - -#ifdef READ_BYTES_WAIT_INT - retval = ms_poll_int(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - return STATUS_FAIL; - } -#endif - - return STATUS_SUCCESS; -} - -int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - int i; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 buf[32]; - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - return STATUS_FAIL; - } - - bufflen = min_t(int, 12, scsi_bufflen(srb)); - rtsx_stor_get_xfer_buf(buf, bufflen, srb); - - for (i = 0; i < 8; i++) - buf[i] = buf[4 + i]; - - for (i = 0; i < 24; i++) - buf[8 + i] = 0; - - retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, - buf, 32); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - return STATUS_FAIL; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN); - rtsx_clear_ms_error(chip); - return STATUS_FAIL; - } - - ms_card->mg_auth = 1; - - return STATUS_SUCCESS; -} - -int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - int bufflen; - unsigned int lun = SCSI_LUN(srb); - u8 *buf = NULL; - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf = kmalloc(1028, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - buf[0] = 0x04; - buf[1] = 0x02; - buf[2] = 0x00; - buf[3] = 0x00; - - retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - goto free_buffer; - } - - retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA, - 2, WAIT_INT, 0, 0, buf + 4, 1024); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - rtsx_clear_ms_error(chip); - goto free_buffer; - } - if (check_ms_err(chip)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - rtsx_clear_ms_error(chip); - retval = STATUS_FAIL; - goto free_buffer; - } - - bufflen = min_t(int, 1028, scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf, bufflen, srb); - -free_buffer: - kfree(buf); - return retval; -} - -int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - int bufflen; -#ifdef MG_SET_ICV_SLOW - int i; -#endif - unsigned int lun = SCSI_LUN(srb); - u8 *buf = NULL; - - ms_cleanup_work(chip); - - retval = ms_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf = kmalloc(1028, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - bufflen = min_t(int, 1028, scsi_bufflen(srb)); - rtsx_stor_get_xfer_buf(buf, bufflen, srb); - - retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num); - if (retval != STATUS_SUCCESS) { - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type - (chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); - } - goto set_ICV_finish; - } - -#ifdef MG_SET_ICV_SLOW - for (i = 0; i < 2; i++) { - udelay(50); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, - 0xFF, PRO_WRITE_LONG_DATA); - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, RING_BUFFER); - - trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, - MS_TRANSFER_START | MS_TM_NORMAL_WRITE); - rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, - MS_TRANSFER_END, MS_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i * 512, - 512, 0, DMA_TO_DEVICE, 3000); - if (retval < 0 || check_ms_err(chip)) { - rtsx_clear_ms_error(chip); - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type - (chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } - retval = STATUS_FAIL; - goto set_ICV_finish; - } - } -#else - retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA, - 2, WAIT_INT, 0, 0, buf + 4, 1024); - if (retval != STATUS_SUCCESS || check_ms_err(chip)) { - rtsx_clear_ms_error(chip); - if (ms_card->mg_auth == 0) { - if ((buf[5] & 0xC0) != 0) - set_sense_type - (chip, lun, - SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB); - else - set_sense_type(chip, lun, - SENSE_TYPE_MG_WRITE_ERR); - } else { - set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR); - } - goto set_ICV_finish; - } -#endif - -set_ICV_finish: - kfree(buf); - return retval; -} - -#endif /* SUPPORT_MAGIC_GATE */ - -void ms_cleanup_work(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - - if (CHK_MSPRO(ms_card)) { - if (ms_card->seq_mode) { - dev_dbg(rtsx_dev(chip), "MS Pro: stop transmission\n"); - mspro_stop_seq_mode(chip); - ms_card->cleanup_counter = 0; - } - if (CHK_MSHG(ms_card)) { - rtsx_write_register(chip, MS_CFG, - MS_2K_SECTOR_MODE, 0x00); - } - } -#ifdef MS_DELAY_WRITE - else if ((!CHK_MSPRO(ms_card)) && - ms_card->delay_write.delay_write_flag) { - dev_dbg(rtsx_dev(chip), "MS: delay write\n"); - ms_delay_write(chip); - ms_card->cleanup_counter = 0; - } -#endif -} - -int ms_power_off_card3v3(struct rtsx_chip *chip) -{ - int retval; - - retval = disable_card_clock(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (chip->asic_code) { - retval = ms_pull_ctl_disable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_MS_PULL_CTL_BIT | 0x20, - FPGA_MS_PULL_CTL_BIT); - if (retval) - return retval; - } - retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); - if (retval) - return retval; - - if (!chip->ft2_fast_mode) { - retval = card_power_off(chip, MS_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int release_ms_card(struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - int retval; - -#ifdef MS_DELAY_WRITE - ms_card->delay_write.delay_write_flag = 0; -#endif - ms_card->pro_under_formatting = 0; - - chip->card_ready &= ~MS_CARD; - chip->card_fail &= ~MS_CARD; - chip->card_wp &= ~MS_CARD; - - ms_free_l2p_tbl(chip); - - memset(ms_card->raw_sys_info, 0, 96); -#ifdef SUPPORT_PCGL_1P18 - memset(ms_card->raw_model_name, 0, 48); -#endif - - retval = ms_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h deleted file mode 100644 index 33bda9ce36b67c8300485adaebaadc489efb31e6..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/ms.h +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_MS_H -#define __REALTEK_RTSX_MS_H - -#define MS_DELAY_WRITE - -#define MS_MAX_RETRY_COUNT 3 - -#define MS_EXTRA_SIZE 0x9 - -#define WRT_PRTCT 0x01 - -/* Error Code */ -#define MS_NO_ERROR 0x00 -#define MS_CRC16_ERROR 0x80 -#define MS_TO_ERROR 0x40 -#define MS_NO_CARD 0x20 -#define MS_NO_MEMORY 0x10 -#define MS_CMD_NK 0x08 -#define MS_FLASH_READ_ERROR 0x04 -#define MS_FLASH_WRITE_ERROR 0x02 -#define MS_BREQ_ERROR 0x01 -#define MS_NOT_FOUND 0x03 - -/* Transfer Protocol Command */ -#define READ_PAGE_DATA 0x02 -#define READ_REG 0x04 -#define GET_INT 0x07 -#define WRITE_PAGE_DATA 0x0D -#define WRITE_REG 0x0B -#define SET_RW_REG_ADRS 0x08 -#define SET_CMD 0x0E - -#define PRO_READ_LONG_DATA 0x02 -#define PRO_READ_SHORT_DATA 0x03 -#define PRO_READ_REG 0x04 -#define PRO_READ_QUAD_DATA 0x05 -#define PRO_GET_INT 0x07 -#define PRO_WRITE_LONG_DATA 0x0D -#define PRO_WRITE_SHORT_DATA 0x0C -#define PRO_WRITE_QUAD_DATA 0x0A -#define PRO_WRITE_REG 0x0B -#define PRO_SET_RW_REG_ADRS 0x08 -#define PRO_SET_CMD 0x0E -#define PRO_EX_SET_CMD 0x09 - -#ifdef SUPPORT_MAGIC_GATE - -#define MG_GET_ID 0x40 -#define MG_SET_LID 0x41 -#define MG_GET_LEKB 0x42 -#define MG_SET_RD 0x43 -#define MG_MAKE_RMS 0x44 -#define MG_MAKE_KSE 0x45 -#define MG_SET_IBD 0x46 -#define MG_GET_IBD 0x47 - -#endif - -#ifdef XC_POWERCLASS -#define XC_CHG_POWER 0x16 -#endif - -#define BLOCK_READ 0xAA -#define BLOCK_WRITE 0x55 -#define BLOCK_END 0x33 -#define BLOCK_ERASE 0x99 -#define FLASH_STOP 0xCC - -#define SLEEP 0x5A -#define CLEAR_BUF 0xC3 -#define MS_RESET 0x3C - -#define PRO_READ_DATA 0x20 -#define PRO_WRITE_DATA 0x21 -#define PRO_READ_ATRB 0x24 -#define PRO_STOP 0x25 -#define PRO_ERASE 0x26 -#define PRO_READ_2K_DATA 0x27 -#define PRO_WRITE_2K_DATA 0x28 - -#define PRO_FORMAT 0x10 -#define PRO_SLEEP 0x11 - -#define INT_REG 0x01 -#define STATUS_REG0 0x02 -#define STATUS_REG1 0x03 - -#define SYSTEM_PARAM 0x10 -#define BLOCK_ADRS 0x11 -#define CMD_PARM 0x14 -#define PAGE_ADRS 0x15 - -#define OVERWRITE_FLAG 0x16 -#define MANAGEMEN_FLAG 0x17 -#define LOGICAL_ADRS 0x18 -#define RESERVE_AREA 0x1A - -#define PRO_INT_REG 0x01 -#define PRO_STATUS_REG 0x02 -#define PRO_TYPE_REG 0x04 -#define PRO_IF_mode_REG 0x05 -#define PRO_CATEGORY_REG 0x06 -#define PRO_CLASS_REG 0x07 - -#define PRO_SYSTEM_PARAM 0x10 -#define PRO_DATA_COUNT1 0x11 -#define PRO_DATA_COUNT0 0x12 -#define PRO_DATA_ADDR3 0x13 -#define PRO_DATA_ADDR2 0x14 -#define PRO_DATA_ADDR1 0x15 -#define PRO_DATA_ADDR0 0x16 - -#define PRO_TPC_PARM 0x17 -#define PRO_CMD_PARM 0x18 - -#define INT_REG_CED 0x80 -#define INT_REG_ERR 0x40 -#define INT_REG_BREQ 0x20 -#define INT_REG_CMDNK 0x01 - -#define BLOCK_BOOT 0xC0 -#define BLOCK_OK 0x80 -#define PAGE_OK 0x60 -#define DATA_COMPL 0x10 - -#define NOT_BOOT_BLOCK 0x4 -#define NOT_TRANSLATION_TABLE 0x8 - -#define HEADER_ID0 PPBUF_BASE2 -#define HEADER_ID1 (PPBUF_BASE2 + 1) -#define DISABLED_BLOCK0 (PPBUF_BASE2 + 0x170 + 4) -#define DISABLED_BLOCK1 (PPBUF_BASE2 + 0x170 + 5) -#define DISABLED_BLOCK2 (PPBUF_BASE2 + 0x170 + 6) -#define DISABLED_BLOCK3 (PPBUF_BASE2 + 0x170 + 7) -#define BLOCK_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 2) -#define BLOCK_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 3) -#define BLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 4) -#define BLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 5) -#define EBLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 6) -#define EBLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 7) -#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8) -#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9) - -#define MS_device_type (PPBUF_BASE2 + 0x1D8) - -#define MS_4bit_support (PPBUF_BASE2 + 0x1D3) - -#define set_PS_NG 1 -#define set_PS_error 0 - -#define PARALLEL_8BIT_IF 0x40 -#define PARALLEL_4BIT_IF 0x00 -#define SERIAL_IF 0x80 - -#define BUF_FULL 0x10 -#define BUF_EMPTY 0x20 - -#define MEDIA_BUSY 0x80 -#define FLASH_BUSY 0x40 -#define DATA_ERROR 0x20 -#define STS_UCDT 0x10 -#define EXTRA_ERROR 0x08 -#define STS_UCEX 0x04 -#define FLAG_ERROR 0x02 -#define STS_UCFG 0x01 - -#define MS_SHORT_DATA_LEN 32 - -#define FORMAT_SUCCESS 0 -#define FORMAT_FAIL 1 -#define FORMAT_IN_PROGRESS 2 - -#define MS_SET_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag |= 0x80) -#define MS_CLR_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag &= 0x7F) -#define MS_TST_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag & 0x80) - -void mspro_polling_format_status(struct rtsx_chip *chip); - -void mspro_stop_seq_mode(struct rtsx_chip *chip); -int reset_ms_card(struct rtsx_chip *chip); -int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt); -int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, - int short_data_len, bool quick_format); -void ms_free_l2p_tbl(struct rtsx_chip *chip); -void ms_cleanup_work(struct rtsx_chip *chip); -int ms_power_off_card3v3(struct rtsx_chip *chip); -int release_ms_card(struct rtsx_chip *chip); -#ifdef MS_DELAY_WRITE -int ms_delay_write(struct rtsx_chip *chip); -#endif - -#ifdef SUPPORT_MAGIC_GATE -int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip); -#endif - -#endif /* __REALTEK_RTSX_MS_H */ diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c deleted file mode 100644 index c4f54c311d0549247730a3cce94aad0c30470b12..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx.c +++ /dev/null @@ -1,987 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/workqueue.h> - -#include "rtsx.h" -#include "ms.h" -#include "sd.h" -#include "xd.h" - -MODULE_DESCRIPTION("Realtek PCI-Express card reader rts5208/rts5288 driver"); -MODULE_LICENSE("GPL"); - -static unsigned int delay_use = 1; -module_param(delay_use, uint, 0644); -MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); - -static int ss_en; -module_param(ss_en, int, 0644); -MODULE_PARM_DESC(ss_en, "enable selective suspend"); - -static int ss_interval = 50; -module_param(ss_interval, int, 0644); -MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds"); - -static int auto_delink_en; -module_param(auto_delink_en, int, 0644); -MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); - -static unsigned char aspm_l0s_l1_en; -module_param(aspm_l0s_l1_en, byte, 0644); -MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm"); - -static int msi_en; -module_param(msi_en, int, 0644); -MODULE_PARM_DESC(msi_en, "enable msi"); - -static irqreturn_t rtsx_interrupt(int irq, void *dev_id); - -/*********************************************************************** - * Host functions - ***********************************************************************/ - -static const char *host_info(struct Scsi_Host *host) -{ - return "SCSI emulation for PCI-Express Mass Storage devices"; -} - -static int slave_alloc(struct scsi_device *sdev) -{ - /* - * Set the INQUIRY transfer length to 36. We don't use any of - * the extra data and many devices choke if asked for more or - * less than 36 bytes. - */ - sdev->inquiry_len = 36; - return 0; -} - -static int slave_configure(struct scsi_device *sdev) -{ - /* Set the SCSI level to at least 2. We'll leave it at 3 if that's - * what is originally reported. We need this to avoid confusing - * the SCSI layer with devices that report 0 or 1, but need 10-byte - * commands (ala ATAPI devices behind certain bridges, or devices - * which simply have broken INQUIRY data). - * - * NOTE: This means /dev/sg programs (ala cdrecord) will get the - * actual information. This seems to be the preference for - * programs like that. - * - * NOTE: This also means that /proc/scsi/scsi and sysfs may report - * the actual value or the modified one, depending on where the - * data comes from. - */ - if (sdev->scsi_level < SCSI_2) { - sdev->scsi_level = SCSI_2; - sdev->sdev_target->scsi_level = SCSI_2; - } - - return 0; -} - -/*********************************************************************** - * /proc/scsi/ functions - ***********************************************************************/ - -/* we use this macro to help us write into the buffer */ -#undef SPRINTF -#define SPRINTF(args...) \ - do { \ - if (pos < buffer + length) \ - pos += sprintf(pos, ## args); \ - } while (0) - -/* queue a command */ -/* This is always called with spin_lock_irq(host->host_lock) held */ -static int queuecommand_lck(struct scsi_cmnd *srb) -{ - void (*done)(struct scsi_cmnd *) = scsi_done; - struct rtsx_dev *dev = host_to_rtsx(srb->device->host); - struct rtsx_chip *chip = dev->chip; - - /* check for state-transition errors */ - if (chip->srb) { - dev_err(&dev->pci->dev, "Error: chip->srb = %p\n", - chip->srb); - return SCSI_MLQUEUE_HOST_BUSY; - } - - /* fail the command if we are disconnecting */ - if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - dev_info(&dev->pci->dev, "Fail command during disconnect\n"); - srb->result = DID_NO_CONNECT << 16; - done(srb); - return 0; - } - - /* enqueue the command and wake up the control thread */ - chip->srb = srb; - complete(&dev->cmnd_ready); - - return 0; -} - -static DEF_SCSI_QCMD(queuecommand) - -/*********************************************************************** - * Error handling functions - ***********************************************************************/ - -/* Command timeout and abort */ -static int command_abort(struct scsi_cmnd *srb) -{ - struct Scsi_Host *host = srb->device->host; - struct rtsx_dev *dev = host_to_rtsx(host); - struct rtsx_chip *chip = dev->chip; - - spin_lock_irq(host->host_lock); - - /* Is this command still active? */ - if (chip->srb != srb) { - spin_unlock_irq(host->host_lock); - dev_info(&dev->pci->dev, "-- nothing to abort\n"); - return FAILED; - } - - rtsx_set_stat(chip, RTSX_STAT_ABORT); - - spin_unlock_irq(host->host_lock); - - /* Wait for the aborted command to finish */ - wait_for_completion(&dev->notify); - - return SUCCESS; -} - -/* - * This invokes the transport reset mechanism to reset the state of the - * device - */ -static int device_reset(struct scsi_cmnd *srb) -{ - return SUCCESS; -} - -/* - * this defines our host template, with which we'll allocate hosts - */ - -static const struct scsi_host_template rtsx_host_template = { - /* basic userland interface stuff */ - .name = CR_DRIVER_NAME, - .proc_name = CR_DRIVER_NAME, - .info = host_info, - - /* command interface -- queued only */ - .queuecommand = queuecommand, - - /* error and abort handlers */ - .eh_abort_handler = command_abort, - .eh_device_reset_handler = device_reset, - - /* queue commands only, only one command per LUN */ - .can_queue = 1, - - /* unknown initiator id */ - .this_id = -1, - - .slave_alloc = slave_alloc, - .slave_configure = slave_configure, - - /* lots of sg segments can be handled */ - .sg_tablesize = SG_ALL, - - /* limit the total size of a transfer to 120 KB */ - .max_sectors = 240, - - /* - * Scatter-gather buffers (all but the last) must have a length - * divisible by the bulk maxpacket size. Otherwise a data packet - * would end up being short, causing a premature end to the data - * transfer. Since high-speed bulk pipes have a maxpacket size - * of 512, we'll use that as the scsi device queue's DMA alignment - * mask. Guaranteeing proper alignment of the first buffer will - * have the desired effect because, except at the beginning and - * the end, scatter-gather buffers follow page boundaries. - */ - .dma_alignment = 511, - - /* emulated HBA */ - .emulated = 1, - - /* we do our own delay after a device or bus reset */ - .skip_settle_delay = 1, - - /* module management */ - .module = THIS_MODULE -}; - -static int rtsx_acquire_irq(struct rtsx_dev *dev) -{ - struct rtsx_chip *chip = dev->chip; - - dev_info(&dev->pci->dev, "%s: chip->msi_en = %d, pci->irq = %d\n", - __func__, chip->msi_en, dev->pci->irq); - - if (request_irq(dev->pci->irq, rtsx_interrupt, - chip->msi_en ? 0 : IRQF_SHARED, - CR_DRIVER_NAME, dev)) { - dev_err(&dev->pci->dev, - "rtsx: unable to grab IRQ %d, disabling device\n", - dev->pci->irq); - return -1; - } - - dev->irq = dev->pci->irq; - pci_intx(dev->pci, !chip->msi_en); - - return 0; -} - -/* - * power management - */ -static int __maybe_unused rtsx_suspend(struct device *dev_d) -{ - struct pci_dev *pci = to_pci_dev(dev_d); - struct rtsx_dev *dev = pci_get_drvdata(pci); - struct rtsx_chip *chip; - - if (!dev) - return 0; - - /* lock the device pointers */ - mutex_lock(&dev->dev_mutex); - - chip = dev->chip; - - rtsx_do_before_power_down(chip, PM_S3); - - if (dev->irq >= 0) { - free_irq(dev->irq, (void *)dev); - dev->irq = -1; - } - - if (chip->msi_en) - pci_free_irq_vectors(pci); - - device_wakeup_enable(dev_d); - - /* unlock the device pointers */ - mutex_unlock(&dev->dev_mutex); - - return 0; -} - -static int __maybe_unused rtsx_resume(struct device *dev_d) -{ - struct pci_dev *pci = to_pci_dev(dev_d); - struct rtsx_dev *dev = pci_get_drvdata(pci); - struct rtsx_chip *chip; - - if (!dev) - return 0; - - chip = dev->chip; - - /* lock the device pointers */ - mutex_lock(&dev->dev_mutex); - - pci_set_master(pci); - - if (chip->msi_en) { - if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0) - chip->msi_en = 0; - } - - if (rtsx_acquire_irq(dev) < 0) { - /* unlock the device pointers */ - mutex_unlock(&dev->dev_mutex); - return -EIO; - } - - rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00); - rtsx_init_chip(chip); - - /* unlock the device pointers */ - mutex_unlock(&dev->dev_mutex); - - return 0; -} - -static void rtsx_shutdown(struct pci_dev *pci) -{ - struct rtsx_dev *dev = pci_get_drvdata(pci); - struct rtsx_chip *chip; - - if (!dev) - return; - - chip = dev->chip; - - rtsx_do_before_power_down(chip, PM_S1); - - if (dev->irq >= 0) { - free_irq(dev->irq, (void *)dev); - dev->irq = -1; - } - - if (chip->msi_en) - pci_free_irq_vectors(pci); - - pci_disable_device(pci); -} - -static int rtsx_control_thread(void *__dev) -{ - struct rtsx_dev *dev = __dev; - struct rtsx_chip *chip = dev->chip; - struct Scsi_Host *host = rtsx_to_host(dev); - - for (;;) { - if (wait_for_completion_interruptible(&dev->cmnd_ready)) - break; - - /* lock the device pointers */ - mutex_lock(&dev->dev_mutex); - - /* if the device has disconnected, we are free to exit */ - if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - dev_info(&dev->pci->dev, "-- rtsx-control exiting\n"); - mutex_unlock(&dev->dev_mutex); - break; - } - - /* lock access to the state */ - spin_lock_irq(host->host_lock); - - /* has the command aborted ? */ - if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { - chip->srb->result = DID_ABORT << 16; - goto skip_for_abort; - } - - spin_unlock_irq(host->host_lock); - - /* reject the command if the direction indicator - * is UNKNOWN - */ - if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) { - dev_err(&dev->pci->dev, "UNKNOWN data direction\n"); - chip->srb->result = DID_ERROR << 16; - } else if (chip->srb->device->id) { - /* reject if target != 0 or if LUN is higher than - * the maximum known LUN - */ - dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n", - chip->srb->device->id, - (u8)chip->srb->device->lun); - chip->srb->result = DID_BAD_TARGET << 16; - } else if (chip->srb->device->lun > chip->max_lun) { - dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n", - chip->srb->device->id, - (u8)chip->srb->device->lun); - chip->srb->result = DID_BAD_TARGET << 16; - } else { - /* we've got a command, let's do it! */ - scsi_show_command(chip); - rtsx_invoke_transport(chip->srb, chip); - } - - /* lock access to the state */ - spin_lock_irq(host->host_lock); - - /* did the command already complete because of a disconnect? */ - if (!chip->srb) - ; /* nothing to do */ - - /* indicate that the command is done */ - else if (chip->srb->result != DID_ABORT << 16) { - scsi_done(chip->srb); - } else { -skip_for_abort: - dev_err(&dev->pci->dev, "scsi command aborted\n"); - } - - if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { - complete(&dev->notify); - - rtsx_set_stat(chip, RTSX_STAT_IDLE); - } - - /* finished working on this command */ - chip->srb = NULL; - spin_unlock_irq(host->host_lock); - - /* unlock the device pointers */ - mutex_unlock(&dev->dev_mutex); - } /* for (;;) */ - - /* notify the exit routine that we're actually exiting now - * - * complete()/wait_for_completion() is similar to up()/down(), - * except that complete() is safe in the case where the structure - * is getting deleted in a parallel mode of execution (i.e. just - * after the down() -- that's necessary for the thread-shutdown - * case. - * - * kthread_complete_and_exit() goes even further than this -- - * it is safe in the case that the thread of the caller is going away - * (not just the structure) -- this is necessary for the module-remove - * case. This is important in preemption kernels, which transfer the - * flow of execution immediately upon a complete(). - */ - kthread_complete_and_exit(&dev->control_exit, 0); -} - -static int rtsx_polling_thread(void *__dev) -{ - struct rtsx_dev *dev = __dev; - struct rtsx_chip *chip = dev->chip; - struct sd_info *sd_card = &chip->sd_card; - struct xd_info *xd_card = &chip->xd_card; - struct ms_info *ms_card = &chip->ms_card; - - sd_card->cleanup_counter = 0; - xd_card->cleanup_counter = 0; - ms_card->cleanup_counter = 0; - - /* Wait until SCSI scan finished */ - wait_timeout((delay_use + 5) * 1000); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(POLLING_INTERVAL)); - - /* lock the device pointers */ - mutex_lock(&dev->dev_mutex); - - /* if the device has disconnected, we are free to exit */ - if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - dev_info(&dev->pci->dev, "-- rtsx-polling exiting\n"); - mutex_unlock(&dev->dev_mutex); - break; - } - - mutex_unlock(&dev->dev_mutex); - - mspro_polling_format_status(chip); - - /* lock the device pointers */ - mutex_lock(&dev->dev_mutex); - - rtsx_polling_func(chip); - - /* unlock the device pointers */ - mutex_unlock(&dev->dev_mutex); - } - - kthread_complete_and_exit(&dev->polling_exit, 0); -} - -/* - * interrupt handler - */ -static irqreturn_t rtsx_interrupt(int irq, void *dev_id) -{ - struct rtsx_dev *dev = dev_id; - struct rtsx_chip *chip; - int retval; - u32 status; - - if (dev) - chip = dev->chip; - else - return IRQ_NONE; - - if (!chip) - return IRQ_NONE; - - spin_lock(&dev->reg_lock); - - retval = rtsx_pre_handle_interrupt(chip); - if (retval == STATUS_FAIL) { - spin_unlock(&dev->reg_lock); - if (chip->int_reg == 0xFFFFFFFF) - return IRQ_HANDLED; - return IRQ_NONE; - } - - status = chip->int_reg; - - if (dev->check_card_cd) { - if (!(dev->check_card_cd & status)) { - /* card not exist, return TRANS_RESULT_FAIL */ - dev->trans_result = TRANS_RESULT_FAIL; - if (dev->done) - complete(dev->done); - goto exit; - } - } - - if (status & (NEED_COMPLETE_INT | DELINK_INT)) { - if (status & (TRANS_FAIL_INT | DELINK_INT)) { - if (status & DELINK_INT) - RTSX_SET_DELINK(chip); - dev->trans_result = TRANS_RESULT_FAIL; - if (dev->done) - complete(dev->done); - } else if (status & TRANS_OK_INT) { - dev->trans_result = TRANS_RESULT_OK; - if (dev->done) - complete(dev->done); - } else if (status & DATA_DONE_INT) { - dev->trans_result = TRANS_NOT_READY; - if (dev->done && dev->trans_state == STATE_TRANS_SG) - complete(dev->done); - } - } - -exit: - spin_unlock(&dev->reg_lock); - return IRQ_HANDLED; -} - -/* Release all our dynamic resources */ -static void rtsx_release_resources(struct rtsx_dev *dev) -{ - dev_info(&dev->pci->dev, "-- %s\n", __func__); - - /* Tell the control thread to exit. The SCSI host must - * already have been removed so it won't try to queue - * any more commands. - */ - dev_info(&dev->pci->dev, "-- sending exit command to thread\n"); - complete(&dev->cmnd_ready); - if (dev->ctl_thread) - wait_for_completion(&dev->control_exit); - if (dev->polling_thread) - wait_for_completion(&dev->polling_exit); - - wait_timeout(200); - - if (dev->rtsx_resv_buf) { - dev->chip->host_cmds_ptr = NULL; - dev->chip->host_sg_tbl_ptr = NULL; - } - - if (dev->irq > 0) - free_irq(dev->irq, (void *)dev); - if (dev->chip->msi_en) - pci_free_irq_vectors(dev->pci); - if (dev->remap_addr) - iounmap(dev->remap_addr); - - rtsx_release_chip(dev->chip); - kfree(dev->chip); -} - -/* - * First stage of disconnect processing: stop all commands and remove - * the host - */ -static void quiesce_and_remove_host(struct rtsx_dev *dev) -{ - struct Scsi_Host *host = rtsx_to_host(dev); - struct rtsx_chip *chip = dev->chip; - - /* - * Prevent new transfers, stop the current command, and - * interrupt a SCSI-scan or device-reset delay - */ - mutex_lock(&dev->dev_mutex); - spin_lock_irq(host->host_lock); - rtsx_set_stat(chip, RTSX_STAT_DISCONNECT); - spin_unlock_irq(host->host_lock); - mutex_unlock(&dev->dev_mutex); - wake_up(&dev->delay_wait); - wait_for_completion(&dev->scanning_done); - - /* Wait some time to let other threads exist */ - wait_timeout(100); - - /* - * queuecommand won't accept any new commands and the control - * thread won't execute a previously-queued command. If there - * is such a command pending, complete it with an error. - */ - mutex_lock(&dev->dev_mutex); - if (chip->srb) { - chip->srb->result = DID_NO_CONNECT << 16; - spin_lock_irq(host->host_lock); - scsi_done(dev->chip->srb); - chip->srb = NULL; - spin_unlock_irq(host->host_lock); - } - mutex_unlock(&dev->dev_mutex); - - /* Now we own no commands so it's safe to remove the SCSI host */ - scsi_remove_host(host); -} - -/* Second stage of disconnect processing: deallocate all resources */ -static void release_everything(struct rtsx_dev *dev) -{ - rtsx_release_resources(dev); - - /* - * Drop our reference to the host; the SCSI core will free it - * when the refcount becomes 0. - */ - scsi_host_put(rtsx_to_host(dev)); -} - -/* Thread to carry out delayed SCSI-device scanning */ -static int rtsx_scan_thread(void *__dev) -{ - struct rtsx_dev *dev = __dev; - struct rtsx_chip *chip = dev->chip; - - /* Wait for the timeout to expire or for a disconnect */ - if (delay_use > 0) { - dev_info(&dev->pci->dev, - "%s: waiting for device to settle before scanning\n", - CR_DRIVER_NAME); - wait_event_interruptible_timeout - (dev->delay_wait, - rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT), - delay_use * HZ); - } - - /* If the device is still connected, perform the scanning */ - if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) { - scsi_scan_host(rtsx_to_host(dev)); - dev_info(&dev->pci->dev, "%s: device scan complete\n", - CR_DRIVER_NAME); - - /* Should we unbind if no devices were detected? */ - } - - kthread_complete_and_exit(&dev->scanning_done, 0); -} - -static void rtsx_init_options(struct rtsx_chip *chip) -{ - chip->vendor_id = chip->rtsx->pci->vendor; - chip->product_id = chip->rtsx->pci->device; - chip->adma_mode = 1; - chip->lun_mc = 0; - chip->driver_first_load = 1; -#ifdef HW_AUTO_SWITCH_SD_BUS - chip->sdio_in_charge = 0; -#endif - - chip->mspro_formatter_enable = 1; - chip->ignore_sd = 0; - chip->use_hw_setting = 0; - chip->lun_mode = DEFAULT_SINGLE; - chip->auto_delink_en = auto_delink_en; - chip->ss_en = ss_en; - chip->ss_idle_period = ss_interval * 1000; - chip->remote_wakeup_en = 0; - chip->aspm_l0s_l1_en = aspm_l0s_l1_en; - chip->dynamic_aspm = 1; - chip->fpga_sd_sdr104_clk = CLK_200; - chip->fpga_sd_ddr50_clk = CLK_100; - chip->fpga_sd_sdr50_clk = CLK_100; - chip->fpga_sd_hs_clk = CLK_100; - chip->fpga_mmc_52m_clk = CLK_80; - chip->fpga_ms_hg_clk = CLK_80; - chip->fpga_ms_4bit_clk = CLK_80; - chip->fpga_ms_1bit_clk = CLK_40; - chip->asic_sd_sdr104_clk = 203; - chip->asic_sd_sdr50_clk = 98; - chip->asic_sd_ddr50_clk = 98; - chip->asic_sd_hs_clk = 98; - chip->asic_mmc_52m_clk = 98; - chip->asic_ms_hg_clk = 117; - chip->asic_ms_4bit_clk = 78; - chip->asic_ms_1bit_clk = 39; - chip->ssc_depth_sd_sdr104 = SSC_DEPTH_2M; - chip->ssc_depth_sd_sdr50 = SSC_DEPTH_2M; - chip->ssc_depth_sd_ddr50 = SSC_DEPTH_1M; - chip->ssc_depth_sd_hs = SSC_DEPTH_1M; - chip->ssc_depth_mmc_52m = SSC_DEPTH_1M; - chip->ssc_depth_ms_hg = SSC_DEPTH_1M; - chip->ssc_depth_ms_4bit = SSC_DEPTH_512K; - chip->ssc_depth_low_speed = SSC_DEPTH_512K; - chip->ssc_en = 1; - chip->sd_speed_prior = 0x01040203; - chip->sd_current_prior = 0x00010203; - chip->sd_ctl = SD_PUSH_POINT_AUTO | - SD_SAMPLE_POINT_AUTO | - SUPPORT_MMC_DDR_MODE; - chip->sd_ddr_tx_phase = 0; - chip->mmc_ddr_tx_phase = 1; - chip->sd_default_tx_phase = 15; - chip->sd_default_rx_phase = 15; - chip->pmos_pwr_on_interval = 200; - chip->sd_voltage_switch_delay = 1000; - chip->ms_power_class_en = 3; - - chip->sd_400mA_ocp_thd = 1; - chip->sd_800mA_ocp_thd = 5; - chip->ms_ocp_thd = 2; - - chip->card_drive_sel = 0x55; - chip->sd30_drive_sel_1v8 = 0x03; - chip->sd30_drive_sel_3v3 = 0x01; - - chip->do_delink_before_power_down = 1; - chip->auto_power_down = 1; - chip->polling_config = 0; - - chip->force_clkreq_0 = 1; - chip->ft2_fast_mode = 0; - - chip->sdio_retry_cnt = 1; - - chip->xd_timeout = 2000; - chip->sd_timeout = 10000; - chip->ms_timeout = 2000; - chip->mspro_timeout = 15000; - - chip->power_down_in_ss = 1; - - chip->sdr104_en = 1; - chip->sdr50_en = 1; - chip->ddr50_en = 1; - - chip->delink_stage1_step = 100; - chip->delink_stage2_step = 40; - chip->delink_stage3_step = 20; - - chip->auto_delink_in_L1 = 1; - chip->blink_led = 1; - chip->msi_en = msi_en; - chip->hp_watch_bios_hotplug = 0; - chip->max_payload = 0; - chip->phy_voltage = 0; - - chip->support_ms_8bit = 1; - chip->s3_pwr_off_delay = 1000; -} - -static int rtsx_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct Scsi_Host *host; - struct rtsx_dev *dev; - int err = 0; - struct task_struct *th; - - dev_dbg(&pci->dev, "Realtek PCI-E card reader detected\n"); - - err = pcim_enable_device(pci); - if (err < 0) { - dev_err(&pci->dev, "PCI enable device failed!\n"); - return err; - } - - err = pci_request_regions(pci, CR_DRIVER_NAME); - if (err < 0) { - dev_err(&pci->dev, "PCI request regions for %s failed!\n", - CR_DRIVER_NAME); - return err; - } - - /* - * Ask the SCSI layer to allocate a host structure, with extra - * space at the end for our private rtsx_dev structure. - */ - host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev)); - if (!host) { - dev_err(&pci->dev, "Unable to allocate the scsi host\n"); - err = -ENOMEM; - goto scsi_host_alloc_fail; - } - - dev = host_to_rtsx(host); - memset(dev, 0, sizeof(struct rtsx_dev)); - - dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL); - if (!dev->chip) { - err = -ENOMEM; - goto chip_alloc_fail; - } - - spin_lock_init(&dev->reg_lock); - mutex_init(&dev->dev_mutex); - init_completion(&dev->cmnd_ready); - init_completion(&dev->control_exit); - init_completion(&dev->polling_exit); - init_completion(&dev->notify); - init_completion(&dev->scanning_done); - init_waitqueue_head(&dev->delay_wait); - - dev->pci = pci; - dev->irq = -1; - - dev_info(&pci->dev, "Resource length: 0x%x\n", - (unsigned int)pci_resource_len(pci, 0)); - dev->addr = pci_resource_start(pci, 0); - dev->remap_addr = ioremap(dev->addr, pci_resource_len(pci, 0)); - if (!dev->remap_addr) { - dev_err(&pci->dev, "ioremap error\n"); - err = -ENXIO; - goto ioremap_fail; - } - - /* - * Using "unsigned long" cast here to eliminate gcc warning in - * 64-bit system - */ - dev_info(&pci->dev, "Original address: 0x%lx, remapped address: 0x%lx\n", - (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr)); - - dev->rtsx_resv_buf = dmam_alloc_coherent(&pci->dev, RTSX_RESV_BUF_LEN, - &dev->rtsx_resv_buf_addr, - GFP_KERNEL); - if (!dev->rtsx_resv_buf) { - dev_err(&pci->dev, "alloc dma buffer fail\n"); - err = -ENXIO; - goto dma_alloc_fail; - } - dev->chip->host_cmds_ptr = dev->rtsx_resv_buf; - dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr; - dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN; - dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr + - HOST_CMDS_BUF_LEN; - - dev->chip->rtsx = dev; - - rtsx_init_options(dev->chip); - - dev_info(&pci->dev, "pci->irq = %d\n", pci->irq); - - if (dev->chip->msi_en) { - if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0) - dev->chip->msi_en = 0; - } - - if (rtsx_acquire_irq(dev) < 0) { - err = -EBUSY; - goto irq_acquire_fail; - } - - pci_set_master(pci); - synchronize_irq(dev->irq); - - rtsx_init_chip(dev->chip); - - /* - * set the supported max_lun and max_id for the scsi host - * NOTE: the minimal value of max_id is 1 - */ - host->max_id = 1; - host->max_lun = dev->chip->max_lun; - - /* Start up our control thread */ - th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME); - if (IS_ERR(th)) { - dev_err(&pci->dev, "Unable to start control thread\n"); - err = PTR_ERR(th); - goto control_thread_fail; - } - dev->ctl_thread = th; - - err = scsi_add_host(host, &pci->dev); - if (err) { - dev_err(&pci->dev, "Unable to add the scsi host\n"); - goto scsi_add_host_fail; - } - - /* Start up the thread for delayed SCSI-device scanning */ - th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan"); - if (IS_ERR(th)) { - dev_err(&pci->dev, "Unable to start the device-scanning thread\n"); - complete(&dev->scanning_done); - err = PTR_ERR(th); - goto scan_thread_fail; - } - - /* Start up the thread for polling thread */ - th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling"); - if (IS_ERR(th)) { - dev_err(&pci->dev, "Unable to start the device-polling thread\n"); - err = PTR_ERR(th); - goto scan_thread_fail; - } - dev->polling_thread = th; - - pci_set_drvdata(pci, dev); - - return 0; - - /* We come here if there are any problems */ -scan_thread_fail: - quiesce_and_remove_host(dev); -scsi_add_host_fail: - complete(&dev->cmnd_ready); - wait_for_completion(&dev->control_exit); -control_thread_fail: - free_irq(dev->irq, (void *)dev); - rtsx_release_chip(dev->chip); -irq_acquire_fail: - dev->chip->host_cmds_ptr = NULL; - dev->chip->host_sg_tbl_ptr = NULL; - if (dev->chip->msi_en) - pci_free_irq_vectors(dev->pci); -dma_alloc_fail: - iounmap(dev->remap_addr); -ioremap_fail: - kfree(dev->chip); -chip_alloc_fail: - dev_err(&pci->dev, "%s failed\n", __func__); - scsi_host_put(host); -scsi_host_alloc_fail: - pci_release_regions(pci); - return err; -} - -static void rtsx_remove(struct pci_dev *pci) -{ - struct rtsx_dev *dev = pci_get_drvdata(pci); - - quiesce_and_remove_host(dev); - release_everything(dev); - pci_release_regions(pci); -} - -/* PCI IDs */ -static const struct pci_device_id rtsx_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5208), - PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5288), - PCI_CLASS_OTHERS << 16, 0xFF0000 }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, rtsx_ids); - -static SIMPLE_DEV_PM_OPS(rtsx_pm_ops, rtsx_suspend, rtsx_resume); - -/* pci_driver definition */ -static struct pci_driver rtsx_driver = { - .name = CR_DRIVER_NAME, - .id_table = rtsx_ids, - .probe = rtsx_probe, - .remove = rtsx_remove, - .driver.pm = &rtsx_pm_ops, - .shutdown = rtsx_shutdown, -}; - -module_pci_driver(rtsx_driver); diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h deleted file mode 100644 index ec6f5b07390b2c9d2cd83579c7019ab0efb4d594..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx.h +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_H -#define __REALTEK_RTSX_H - -#include <linux/io.h> -#include <linux/bitops.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/mutex.h> -#include <linux/cdrom.h> -#include <linux/workqueue.h> -#include <linux/timer.h> -#include <linux/time64.h> - -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_devinfo.h> -#include <scsi/scsi_eh.h> -#include <scsi/scsi_host.h> - -#define CR_DRIVER_NAME "rts5208" - -/* - * macros for easy use - */ -#define wait_timeout_x(task_state, msecs) \ -do { \ - set_current_state((task_state)); \ - schedule_timeout((msecs) * HZ / 1000); \ -} while (0) -#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs)) - -#define STATE_TRANS_NONE 0 -#define STATE_TRANS_CMD 1 -#define STATE_TRANS_BUF 2 -#define STATE_TRANS_SG 3 - -#define TRANS_NOT_READY 0 -#define TRANS_RESULT_OK 1 -#define TRANS_RESULT_FAIL 2 - -#define SCSI_LUN(srb) ((srb)->device->lun) - -struct rtsx_chip; - -struct rtsx_dev { - struct pci_dev *pci; - - /* pci resources */ - unsigned long addr; - void __iomem *remap_addr; - int irq; - - /* locks */ - spinlock_t reg_lock; - - struct task_struct *ctl_thread; /* the control thread */ - struct task_struct *polling_thread; /* the polling thread */ - - /* mutual exclusion and synchronization structures */ - struct completion cmnd_ready; /* to sleep thread on */ - struct completion control_exit; /* control thread exit */ - struct completion polling_exit; /* polling thread exit */ - struct completion notify; /* thread begin/end */ - struct completion scanning_done; /* wait for scan thread */ - - wait_queue_head_t delay_wait; /* wait during scan, reset */ - struct mutex dev_mutex; - - /* host reserved buffer */ - void *rtsx_resv_buf; - dma_addr_t rtsx_resv_buf_addr; - - char trans_result; - char trans_state; - - struct completion *done; - /* Whether interrupt handler should care card cd info */ - u32 check_card_cd; - - struct rtsx_chip *chip; -}; - -/* Convert between rtsx_dev and the corresponding Scsi_Host */ -static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev) -{ - return container_of((void *)dev, struct Scsi_Host, hostdata); -} - -static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host) -{ - return (struct rtsx_dev *)host->hostdata; -} - -#define lock_state(chip) spin_lock_irq(&((chip)->rtsx->reg_lock)) -#define unlock_state(chip) spin_unlock_irq(&((chip)->rtsx->reg_lock)) - -/* struct scsi_cmnd transfer buffer access utilities */ -enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; - -#include "rtsx_chip.h" -#include "rtsx_transport.h" -#include "rtsx_scsi.h" -#include "rtsx_card.h" -#include "rtsx_sys.h" -#include "general.h" - -static inline void rtsx_writel(struct rtsx_chip *chip, u32 reg, u32 value) -{ - iowrite32(value, chip->rtsx->remap_addr + reg); -} - -static inline u32 rtsx_readl(struct rtsx_chip *chip, u32 reg) -{ - return ioread32(chip->rtsx->remap_addr + reg); -} - -static inline void rtsx_writew(struct rtsx_chip *chip, u32 reg, u16 value) -{ - iowrite16(value, chip->rtsx->remap_addr + reg); -} - -static inline u16 rtsx_readw(struct rtsx_chip *chip, u32 reg) -{ - return ioread16(chip->rtsx->remap_addr + reg); -} - -static inline void rtsx_writeb(struct rtsx_chip *chip, u32 reg, u8 value) -{ - iowrite8(value, chip->rtsx->remap_addr + reg); -} - -static inline u8 rtsx_readb(struct rtsx_chip *chip, u32 reg) -{ - return ioread8((chip)->rtsx->remap_addr + reg); -} - -static inline int rtsx_read_config_byte(struct rtsx_chip *chip, int where, u8 *val) -{ - return pci_read_config_byte(chip->rtsx->pci, where, val); -} - -static inline int rtsx_write_config_byte(struct rtsx_chip *chip, int where, u8 val) -{ - return pci_write_config_byte(chip->rtsx->pci, where, val); -} - -#endif /* __REALTEK_RTSX_H */ diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c deleted file mode 100644 index 326b04756f62c71916f8bd44a324825b587c72ff..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_card.c +++ /dev/null @@ -1,1151 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/workqueue.h> -#include <linux/kernel.h> - -#include "rtsx.h" -#include "sd.h" -#include "xd.h" -#include "ms.h" - -void do_remaining_work(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; -#ifdef XD_DELAY_WRITE - struct xd_info *xd_card = &chip->xd_card; -#endif - struct ms_info *ms_card = &chip->ms_card; - - if (chip->card_ready & SD_CARD) { - if (sd_card->seq_mode) { - rtsx_set_stat(chip, RTSX_STAT_RUN); - sd_card->cleanup_counter++; - } else { - sd_card->cleanup_counter = 0; - } - } - -#ifdef XD_DELAY_WRITE - if (chip->card_ready & XD_CARD) { - if (xd_card->delay_write.delay_write_flag) { - rtsx_set_stat(chip, RTSX_STAT_RUN); - xd_card->cleanup_counter++; - } else { - xd_card->cleanup_counter = 0; - } - } -#endif - - if (chip->card_ready & MS_CARD) { - if (CHK_MSPRO(ms_card)) { - if (ms_card->seq_mode) { - rtsx_set_stat(chip, RTSX_STAT_RUN); - ms_card->cleanup_counter++; - } else { - ms_card->cleanup_counter = 0; - } - } else { -#ifdef MS_DELAY_WRITE - if (ms_card->delay_write.delay_write_flag) { - rtsx_set_stat(chip, RTSX_STAT_RUN); - ms_card->cleanup_counter++; - } else { - ms_card->cleanup_counter = 0; - } -#endif - } - } - - if (sd_card->cleanup_counter > POLLING_WAIT_CNT) - sd_cleanup_work(chip); - - if (xd_card->cleanup_counter > POLLING_WAIT_CNT) - xd_cleanup_work(chip); - - if (ms_card->cleanup_counter > POLLING_WAIT_CNT) - ms_cleanup_work(chip); -} - -void try_to_switch_sdio_ctrl(struct rtsx_chip *chip) -{ - u8 reg1 = 0, reg2 = 0; - - rtsx_read_register(chip, 0xFF34, ®1); - rtsx_read_register(chip, 0xFF38, ®2); - dev_dbg(rtsx_dev(chip), "reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n", - reg1, reg2); - if ((reg1 & 0xC0) && (reg2 & 0xC0)) { - chip->sd_int = 1; - rtsx_write_register(chip, SDIO_CTRL, 0xFF, - SDIO_BUS_CTRL | SDIO_CD_CTRL); - rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_ON); - } -} - -#ifdef SUPPORT_SDIO_ASPM -void dynamic_configure_sdio_aspm(struct rtsx_chip *chip) -{ - u8 buf[12], reg; - int i; - - for (i = 0; i < 12; i++) - rtsx_read_register(chip, 0xFF08 + i, &buf[i]); - rtsx_read_register(chip, 0xFF25, ®); - if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) { - chip->sdio_counter = 0; - chip->sdio_idle = 0; - } else { - if (!chip->sdio_idle) { - chip->sdio_counter++; - if (chip->sdio_counter >= SDIO_IDLE_COUNT) { - chip->sdio_counter = 0; - chip->sdio_idle = 1; - } - } - } - memcpy(chip->sdio_raw_data, buf, 12); - - if (chip->sdio_idle) { - if (!chip->sdio_aspm) { - dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n"); - rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, - 0x30 | (chip->aspm_level[1] << 2)); - chip->sdio_aspm = 1; - } - } else { - if (chip->sdio_aspm) { - dev_dbg(rtsx_dev(chip), "SDIO exit ASPM!\n"); - rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30); - chip->sdio_aspm = 0; - } - } -} -#endif - -void do_reset_sd_card(struct rtsx_chip *chip) -{ - int retval; - - dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__, - chip->sd_reset_counter, chip->card2lun[SD_CARD]); - - if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) { - clear_bit(SD_NR, &chip->need_reset); - chip->sd_reset_counter = 0; - chip->sd_show_cnt = 0; - return; - } - - chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0; - - rtsx_set_stat(chip, RTSX_STAT_RUN); - rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); - - retval = reset_sd_card(chip); - if (chip->need_release & SD_CARD) - return; - if (retval == STATUS_SUCCESS) { - clear_bit(SD_NR, &chip->need_reset); - chip->sd_reset_counter = 0; - chip->sd_show_cnt = 0; - chip->card_ready |= SD_CARD; - chip->card_fail &= ~SD_CARD; - chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw; - } else { - if (chip->sd_io || chip->sd_reset_counter >= MAX_RESET_CNT) { - clear_bit(SD_NR, &chip->need_reset); - chip->sd_reset_counter = 0; - chip->sd_show_cnt = 0; - } else { - chip->sd_reset_counter++; - } - chip->card_ready &= ~SD_CARD; - chip->card_fail |= SD_CARD; - chip->capacity[chip->card2lun[SD_CARD]] = 0; - chip->rw_card[chip->card2lun[SD_CARD]] = NULL; - - rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); - if (!chip->ft2_fast_mode) - card_power_off(chip, SD_CARD); - if (chip->sd_io) { - chip->sd_int = 0; - try_to_switch_sdio_ctrl(chip); - } else { - disable_card_clock(chip, SD_CARD); - } - } -} - -void do_reset_xd_card(struct rtsx_chip *chip) -{ - int retval; - - dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__, - chip->xd_reset_counter, chip->card2lun[XD_CARD]); - - if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) { - clear_bit(XD_NR, &chip->need_reset); - chip->xd_reset_counter = 0; - chip->xd_show_cnt = 0; - return; - } - - chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0; - - rtsx_set_stat(chip, RTSX_STAT_RUN); - rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); - - retval = reset_xd_card(chip); - if (chip->need_release & XD_CARD) - return; - if (retval == STATUS_SUCCESS) { - clear_bit(XD_NR, &chip->need_reset); - chip->xd_reset_counter = 0; - chip->card_ready |= XD_CARD; - chip->card_fail &= ~XD_CARD; - chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw; - } else { - if (chip->xd_reset_counter >= MAX_RESET_CNT) { - clear_bit(XD_NR, &chip->need_reset); - chip->xd_reset_counter = 0; - chip->xd_show_cnt = 0; - } else { - chip->xd_reset_counter++; - } - chip->card_ready &= ~XD_CARD; - chip->card_fail |= XD_CARD; - chip->capacity[chip->card2lun[XD_CARD]] = 0; - chip->rw_card[chip->card2lun[XD_CARD]] = NULL; - - rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0); - if (!chip->ft2_fast_mode) - card_power_off(chip, XD_CARD); - disable_card_clock(chip, XD_CARD); - } -} - -void do_reset_ms_card(struct rtsx_chip *chip) -{ - int retval; - - dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__, - chip->ms_reset_counter, chip->card2lun[MS_CARD]); - - if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) { - clear_bit(MS_NR, &chip->need_reset); - chip->ms_reset_counter = 0; - chip->ms_show_cnt = 0; - return; - } - - chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0; - - rtsx_set_stat(chip, RTSX_STAT_RUN); - rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0); - - retval = reset_ms_card(chip); - if (chip->need_release & MS_CARD) - return; - if (retval == STATUS_SUCCESS) { - clear_bit(MS_NR, &chip->need_reset); - chip->ms_reset_counter = 0; - chip->card_ready |= MS_CARD; - chip->card_fail &= ~MS_CARD; - chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw; - } else { - if (chip->ms_reset_counter >= MAX_RESET_CNT) { - clear_bit(MS_NR, &chip->need_reset); - chip->ms_reset_counter = 0; - chip->ms_show_cnt = 0; - } else { - chip->ms_reset_counter++; - } - chip->card_ready &= ~MS_CARD; - chip->card_fail |= MS_CARD; - chip->capacity[chip->card2lun[MS_CARD]] = 0; - chip->rw_card[chip->card2lun[MS_CARD]] = NULL; - - rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); - if (!chip->ft2_fast_mode) - card_power_off(chip, MS_CARD); - disable_card_clock(chip, MS_CARD); - } -} - -static void release_sdio(struct rtsx_chip *chip) -{ - if (chip->sd_io) { - rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - - if (chip->chip_insert_with_sdio) { - chip->chip_insert_with_sdio = 0; - - if (CHECK_PID(chip, 0x5288)) - rtsx_write_register(chip, 0xFE5A, 0x08, 0x00); - else - rtsx_write_register(chip, 0xFE70, 0x80, 0x00); - } - - rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0); - chip->sd_io = 0; - } -} - -void rtsx_power_off_card(struct rtsx_chip *chip) -{ - if ((chip->card_ready & SD_CARD) || chip->sd_io) { - sd_cleanup_work(chip); - sd_power_off_card3v3(chip); - } - - if (chip->card_ready & XD_CARD) { - xd_cleanup_work(chip); - xd_power_off_card3v3(chip); - } - - if (chip->card_ready & MS_CARD) { - ms_cleanup_work(chip); - ms_power_off_card3v3(chip); - } -} - -void rtsx_release_cards(struct rtsx_chip *chip) -{ - chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - - if ((chip->card_ready & SD_CARD) || chip->sd_io) { - if (chip->int_reg & SD_EXIST) - sd_cleanup_work(chip); - release_sd_card(chip); - } - - if (chip->card_ready & XD_CARD) { - if (chip->int_reg & XD_EXIST) - xd_cleanup_work(chip); - release_xd_card(chip); - } - - if (chip->card_ready & MS_CARD) { - if (chip->int_reg & MS_EXIST) - ms_cleanup_work(chip); - release_ms_card(chip); - } -} - -void rtsx_reset_cards(struct rtsx_chip *chip) -{ - if (!chip->need_reset) - return; - - rtsx_set_stat(chip, RTSX_STAT_RUN); - - rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); - - rtsx_disable_aspm(chip); - - if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio) - clear_bit(SD_NR, &chip->need_reset); - - if (chip->need_reset & XD_CARD) { - chip->card_exist |= XD_CARD; - - if (chip->xd_show_cnt >= MAX_SHOW_CNT) - do_reset_xd_card(chip); - else - chip->xd_show_cnt++; - } - if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { - if (chip->card_exist & XD_CARD) { - clear_bit(SD_NR, &chip->need_reset); - clear_bit(MS_NR, &chip->need_reset); - } - } - if (chip->need_reset & SD_CARD) { - chip->card_exist |= SD_CARD; - - if (chip->sd_show_cnt >= MAX_SHOW_CNT) { - rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - do_reset_sd_card(chip); - } else { - chip->sd_show_cnt++; - } - } - if (chip->need_reset & MS_CARD) { - chip->card_exist |= MS_CARD; - - if (chip->ms_show_cnt >= MAX_SHOW_CNT) - do_reset_ms_card(chip); - else - chip->ms_show_cnt++; - } -} - -void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip) -{ - rtsx_set_stat(chip, RTSX_STAT_RUN); - - rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); - - if (reset_chip) - rtsx_reset_chip(chip); - - chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - - if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) { - release_sdio(chip); - release_sd_card(chip); - - wait_timeout(100); - - chip->card_exist |= SD_CARD; - do_reset_sd_card(chip); - } - - if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) { - release_xd_card(chip); - - wait_timeout(100); - - chip->card_exist |= XD_CARD; - do_reset_xd_card(chip); - } - - if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) { - release_ms_card(chip); - - wait_timeout(100); - - chip->card_exist |= MS_CARD; - do_reset_ms_card(chip); - } - - chip->need_reinit = 0; -} - -#ifdef DISABLE_CARD_INT -void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, - unsigned long *need_release) -{ - u8 release_map = 0, reset_map = 0; - - chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - - if (chip->card_exist) { - if (chip->card_exist & XD_CARD) { - if (!(chip->int_reg & XD_EXIST)) - release_map |= XD_CARD; - } else if (chip->card_exist & SD_CARD) { - if (!(chip->int_reg & SD_EXIST)) - release_map |= SD_CARD; - } else if (chip->card_exist & MS_CARD) { - if (!(chip->int_reg & MS_EXIST)) - release_map |= MS_CARD; - } - } else { - if (chip->int_reg & XD_EXIST) - reset_map |= XD_CARD; - else if (chip->int_reg & SD_EXIST) - reset_map |= SD_CARD; - else if (chip->int_reg & MS_EXIST) - reset_map |= MS_CARD; - } - - if (reset_map) { - int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0; - int i; - - for (i = 0; i < (DEBOUNCE_CNT); i++) { - chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - - if (chip->int_reg & XD_EXIST) - xd_cnt++; - else - xd_cnt = 0; - - if (chip->int_reg & SD_EXIST) - sd_cnt++; - else - sd_cnt = 0; - - if (chip->int_reg & MS_EXIST) - ms_cnt++; - else - ms_cnt = 0; - - wait_timeout(30); - } - - reset_map = 0; - if (!(chip->card_exist & XD_CARD) && - (xd_cnt > (DEBOUNCE_CNT - 1))) - reset_map |= XD_CARD; - if (!(chip->card_exist & SD_CARD) && - (sd_cnt > (DEBOUNCE_CNT - 1))) - reset_map |= SD_CARD; - if (!(chip->card_exist & MS_CARD) && - (ms_cnt > (DEBOUNCE_CNT - 1))) - reset_map |= MS_CARD; - } - - if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) - rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00); - - if (need_reset) - *need_reset = reset_map; - if (need_release) - *need_release = release_map; -} -#endif - -void rtsx_init_cards(struct rtsx_chip *chip) -{ - if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) { - dev_dbg(rtsx_dev(chip), "Reset chip in polling thread!\n"); - rtsx_reset_chip(chip); - RTSX_CLR_DELINK(chip); - } - -#ifdef DISABLE_CARD_INT - card_cd_debounce(chip, &chip->need_reset, &chip->need_release); -#endif - - if (chip->need_release) { - if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) { - if (chip->int_reg & XD_EXIST) { - clear_bit(SD_NR, &chip->need_release); - clear_bit(MS_NR, &chip->need_release); - } - } - - if (!(chip->card_exist & SD_CARD) && !chip->sd_io) - clear_bit(SD_NR, &chip->need_release); - if (!(chip->card_exist & XD_CARD)) - clear_bit(XD_NR, &chip->need_release); - if (!(chip->card_exist & MS_CARD)) - clear_bit(MS_NR, &chip->need_release); - - dev_dbg(rtsx_dev(chip), "chip->need_release = 0x%x\n", - (unsigned int)(chip->need_release)); - -#ifdef SUPPORT_OCP - if (chip->need_release) { - if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER)) - rtsx_write_register(chip, OCPCLR, - CARD_OC_INT_CLR | - CARD_OC_CLR, - CARD_OC_INT_CLR | - CARD_OC_CLR); - chip->ocp_stat = 0; - } -#endif - if (chip->need_release) { - rtsx_set_stat(chip, RTSX_STAT_RUN); - rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); - } - - if (chip->need_release & SD_CARD) { - clear_bit(SD_NR, &chip->need_release); - chip->card_exist &= ~SD_CARD; - chip->card_ejected &= ~SD_CARD; - chip->card_fail &= ~SD_CARD; - CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]); - chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0; - rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - - release_sdio(chip); - release_sd_card(chip); - } - - if (chip->need_release & XD_CARD) { - clear_bit(XD_NR, &chip->need_release); - chip->card_exist &= ~XD_CARD; - chip->card_ejected &= ~XD_CARD; - chip->card_fail &= ~XD_CARD; - CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]); - chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0; - - release_xd_card(chip); - - if (CHECK_PID(chip, 0x5288) && - CHECK_BARO_PKG(chip, QFN)) - rtsx_write_register(chip, HOST_SLEEP_STATE, - 0xC0, 0xC0); - } - - if (chip->need_release & MS_CARD) { - clear_bit(MS_NR, &chip->need_release); - chip->card_exist &= ~MS_CARD; - chip->card_ejected &= ~MS_CARD; - chip->card_fail &= ~MS_CARD; - CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]); - chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0; - - release_ms_card(chip); - } - - dev_dbg(rtsx_dev(chip), "chip->card_exist = 0x%x\n", - chip->card_exist); - - if (!chip->card_exist) - turn_off_led(chip, LED_GPIO); - } - - if (chip->need_reset) { - dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x\n", - (unsigned int)(chip->need_reset)); - - rtsx_reset_cards(chip); - } - - if (chip->need_reinit) { - dev_dbg(rtsx_dev(chip), "chip->need_reinit = 0x%x\n", - (unsigned int)(chip->need_reinit)); - - rtsx_reinit_cards(chip, 0); - } -} - -int switch_ssc_clock(struct rtsx_chip *chip, int clk) -{ - int retval; - u8 n = (u8)(clk - 2), min_n, max_n; - u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask; - int sd_vpclk_phase_reset = 0; - - if (chip->cur_clk == clk) - return STATUS_SUCCESS; - - min_n = 60; - max_n = 120; - max_div = CLK_DIV_4; - - dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n", - clk, chip->cur_clk); - - if (clk <= 2 || n > max_n) - return STATUS_FAIL; - - mcu_cnt = (u8)(125 / clk + 3); - if (mcu_cnt > 7) - mcu_cnt = 7; - - div = CLK_DIV_1; - while ((n < min_n) && (div < max_div)) { - n = (n + 2) * 2 - 2; - div++; - } - dev_dbg(rtsx_dev(chip), "n = %d, div = %d\n", n, div); - - if (chip->ssc_en) { - ssc_depth = 0x01; - n -= 2; - } else { - ssc_depth = 0; - } - - ssc_depth_mask = 0x03; - - dev_dbg(rtsx_dev(chip), "ssc_depth = %d\n", ssc_depth); - - rtsx_init_cmd(chip); - rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); - rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth); - rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n); - rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB); - if (sd_vpclk_phase_reset) { - rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - } - - retval = rtsx_send_cmd(chip, 0, WAIT_TIME); - if (retval < 0) - return STATUS_ERROR; - - udelay(10); - retval = rtsx_write_register(chip, CLK_CTL, CLK_LOW_FREQ, 0); - if (retval) - return retval; - - chip->cur_clk = clk; - - return STATUS_SUCCESS; -} - -int switch_normal_clock(struct rtsx_chip *chip, int clk) -{ - int retval; - u8 sel, div, mcu_cnt; - int sd_vpclk_phase_reset = 0; - - if (chip->cur_clk == clk) - return STATUS_SUCCESS; - - switch (clk) { - case CLK_20: - dev_dbg(rtsx_dev(chip), "Switch clock to 20MHz\n"); - sel = SSC_80; - div = CLK_DIV_4; - mcu_cnt = 7; - break; - - case CLK_30: - dev_dbg(rtsx_dev(chip), "Switch clock to 30MHz\n"); - sel = SSC_120; - div = CLK_DIV_4; - mcu_cnt = 7; - break; - - case CLK_40: - dev_dbg(rtsx_dev(chip), "Switch clock to 40MHz\n"); - sel = SSC_80; - div = CLK_DIV_2; - mcu_cnt = 7; - break; - - case CLK_50: - dev_dbg(rtsx_dev(chip), "Switch clock to 50MHz\n"); - sel = SSC_100; - div = CLK_DIV_2; - mcu_cnt = 6; - break; - - case CLK_60: - dev_dbg(rtsx_dev(chip), "Switch clock to 60MHz\n"); - sel = SSC_120; - div = CLK_DIV_2; - mcu_cnt = 6; - break; - - case CLK_80: - dev_dbg(rtsx_dev(chip), "Switch clock to 80MHz\n"); - sel = SSC_80; - div = CLK_DIV_1; - mcu_cnt = 5; - break; - - case CLK_100: - dev_dbg(rtsx_dev(chip), "Switch clock to 100MHz\n"); - sel = SSC_100; - div = CLK_DIV_1; - mcu_cnt = 5; - break; - - case CLK_120: - dev_dbg(rtsx_dev(chip), "Switch clock to 120MHz\n"); - sel = SSC_120; - div = CLK_DIV_1; - mcu_cnt = 5; - break; - - case CLK_150: - dev_dbg(rtsx_dev(chip), "Switch clock to 150MHz\n"); - sel = SSC_150; - div = CLK_DIV_1; - mcu_cnt = 4; - break; - - case CLK_200: - dev_dbg(rtsx_dev(chip), "Switch clock to 200MHz\n"); - sel = SSC_200; - div = CLK_DIV_1; - mcu_cnt = 4; - break; - - default: - dev_dbg(rtsx_dev(chip), "Try to switch to an illegal clock (%d)\n", - clk); - return STATUS_FAIL; - } - - retval = rtsx_write_register(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ); - if (retval) - return retval; - if (sd_vpclk_phase_reset) { - retval = rtsx_write_register(chip, SD_VPCLK0_CTL, - PHASE_NOT_RESET, 0); - if (retval) - return retval; - retval = rtsx_write_register(chip, SD_VPCLK1_CTL, - PHASE_NOT_RESET, 0); - if (retval) - return retval; - } - retval = rtsx_write_register(chip, CLK_DIV, 0xFF, - (div << 4) | mcu_cnt); - if (retval) - return retval; - retval = rtsx_write_register(chip, CLK_SEL, 0xFF, sel); - if (retval) - return retval; - - if (sd_vpclk_phase_reset) { - udelay(200); - retval = rtsx_write_register(chip, SD_VPCLK0_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - if (retval) - return retval; - retval = rtsx_write_register(chip, SD_VPCLK1_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - if (retval) - return retval; - udelay(200); - } - retval = rtsx_write_register(chip, CLK_CTL, 0xFF, 0); - if (retval) - return retval; - - chip->cur_clk = clk; - - return STATUS_SUCCESS; -} - -void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, - u32 byte_cnt, u8 pack_size) -{ - if (pack_size > DMA_1024) - pack_size = DMA_512; - - rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT); - - rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt); - - if (dir == DMA_FROM_DEVICE) { - rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, - 0x03 | DMA_PACK_SIZE_MASK, - DMA_DIR_FROM_CARD | DMA_EN | pack_size); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, - 0x03 | DMA_PACK_SIZE_MASK, - DMA_DIR_TO_CARD | DMA_EN | pack_size); - } - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); -} - -int enable_card_clock(struct rtsx_chip *chip, u8 card) -{ - int retval; - u8 clk_en = 0; - - if (card & XD_CARD) - clk_en |= XD_CLK_EN; - if (card & SD_CARD) - clk_en |= SD_CLK_EN; - if (card & MS_CARD) - clk_en |= MS_CLK_EN; - - retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, clk_en); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int disable_card_clock(struct rtsx_chip *chip, u8 card) -{ - int retval; - u8 clk_en = 0; - - if (card & XD_CARD) - clk_en |= XD_CLK_EN; - if (card & SD_CARD) - clk_en |= SD_CLK_EN; - if (card & MS_CARD) - clk_en |= MS_CLK_EN; - - retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, 0); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int card_power_on(struct rtsx_chip *chip, u8 card) -{ - int retval; - u8 mask, val1, val2; - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) { - mask = MS_POWER_MASK; - val1 = MS_PARTIAL_POWER_ON; - val2 = MS_POWER_ON; - } else { - mask = SD_POWER_MASK; - val1 = SD_PARTIAL_POWER_ON; - val2 = SD_POWER_ON; - } - - rtsx_init_cmd(chip); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - udelay(chip->pmos_pwr_on_interval); - - rtsx_init_cmd(chip); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int card_power_off(struct rtsx_chip *chip, u8 card) -{ - int retval; - u8 mask, val; - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) { - mask = MS_POWER_MASK; - val = MS_POWER_OFF; - } else { - mask = SD_POWER_MASK; - val = SD_POWER_OFF; - } - - retval = rtsx_write_register(chip, CARD_PWR_CTL, mask, val); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 sec_addr, u16 sec_cnt) -{ - int retval; - unsigned int lun = SCSI_LUN(srb); - int i; - - if (!chip->rw_card[lun]) - return STATUS_FAIL; - - for (i = 0; i < 3; i++) { - chip->rw_need_retry = 0; - - retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt); - if (retval != STATUS_SUCCESS) { - if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) { - rtsx_release_chip(chip); - return STATUS_FAIL; - } - if (detect_card_cd(chip, chip->cur_card) != - STATUS_SUCCESS) { - return STATUS_FAIL; - } - - if (!chip->rw_need_retry) { - dev_dbg(rtsx_dev(chip), "RW fail, but no need to retry\n"); - break; - } - } else { - chip->rw_need_retry = 0; - break; - } - - dev_dbg(rtsx_dev(chip), "Retry RW, (i = %d)\n", i); - } - - return retval; -} - -int card_share_mode(struct rtsx_chip *chip, int card) -{ - int retval; - u8 mask, value; - - if (CHECK_PID(chip, 0x5208)) { - mask = CARD_SHARE_MASK; - if (card == SD_CARD) - value = CARD_SHARE_48_SD; - else if (card == MS_CARD) - value = CARD_SHARE_48_MS; - else if (card == XD_CARD) - value = CARD_SHARE_48_XD; - else - return STATUS_FAIL; - - } else if (CHECK_PID(chip, 0x5288)) { - mask = 0x03; - if (card == SD_CARD) - value = CARD_SHARE_BAROSSA_SD; - else if (card == MS_CARD) - value = CARD_SHARE_BAROSSA_MS; - else if (card == XD_CARD) - value = CARD_SHARE_BAROSSA_XD; - else - return STATUS_FAIL; - - } else { - return STATUS_FAIL; - } - - retval = rtsx_write_register(chip, CARD_SHARE_MODE, mask, value); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int select_card(struct rtsx_chip *chip, int card) -{ - int retval; - - if (chip->cur_card != card) { - u8 mod; - - if (card == SD_CARD) - mod = SD_MOD_SEL; - else if (card == MS_CARD) - mod = MS_MOD_SEL; - else if (card == XD_CARD) - mod = XD_MOD_SEL; - else if (card == SPI_CARD) - mod = SPI_MOD_SEL; - else - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_SELECT, 0x07, mod); - if (retval) - return retval; - chip->cur_card = card; - - retval = card_share_mode(chip, card); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -void toggle_gpio(struct rtsx_chip *chip, u8 gpio) -{ - u8 temp_reg; - - rtsx_read_register(chip, CARD_GPIO, &temp_reg); - temp_reg ^= (0x01 << gpio); - rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg); -} - -void turn_on_led(struct rtsx_chip *chip, u8 gpio) -{ - if (CHECK_PID(chip, 0x5288)) - rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), - (u8)(1 << gpio)); - else - rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); -} - -void turn_off_led(struct rtsx_chip *chip, u8 gpio) -{ - if (CHECK_PID(chip, 0x5288)) - rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0); - else - rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), - (u8)(1 << gpio)); -} - -int detect_card_cd(struct rtsx_chip *chip, int card) -{ - u32 card_cd, status; - - if (card == SD_CARD) { - card_cd = SD_EXIST; - } else if (card == MS_CARD) { - card_cd = MS_EXIST; - } else if (card == XD_CARD) { - card_cd = XD_EXIST; - } else { - dev_dbg(rtsx_dev(chip), "Wrong card type: 0x%x\n", card); - return STATUS_FAIL; - } - - status = rtsx_readl(chip, RTSX_BIPR); - if (!(status & card_cd)) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int check_card_exist(struct rtsx_chip *chip, unsigned int lun) -{ - if (chip->card_exist & chip->lun2card[lun]) - return 1; - - return 0; -} - -int check_card_ready(struct rtsx_chip *chip, unsigned int lun) -{ - if (chip->card_ready & chip->lun2card[lun]) - return 1; - - return 0; -} - -int check_card_wp(struct rtsx_chip *chip, unsigned int lun) -{ - if (chip->card_wp & chip->lun2card[lun]) - return 1; - - return 0; -} - -u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun) -{ - if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) - return (u8)XD_CARD; - else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) - return (u8)SD_CARD; - else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) - return (u8)MS_CARD; - - return 0; -} - -void eject_card(struct rtsx_chip *chip, unsigned int lun) -{ - do_remaining_work(chip); - - if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) { - release_sd_card(chip); - chip->card_ejected |= SD_CARD; - chip->card_ready &= ~SD_CARD; - chip->capacity[lun] = 0; - } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) { - release_xd_card(chip); - chip->card_ejected |= XD_CARD; - chip->card_ready &= ~XD_CARD; - chip->capacity[lun] = 0; - } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) { - release_ms_card(chip); - chip->card_ejected |= MS_CARD; - chip->card_ready &= ~MS_CARD; - chip->capacity[lun] = 0; - } -} diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h deleted file mode 100644 index 39727371cd7adf4d8856760e6bf8cfc12dc34621..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_card.h +++ /dev/null @@ -1,1087 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_CARD_H -#define __REALTEK_RTSX_CARD_H - -#include "rtsx.h" -#include "rtsx_chip.h" -#include "rtsx_transport.h" -#include "sd.h" - -#define SSC_POWER_DOWN 0x01 -#define SD_OC_POWER_DOWN 0x02 -#define MS_OC_POWER_DOWN 0x04 -#define ALL_POWER_DOWN 0x07 -#define OC_POWER_DOWN 0x06 - -#define PMOS_STRG_MASK 0x10 -#define PMOS_STRG_800mA 0x10 -#define PMOS_STRG_400mA 0x00 - -#define POWER_OFF 0x03 -#define PARTIAL_POWER_ON 0x01 -#define POWER_ON 0x00 - -#define MS_POWER_OFF 0x0C -#define MS_PARTIAL_POWER_ON 0x04 -#define MS_POWER_ON 0x00 -#define MS_POWER_MASK 0x0C - -#define SD_POWER_OFF 0x03 -#define SD_PARTIAL_POWER_ON 0x01 -#define SD_POWER_ON 0x00 -#define SD_POWER_MASK 0x03 - -#define XD_OUTPUT_EN 0x02 -#define SD_OUTPUT_EN 0x04 -#define MS_OUTPUT_EN 0x08 -#define SPI_OUTPUT_EN 0x10 - -#define CLK_LOW_FREQ 0x01 - -#define CLK_DIV_1 0x01 -#define CLK_DIV_2 0x02 -#define CLK_DIV_4 0x03 -#define CLK_DIV_8 0x04 - -#define SSC_80 0 -#define SSC_100 1 -#define SSC_120 2 -#define SSC_150 3 -#define SSC_200 4 - -#define XD_CLK_EN 0x02 -#define SD_CLK_EN 0x04 -#define MS_CLK_EN 0x08 -#define SPI_CLK_EN 0x10 - -#define XD_MOD_SEL 1 -#define SD_MOD_SEL 2 -#define MS_MOD_SEL 3 -#define SPI_MOD_SEL 4 - -#define CHANGE_CLK 0x01 - -#define SD_CRC7_ERR 0x80 -#define SD_CRC16_ERR 0x40 -#define SD_CRC_WRITE_ERR 0x20 -#define SD_CRC_WRITE_ERR_MASK 0x1C -#define GET_CRC_TIME_OUT 0x02 -#define SD_TUNING_COMPARE_ERR 0x01 - -#define SD_RSP_80CLK_TIMEOUT 0x01 - -#define SD_CLK_TOGGLE_EN 0x80 -#define SD_CLK_FORCE_STOP 0x40 -#define SD_DAT3_STATUS 0x10 -#define SD_DAT2_STATUS 0x08 -#define SD_DAT1_STATUS 0x04 -#define SD_DAT0_STATUS 0x02 -#define SD_CMD_STATUS 0x01 - -#define SD_IO_USING_1V8 0x80 -#define SD_IO_USING_3V3 0x7F -#define TYPE_A_DRIVING 0x00 -#define TYPE_B_DRIVING 0x01 -#define TYPE_C_DRIVING 0x02 -#define TYPE_D_DRIVING 0x03 - -#define DDR_FIX_RX_DAT 0x00 -#define DDR_VAR_RX_DAT 0x80 -#define DDR_FIX_RX_DAT_EDGE 0x00 -#define DDR_FIX_RX_DAT_14_DELAY 0x40 -#define DDR_FIX_RX_CMD 0x00 -#define DDR_VAR_RX_CMD 0x20 -#define DDR_FIX_RX_CMD_POS_EDGE 0x00 -#define DDR_FIX_RX_CMD_14_DELAY 0x10 -#define SD20_RX_POS_EDGE 0x00 -#define SD20_RX_14_DELAY 0x08 -#define SD20_RX_SEL_MASK 0x08 - -#define DDR_FIX_TX_CMD_DAT 0x00 -#define DDR_VAR_TX_CMD_DAT 0x80 -#define DDR_FIX_TX_DAT_14_TSU 0x00 -#define DDR_FIX_TX_DAT_12_TSU 0x40 -#define DDR_FIX_TX_CMD_NEG_EDGE 0x00 -#define DDR_FIX_TX_CMD_14_AHEAD 0x20 -#define SD20_TX_NEG_EDGE 0x00 -#define SD20_TX_14_AHEAD 0x10 -#define SD20_TX_SEL_MASK 0x10 -#define DDR_VAR_SDCLK_POL_SWAP 0x01 - -#define SD_TRANSFER_START 0x80 -#define SD_TRANSFER_END 0x40 -#define SD_STAT_IDLE 0x20 -#define SD_TRANSFER_ERR 0x10 -#define SD_TM_NORMAL_WRITE 0x00 -#define SD_TM_AUTO_WRITE_3 0x01 -#define SD_TM_AUTO_WRITE_4 0x02 -#define SD_TM_AUTO_READ_3 0x05 -#define SD_TM_AUTO_READ_4 0x06 -#define SD_TM_CMD_RSP 0x08 -#define SD_TM_AUTO_WRITE_1 0x09 -#define SD_TM_AUTO_WRITE_2 0x0A -#define SD_TM_NORMAL_READ 0x0C -#define SD_TM_AUTO_READ_1 0x0D -#define SD_TM_AUTO_READ_2 0x0E -#define SD_TM_AUTO_TUNING 0x0F - -#define PHASE_CHANGE 0x80 -#define PHASE_NOT_RESET 0x40 - -#define DCMPS_CHANGE 0x80 -#define DCMPS_CHANGE_DONE 0x40 -#define DCMPS_ERROR 0x20 -#define DCMPS_CURRENT_PHASE 0x1F - -#define SD_CLK_DIVIDE_0 0x00 -#define SD_CLK_DIVIDE_256 0xC0 -#define SD_CLK_DIVIDE_128 0x80 -#define SD_BUS_WIDTH_1 0x00 -#define SD_BUS_WIDTH_4 0x01 -#define SD_BUS_WIDTH_8 0x02 -#define SD_ASYNC_FIFO_NOT_RST 0x10 -#define SD_20_MODE 0x00 -#define SD_DDR_MODE 0x04 -#define SD_30_MODE 0x08 - -#define SD_CLK_DIVIDE_MASK 0xC0 - -#define SD_CMD_IDLE 0x80 - -#define SD_DATA_IDLE 0x80 - -#define DCM_RESET 0x08 -#define DCM_LOCKED 0x04 -#define DCM_208M 0x00 -#define DCM_TX 0x01 -#define DCM_RX 0x02 - -#define DRP_START 0x80 -#define DRP_DONE 0x40 - -#define DRP_WRITE 0x80 -#define DRP_READ 0x00 -#define DCM_WRITE_ADDRESS_50 0x50 -#define DCM_WRITE_ADDRESS_51 0x51 -#define DCM_READ_ADDRESS_00 0x00 -#define DCM_READ_ADDRESS_51 0x51 - -#define SD_CALCULATE_CRC7 0x00 -#define SD_NO_CALCULATE_CRC7 0x80 -#define SD_CHECK_CRC16 0x00 -#define SD_NO_CHECK_CRC16 0x40 -#define SD_NO_CHECK_WAIT_CRC_TO 0x20 -#define SD_WAIT_BUSY_END 0x08 -#define SD_NO_WAIT_BUSY_END 0x00 -#define SD_CHECK_CRC7 0x00 -#define SD_NO_CHECK_CRC7 0x04 -#define SD_RSP_LEN_0 0x00 -#define SD_RSP_LEN_6 0x01 -#define SD_RSP_LEN_17 0x02 -#define SD_RSP_TYPE_R0 0x04 -#define SD_RSP_TYPE_R1 0x01 -#define SD_RSP_TYPE_R1b 0x09 -#define SD_RSP_TYPE_R2 0x02 -#define SD_RSP_TYPE_R3 0x05 -#define SD_RSP_TYPE_R4 0x05 -#define SD_RSP_TYPE_R5 0x01 -#define SD_RSP_TYPE_R6 0x01 -#define SD_RSP_TYPE_R7 0x01 - -#define SD_RSP_80CLK_TIMEOUT_EN 0x01 - -#define SAMPLE_TIME_RISING 0x00 -#define SAMPLE_TIME_FALLING 0x80 -#define PUSH_TIME_DEFAULT 0x00 -#define PUSH_TIME_ODD 0x40 -#define NO_EXTEND_TOGGLE 0x00 -#define EXTEND_TOGGLE_CHK 0x20 -#define MS_BUS_WIDTH_1 0x00 -#define MS_BUS_WIDTH_4 0x10 -#define MS_BUS_WIDTH_8 0x18 -#define MS_2K_SECTOR_MODE 0x04 -#define MS_512_SECTOR_MODE 0x00 -#define MS_TOGGLE_TIMEOUT_EN 0x00 -#define MS_TOGGLE_TIMEOUT_DISEN 0x01 -#define MS_NO_CHECK_INT 0x02 - -#define WAIT_INT 0x80 -#define NO_WAIT_INT 0x00 -#define NO_AUTO_READ_INT_REG 0x00 -#define AUTO_READ_INT_REG 0x40 -#define MS_CRC16_ERR 0x20 -#define MS_RDY_TIMEOUT 0x10 -#define MS_INT_CMDNK 0x08 -#define MS_INT_BREQ 0x04 -#define MS_INT_ERR 0x02 -#define MS_INT_CED 0x01 - -#define MS_TRANSFER_START 0x80 -#define MS_TRANSFER_END 0x40 -#define MS_TRANSFER_ERR 0x20 -#define MS_BS_STATE 0x10 -#define MS_TM_READ_BYTES 0x00 -#define MS_TM_NORMAL_READ 0x01 -#define MS_TM_WRITE_BYTES 0x04 -#define MS_TM_NORMAL_WRITE 0x05 -#define MS_TM_AUTO_READ 0x08 -#define MS_TM_AUTO_WRITE 0x0C - -#define CARD_SHARE_MASK 0x0F -#define CARD_SHARE_MULTI_LUN 0x00 -#define CARD_SHARE_NORMAL 0x00 -#define CARD_SHARE_48_XD 0x02 -#define CARD_SHARE_48_SD 0x04 -#define CARD_SHARE_48_MS 0x08 -#define CARD_SHARE_BAROSSA_XD 0x00 -#define CARD_SHARE_BAROSSA_SD 0x01 -#define CARD_SHARE_BAROSSA_MS 0x02 - -#define MS_DRIVE_8 0x00 -#define MS_DRIVE_4 0x40 -#define MS_DRIVE_12 0x80 -#define SD_DRIVE_8 0x00 -#define SD_DRIVE_4 0x10 -#define SD_DRIVE_12 0x20 -#define XD_DRIVE_8 0x00 -#define XD_DRIVE_4 0x04 -#define XD_DRIVE_12 0x08 - -#define SPI_STOP 0x01 -#define XD_STOP 0x02 -#define SD_STOP 0x04 -#define MS_STOP 0x08 -#define SPI_CLR_ERR 0x10 -#define XD_CLR_ERR 0x20 -#define SD_CLR_ERR 0x40 -#define MS_CLR_ERR 0x80 - -#define CRC_FIX_CLK (0x00 << 0) -#define CRC_VAR_CLK0 (0x01 << 0) -#define CRC_VAR_CLK1 (0x02 << 0) -#define SD30_FIX_CLK (0x00 << 2) -#define SD30_VAR_CLK0 (0x01 << 2) -#define SD30_VAR_CLK1 (0x02 << 2) -#define SAMPLE_FIX_CLK (0x00 << 4) -#define SAMPLE_VAR_CLK0 (0x01 << 4) -#define SAMPLE_VAR_CLK1 (0x02 << 4) - -#define SDIO_VER_20 0x80 -#define SDIO_VER_10 0x00 -#define SDIO_VER_CHG 0x40 -#define SDIO_BUS_AUTO_SWITCH 0x10 - -#define PINGPONG_BUFFER 0x01 -#define RING_BUFFER 0x00 - -#define RB_FLUSH 0x80 - -#define DMA_DONE_INT_EN 0x80 -#define SUSPEND_INT_EN 0x40 -#define LINK_RDY_INT_EN 0x20 -#define LINK_DOWN_INT_EN 0x10 - -#define DMA_DONE_INT 0x80 -#define SUSPEND_INT 0x40 -#define LINK_RDY_INT 0x20 -#define LINK_DOWN_INT 0x10 - -#define MRD_ERR_INT_EN 0x40 -#define MWR_ERR_INT_EN 0x20 -#define SCSI_CMD_INT_EN 0x10 -#define TLP_RCV_INT_EN 0x08 -#define TLP_TRSMT_INT_EN 0x04 -#define MRD_COMPLETE_INT_EN 0x02 -#define MWR_COMPLETE_INT_EN 0x01 - -#define MRD_ERR_INT 0x40 -#define MWR_ERR_INT 0x20 -#define SCSI_CMD_INT 0x10 -#define TLP_RX_INT 0x08 -#define TLP_TX_INT 0x04 -#define MRD_COMPLETE_INT 0x02 -#define MWR_COMPLETE_INT 0x01 - -#define MSG_RX_INT_EN 0x08 -#define MRD_RX_INT_EN 0x04 -#define MWR_RX_INT_EN 0x02 -#define CPLD_RX_INT_EN 0x01 - -#define MSG_RX_INT 0x08 -#define MRD_RX_INT 0x04 -#define MWR_RX_INT 0x02 -#define CPLD_RX_INT 0x01 - -#define MSG_TX_INT_EN 0x08 -#define MRD_TX_INT_EN 0x04 -#define MWR_TX_INT_EN 0x02 -#define CPLD_TX_INT_EN 0x01 - -#define MSG_TX_INT 0x08 -#define MRD_TX_INT 0x04 -#define MWR_TX_INT 0x02 -#define CPLD_TX_INT 0x01 - -#define DMA_RST 0x80 -#define DMA_BUSY 0x04 -#define DMA_DIR_TO_CARD 0x00 -#define DMA_DIR_FROM_CARD 0x02 -#define DMA_EN 0x01 -#define DMA_128 (0 << 4) -#define DMA_256 (1 << 4) -#define DMA_512 (2 << 4) -#define DMA_1024 (3 << 4) -#define DMA_PACK_SIZE_MASK 0x30 - -#define XD_PWR_OFF_DELAY0 0x00 -#define XD_PWR_OFF_DELAY1 0x02 -#define XD_PWR_OFF_DELAY2 0x04 -#define XD_PWR_OFF_DELAY3 0x06 -#define XD_AUTO_PWR_OFF_EN 0xF7 -#define XD_NO_AUTO_PWR_OFF 0x08 - -#define XD_TIME_RWN_1 0x00 -#define XD_TIME_RWN_STEP 0x20 -#define XD_TIME_RW_1 0x00 -#define XD_TIME_RW_STEP 0x04 -#define XD_TIME_SETUP_1 0x00 -#define XD_TIME_SETUP_STEP 0x01 - -#define XD_ECC2_UNCORRECTABLE 0x80 -#define XD_ECC2_ERROR 0x40 -#define XD_ECC1_UNCORRECTABLE 0x20 -#define XD_ECC1_ERROR 0x10 -#define XD_RDY 0x04 -#define XD_CE_EN 0xFD -#define XD_CE_DISEN 0x02 -#define XD_WP_EN 0xFE -#define XD_WP_DISEN 0x01 - -#define XD_TRANSFER_START 0x80 -#define XD_TRANSFER_END 0x40 -#define XD_PPB_EMPTY 0x20 -#define XD_RESET 0x00 -#define XD_ERASE 0x01 -#define XD_READ_STATUS 0x02 -#define XD_READ_ID 0x03 -#define XD_READ_REDUNDANT 0x04 -#define XD_READ_PAGES 0x05 -#define XD_SET_CMD 0x06 -#define XD_NORMAL_READ 0x07 -#define XD_WRITE_PAGES 0x08 -#define XD_NORMAL_WRITE 0x09 -#define XD_WRITE_REDUNDANT 0x0A -#define XD_SET_ADDR 0x0B - -#define XD_PPB_TO_SIE 0x80 -#define XD_TO_PPB_ONLY 0x00 -#define XD_BA_TRANSFORM 0x40 -#define XD_BA_NO_TRANSFORM 0x00 -#define XD_NO_CALC_ECC 0x20 -#define XD_CALC_ECC 0x00 -#define XD_IGNORE_ECC 0x10 -#define XD_CHECK_ECC 0x00 -#define XD_DIRECT_TO_RB 0x08 -#define XD_ADDR_LENGTH_0 0x00 -#define XD_ADDR_LENGTH_1 0x01 -#define XD_ADDR_LENGTH_2 0x02 -#define XD_ADDR_LENGTH_3 0x03 -#define XD_ADDR_LENGTH_4 0x04 - -#define XD_GPG 0xFF -#define XD_BPG 0x00 - -#define XD_GBLK 0xFF -#define XD_LATER_BBLK 0xF0 - -#define XD_ECC2_ALL1 0x80 -#define XD_ECC1_ALL1 0x40 -#define XD_BA2_ALL0 0x20 -#define XD_BA1_ALL0 0x10 -#define XD_BA1_BA2_EQL 0x04 -#define XD_BA2_VALID 0x02 -#define XD_BA1_VALID 0x01 - -#define XD_PGSTS_ZEROBIT_OVER4 0x00 -#define XD_PGSTS_NOT_FF 0x02 -#define XD_AUTO_CHK_DATA_STATUS 0x01 - -#define RSTB_MODE_DETECT 0x80 -#define MODE_OUT_VLD 0x40 -#define MODE_OUT_0_NONE 0x00 -#define MODE_OUT_10_NONE 0x04 -#define MODE_OUT_10_47 0x05 -#define MODE_OUT_10_180 0x06 -#define MODE_OUT_10_680 0x07 -#define MODE_OUT_16_NONE 0x08 -#define MODE_OUT_16_47 0x09 -#define MODE_OUT_16_180 0x0A -#define MODE_OUT_16_680 0x0B -#define MODE_OUT_NONE_NONE 0x0C -#define MODE_OUT_NONE_47 0x0D -#define MODE_OUT_NONE_180 0x0E -#define MODE_OUT_NONE_680 0x0F - -#define CARD_OC_INT_EN 0x20 -#define CARD_DETECT_EN 0x08 - -#define MS_DETECT_EN 0x80 -#define MS_OCP_INT_EN 0x40 -#define MS_OCP_INT_CLR 0x20 -#define MS_OC_CLR 0x10 -#define SD_DETECT_EN 0x08 -#define SD_OCP_INT_EN 0x04 -#define SD_OCP_INT_CLR 0x02 -#define SD_OC_CLR 0x01 - -#define CARD_OCP_DETECT 0x80 -#define CARD_OC_NOW 0x08 -#define CARD_OC_EVER 0x04 - -#define MS_OCP_DETECT 0x80 -#define MS_OC_NOW 0x40 -#define MS_OC_EVER 0x20 -#define SD_OCP_DETECT 0x08 -#define SD_OC_NOW 0x04 -#define SD_OC_EVER 0x02 - -#define CARD_OC_INT_CLR 0x08 -#define CARD_OC_CLR 0x02 - -#define SD_OCP_GLITCH_MASK 0x07 -#define SD_OCP_GLITCH_6_4 0x00 -#define SD_OCP_GLITCH_64 0x01 -#define SD_OCP_GLITCH_640 0x02 -#define SD_OCP_GLITCH_1000 0x03 -#define SD_OCP_GLITCH_2000 0x04 -#define SD_OCP_GLITCH_4000 0x05 -#define SD_OCP_GLITCH_8000 0x06 -#define SD_OCP_GLITCH_10000 0x07 - -#define MS_OCP_GLITCH_MASK 0x70 -#define MS_OCP_GLITCH_6_4 (0x00 << 4) -#define MS_OCP_GLITCH_64 (0x01 << 4) -#define MS_OCP_GLITCH_640 (0x02 << 4) -#define MS_OCP_GLITCH_1000 (0x03 << 4) -#define MS_OCP_GLITCH_2000 (0x04 << 4) -#define MS_OCP_GLITCH_4000 (0x05 << 4) -#define MS_OCP_GLITCH_8000 (0x06 << 4) -#define MS_OCP_GLITCH_10000 (0x07 << 4) - -#define OCP_TIME_60 0x00 -#define OCP_TIME_100 (0x01 << 3) -#define OCP_TIME_200 (0x02 << 3) -#define OCP_TIME_400 (0x03 << 3) -#define OCP_TIME_600 (0x04 << 3) -#define OCP_TIME_800 (0x05 << 3) -#define OCP_TIME_1100 (0x06 << 3) -#define OCP_TIME_MASK 0x38 - -#define MS_OCP_TIME_60 0x00 -#define MS_OCP_TIME_100 (0x01 << 4) -#define MS_OCP_TIME_200 (0x02 << 4) -#define MS_OCP_TIME_400 (0x03 << 4) -#define MS_OCP_TIME_600 (0x04 << 4) -#define MS_OCP_TIME_800 (0x05 << 4) -#define MS_OCP_TIME_1100 (0x06 << 4) -#define MS_OCP_TIME_MASK 0x70 - -#define SD_OCP_TIME_60 0x00 -#define SD_OCP_TIME_100 0x01 -#define SD_OCP_TIME_200 0x02 -#define SD_OCP_TIME_400 0x03 -#define SD_OCP_TIME_600 0x04 -#define SD_OCP_TIME_800 0x05 -#define SD_OCP_TIME_1100 0x06 -#define SD_OCP_TIME_MASK 0x07 - -#define OCP_THD_315_417 0x00 -#define OCP_THD_283_783 (0x01 << 6) -#define OCP_THD_244_946 (0x02 << 6) -#define OCP_THD_191_1080 (0x03 << 6) -#define OCP_THD_MASK 0xC0 - -#define MS_OCP_THD_450 0x00 -#define MS_OCP_THD_550 (0x01 << 4) -#define MS_OCP_THD_650 (0x02 << 4) -#define MS_OCP_THD_750 (0x03 << 4) -#define MS_OCP_THD_850 (0x04 << 4) -#define MS_OCP_THD_950 (0x05 << 4) -#define MS_OCP_THD_1050 (0x06 << 4) -#define MS_OCP_THD_1150 (0x07 << 4) -#define MS_OCP_THD_MASK 0x70 - -#define SD_OCP_THD_450 0x00 -#define SD_OCP_THD_550 0x01 -#define SD_OCP_THD_650 0x02 -#define SD_OCP_THD_750 0x03 -#define SD_OCP_THD_850 0x04 -#define SD_OCP_THD_950 0x05 -#define SD_OCP_THD_1050 0x06 -#define SD_OCP_THD_1150 0x07 -#define SD_OCP_THD_MASK 0x07 - -#define FPGA_MS_PULL_CTL_EN 0xEF -#define FPGA_SD_PULL_CTL_EN 0xF7 -#define FPGA_XD_PULL_CTL_EN1 0xFE -#define FPGA_XD_PULL_CTL_EN2 0xFD -#define FPGA_XD_PULL_CTL_EN3 0xFB - -#define FPGA_MS_PULL_CTL_BIT 0x10 -#define FPGA_SD_PULL_CTL_BIT 0x08 - -#define BLINK_EN 0x08 -#define LED_GPIO0 (0 << 4) -#define LED_GPIO1 (1 << 4) -#define LED_GPIO2 (2 << 4) - -#define SDIO_BUS_CTRL 0x01 -#define SDIO_CD_CTRL 0x02 - -#define SSC_RSTB 0x80 -#define SSC_8X_EN 0x40 -#define SSC_FIX_FRAC 0x20 -#define SSC_SEL_1M 0x00 -#define SSC_SEL_2M 0x08 -#define SSC_SEL_4M 0x10 -#define SSC_SEL_8M 0x18 - -#define SSC_DEPTH_MASK 0x07 -#define SSC_DEPTH_DISALBE 0x00 -#define SSC_DEPTH_4M 0x01 -#define SSC_DEPTH_2M 0x02 -#define SSC_DEPTH_1M 0x03 -#define SSC_DEPTH_512K 0x04 -#define SSC_DEPTH_256K 0x05 -#define SSC_DEPTH_128K 0x06 -#define SSC_DEPTH_64K 0x07 - -#define XD_D3_NP 0x00 -#define XD_D3_PD (0x01 << 6) -#define XD_D3_PU (0x02 << 6) -#define XD_D2_NP 0x00 -#define XD_D2_PD (0x01 << 4) -#define XD_D2_PU (0x02 << 4) -#define XD_D1_NP 0x00 -#define XD_D1_PD (0x01 << 2) -#define XD_D1_PU (0x02 << 2) -#define XD_D0_NP 0x00 -#define XD_D0_PD 0x01 -#define XD_D0_PU 0x02 - -#define SD_D7_NP 0x00 -#define SD_D7_PD (0x01 << 4) -#define SD_DAT7_PU (0x02 << 4) -#define SD_CLK_NP 0x00 -#define SD_CLK_PD (0x01 << 2) -#define SD_CLK_PU (0x02 << 2) -#define SD_D5_NP 0x00 -#define SD_D5_PD 0x01 -#define SD_D5_PU 0x02 - -#define MS_D1_NP 0x00 -#define MS_D1_PD (0x01 << 6) -#define MS_D1_PU (0x02 << 6) -#define MS_D2_NP 0x00 -#define MS_D2_PD (0x01 << 4) -#define MS_D2_PU (0x02 << 4) -#define MS_CLK_NP 0x00 -#define MS_CLK_PD (0x01 << 2) -#define MS_CLK_PU (0x02 << 2) -#define MS_D6_NP 0x00 -#define MS_D6_PD 0x01 -#define MS_D6_PU 0x02 - -#define XD_D7_NP 0x00 -#define XD_D7_PD (0x01 << 6) -#define XD_D7_PU (0x02 << 6) -#define XD_D6_NP 0x00 -#define XD_D6_PD (0x01 << 4) -#define XD_D6_PU (0x02 << 4) -#define XD_D5_NP 0x00 -#define XD_D5_PD (0x01 << 2) -#define XD_D5_PU (0x02 << 2) -#define XD_D4_NP 0x00 -#define XD_D4_PD 0x01 -#define XD_D4_PU 0x02 - -#define SD_D6_NP 0x00 -#define SD_D6_PD (0x01 << 6) -#define SD_D6_PU (0x02 << 6) -#define SD_D0_NP 0x00 -#define SD_D0_PD (0x01 << 4) -#define SD_D0_PU (0x02 << 4) -#define SD_D1_NP 0x00 -#define SD_D1_PD 0x01 -#define SD_D1_PU 0x02 - -#define MS_D3_NP 0x00 -#define MS_D3_PD (0x01 << 6) -#define MS_D3_PU (0x02 << 6) -#define MS_D0_NP 0x00 -#define MS_D0_PD (0x01 << 4) -#define MS_D0_PU (0x02 << 4) -#define MS_BS_NP 0x00 -#define MS_BS_PD (0x01 << 2) -#define MS_BS_PU (0x02 << 2) - -#define XD_WP_NP 0x00 -#define XD_WP_PD (0x01 << 6) -#define XD_WP_PU (0x02 << 6) -#define XD_CE_NP 0x00 -#define XD_CE_PD (0x01 << 3) -#define XD_CE_PU (0x02 << 3) -#define XD_CLE_NP 0x00 -#define XD_CLE_PD (0x01 << 1) -#define XD_CLE_PU (0x02 << 1) -#define XD_CD_PD 0x00 -#define XD_CD_PU 0x01 - -#define SD_D4_NP 0x00 -#define SD_D4_PD (0x01 << 6) -#define SD_D4_PU (0x02 << 6) - -#define MS_D7_NP 0x00 -#define MS_D7_PD (0x01 << 6) -#define MS_D7_PU (0x02 << 6) - -#define XD_RDY_NP 0x00 -#define XD_RDY_PD (0x01 << 6) -#define XD_RDY_PU (0x02 << 6) -#define XD_WE_NP 0x00 -#define XD_WE_PD (0x01 << 4) -#define XD_WE_PU (0x02 << 4) -#define XD_RE_NP 0x00 -#define XD_RE_PD (0x01 << 2) -#define XD_RE_PU (0x02 << 2) -#define XD_ALE_NP 0x00 -#define XD_ALE_PD 0x01 -#define XD_ALE_PU 0x02 - -#define SD_D3_NP 0x00 -#define SD_D3_PD (0x01 << 4) -#define SD_D3_PU (0x02 << 4) -#define SD_D2_NP 0x00 -#define SD_D2_PD (0x01 << 2) -#define SD_D2_PU (0x02 << 2) - -#define MS_INS_PD 0x00 -#define MS_INS_PU (0x01 << 7) -#define SD_WP_NP 0x00 -#define SD_WP_PD (0x01 << 5) -#define SD_WP_PU (0x02 << 5) -#define SD_CD_PD 0x00 -#define SD_CD_PU (0x01 << 4) -#define SD_CMD_NP 0x00 -#define SD_CMD_PD (0x01 << 2) -#define SD_CMD_PU (0x02 << 2) - -#define MS_D5_NP 0x00 -#define MS_D5_PD (0x01 << 2) -#define MS_D5_PU (0x02 << 2) -#define MS_D4_NP 0x00 -#define MS_D4_PD 0x01 -#define MS_D4_PU 0x02 - -#define FORCE_PM_CLOCK 0x10 -#define EN_CLOCK_PM 0x01 - -#define HOST_ENTER_S3 0x02 -#define HOST_ENTER_S1 0x01 - -#define AUX_PWR_DETECTED 0x01 - -#define PHY_DEBUG_MODE 0x01 - -#define SPI_COMMAND_BIT_8 0xE0 -#define SPI_ADDRESS_BIT_24 0x17 -#define SPI_ADDRESS_BIT_32 0x1F - -#define SPI_TRANSFER0_START 0x80 -#define SPI_TRANSFER0_END 0x40 -#define SPI_C_MODE0 0x00 -#define SPI_CA_MODE0 0x01 -#define SPI_CDO_MODE0 0x02 -#define SPI_CDI_MODE0 0x03 -#define SPI_CADO_MODE0 0x04 -#define SPI_CADI_MODE0 0x05 -#define SPI_POLLING_MODE0 0x06 - -#define SPI_TRANSFER1_START 0x80 -#define SPI_TRANSFER1_END 0x40 -#define SPI_DO_MODE1 0x00 -#define SPI_DI_MODE1 0x01 - -#define CS_POLARITY_HIGH 0x40 -#define CS_POLARITY_LOW 0x00 -#define DTO_MSB_FIRST 0x00 -#define DTO_LSB_FIRST 0x20 -#define SPI_MASTER 0x00 -#define SPI_SLAVE 0x10 -#define SPI_MODE0 0x00 -#define SPI_MODE1 0x04 -#define SPI_MODE2 0x08 -#define SPI_MODE3 0x0C -#define SPI_MANUAL 0x00 -#define SPI_HALF_AUTO 0x01 -#define SPI_AUTO 0x02 -#define SPI_EEPROM_AUTO 0x03 - -#define EDO_TIMING_MASK 0x03 -#define SAMPLE_RISING 0x00 -#define SAMPLE_DELAY_HALF 0x01 -#define SAMPLE_DELAY_ONE 0x02 -#define SAPMLE_DELAY_ONE_HALF 0x03 -#define TCS_MASK 0x0C - -#define NOT_BYPASS_SD 0x02 -#define DISABLE_SDIO_FUNC 0x04 -#define SELECT_1LUN 0x08 - -#define PWR_GATE_EN 0x01 -#define LDO3318_PWR_MASK 0x06 -#define LDO_ON 0x00 -#define LDO_SUSPEND 0x04 -#define LDO_OFF 0x06 - -#define SD_CFG1 0xFDA0 -#define SD_CFG2 0xFDA1 -#define SD_CFG3 0xFDA2 -#define SD_STAT1 0xFDA3 -#define SD_STAT2 0xFDA4 -#define SD_BUS_STAT 0xFDA5 -#define SD_PAD_CTL 0xFDA6 -#define SD_SAMPLE_POINT_CTL 0xFDA7 -#define SD_PUSH_POINT_CTL 0xFDA8 -#define SD_CMD0 0xFDA9 -#define SD_CMD1 0xFDAA -#define SD_CMD2 0xFDAB -#define SD_CMD3 0xFDAC -#define SD_CMD4 0xFDAD -#define SD_CMD5 0xFDAE -#define SD_BYTE_CNT_L 0xFDAF -#define SD_BYTE_CNT_H 0xFDB0 -#define SD_BLOCK_CNT_L 0xFDB1 -#define SD_BLOCK_CNT_H 0xFDB2 -#define SD_TRANSFER 0xFDB3 -#define SD_CMD_STATE 0xFDB5 -#define SD_DATA_STATE 0xFDB6 - -#define DCM_DRP_CTL 0xFC23 -#define DCM_DRP_TRIG 0xFC24 -#define DCM_DRP_CFG 0xFC25 -#define DCM_DRP_WR_DATA_L 0xFC26 -#define DCM_DRP_WR_DATA_H 0xFC27 -#define DCM_DRP_RD_DATA_L 0xFC28 -#define DCM_DRP_RD_DATA_H 0xFC29 -#define SD_VPCLK0_CTL 0xFC2A -#define SD_VPCLK1_CTL 0xFC2B -#define SD_DCMPS0_CTL 0xFC2C -#define SD_DCMPS1_CTL 0xFC2D -#define SD_VPTX_CTL SD_VPCLK0_CTL -#define SD_VPRX_CTL SD_VPCLK1_CTL -#define SD_DCMPS_TX_CTL SD_DCMPS0_CTL -#define SD_DCMPS_RX_CTL SD_DCMPS1_CTL - -#define CARD_CLK_SOURCE 0xFC2E - -#define CARD_PWR_CTL 0xFD50 -#define CARD_CLK_SWITCH 0xFD51 -#define CARD_SHARE_MODE 0xFD52 -#define CARD_DRIVE_SEL 0xFD53 -#define CARD_STOP 0xFD54 -#define CARD_OE 0xFD55 -#define CARD_AUTO_BLINK 0xFD56 -#define CARD_GPIO_DIR 0xFD57 -#define CARD_GPIO 0xFD58 - -#define CARD_DATA_SOURCE 0xFD5B -#define CARD_SELECT 0xFD5C -#define SD30_DRIVE_SEL 0xFD5E - -#define CARD_CLK_EN 0xFD69 - -#define SDIO_CTRL 0xFD6B - -#define FPDCTL 0xFC00 -#define PDINFO 0xFC01 - -#define CLK_CTL 0xFC02 -#define CLK_DIV 0xFC03 -#define CLK_SEL 0xFC04 - -#define SSC_DIV_N_0 0xFC0F -#define SSC_DIV_N_1 0xFC10 - -#define RCCTL 0xFC14 - -#define FPGA_PULL_CTL 0xFC1D - -#define CARD_PULL_CTL1 0xFD60 -#define CARD_PULL_CTL2 0xFD61 -#define CARD_PULL_CTL3 0xFD62 -#define CARD_PULL_CTL4 0xFD63 -#define CARD_PULL_CTL5 0xFD64 -#define CARD_PULL_CTL6 0xFD65 - -#define IRQEN0 0xFE20 -#define IRQSTAT0 0xFE21 -#define IRQEN1 0xFE22 -#define IRQSTAT1 0xFE23 -#define TLPRIEN 0xFE24 -#define TLPRISTAT 0xFE25 -#define TLPTIEN 0xFE26 -#define TLPTISTAT 0xFE27 -#define DMATC0 0xFE28 -#define DMATC1 0xFE29 -#define DMATC2 0xFE2A -#define DMATC3 0xFE2B -#define DMACTL 0xFE2C -#define BCTL 0xFE2D -#define RBBC0 0xFE2E -#define RBBC1 0xFE2F -#define RBDAT 0xFE30 -#define RBCTL 0xFE34 -#define CFGADDR0 0xFE35 -#define CFGADDR1 0xFE36 -#define CFGDATA0 0xFE37 -#define CFGDATA1 0xFE38 -#define CFGDATA2 0xFE39 -#define CFGDATA3 0xFE3A -#define CFGRWCTL 0xFE3B -#define PHYRWCTL 0xFE3C -#define PHYDATA0 0xFE3D -#define PHYDATA1 0xFE3E -#define PHYADDR 0xFE3F -#define MSGRXDATA0 0xFE40 -#define MSGRXDATA1 0xFE41 -#define MSGRXDATA2 0xFE42 -#define MSGRXDATA3 0xFE43 -#define MSGTXDATA0 0xFE44 -#define MSGTXDATA1 0xFE45 -#define MSGTXDATA2 0xFE46 -#define MSGTXDATA3 0xFE47 -#define MSGTXCTL 0xFE48 -#define PETXCFG 0xFE49 - -#define CDRESUMECTL 0xFE52 -#define WAKE_SEL_CTL 0xFE54 -#define PME_FORCE_CTL 0xFE56 -#define ASPM_FORCE_CTL 0xFE57 -#define PM_CLK_FORCE_CTL 0xFE58 -#define PERST_GLITCH_WIDTH 0xFE5C -#define CHANGE_LINK_STATE 0xFE5B -#define RESET_LOAD_REG 0xFE5E -#define HOST_SLEEP_STATE 0xFE60 -#define MAIN_PWR_OFF_CTL 0xFE70 /* RTS5208 */ - -#define NFTS_TX_CTRL 0xFE72 - -#define PWR_GATE_CTRL 0xFE75 -#define PWD_SUSPEND_EN 0xFE76 - -#define EFUSE_CONTENT 0xFE5F - -#define XD_INIT 0xFD10 -#define XD_DTCTL 0xFD11 -#define XD_CTL 0xFD12 -#define XD_TRANSFER 0xFD13 -#define XD_CFG 0xFD14 -#define XD_ADDRESS0 0xFD15 -#define XD_ADDRESS1 0xFD16 -#define XD_ADDRESS2 0xFD17 -#define XD_ADDRESS3 0xFD18 -#define XD_ADDRESS4 0xFD19 -#define XD_DAT 0xFD1A -#define XD_PAGE_CNT 0xFD1B -#define XD_PAGE_STATUS 0xFD1C -#define XD_BLOCK_STATUS 0xFD1D -#define XD_BLOCK_ADDR1_L 0xFD1E -#define XD_BLOCK_ADDR1_H 0xFD1F -#define XD_BLOCK_ADDR2_L 0xFD20 -#define XD_BLOCK_ADDR2_H 0xFD21 -#define XD_BYTE_CNT_L 0xFD22 -#define XD_BYTE_CNT_H 0xFD23 -#define XD_PARITY 0xFD24 -#define XD_ECC_BIT1 0xFD25 -#define XD_ECC_BYTE1 0xFD26 -#define XD_ECC_BIT2 0xFD27 -#define XD_ECC_BYTE2 0xFD28 -#define XD_RESERVED0 0xFD29 -#define XD_RESERVED1 0xFD2A -#define XD_RESERVED2 0xFD2B -#define XD_RESERVED3 0xFD2C -#define XD_CHK_DATA_STATUS 0xFD2D -#define XD_CATCTL 0xFD2E - -#define MS_CFG 0xFD40 -#define MS_TPC 0xFD41 -#define MS_TRANS_CFG 0xFD42 -#define MS_TRANSFER 0xFD43 -#define MS_INT_REG 0xFD44 -#define MS_BYTE_CNT 0xFD45 -#define MS_SECTOR_CNT_L 0xFD46 -#define MS_SECTOR_CNT_H 0xFD47 -#define MS_DBUS_H 0xFD48 - -#define SSC_CTL1 0xFC11 -#define SSC_CTL2 0xFC12 - -#define OCPCTL 0xFC15 -#define OCPSTAT 0xFC16 -#define OCPCLR 0xFC17 /* 5208 */ -#define OCPPARA1 0xFC18 -#define OCPPARA2 0xFC19 - -#define EFUSE_OP 0xFC20 -#define EFUSE_CTRL 0xFC21 -#define EFUSE_DATA 0xFC22 - -#define SPI_COMMAND 0xFD80 -#define SPI_ADDR0 0xFD81 -#define SPI_ADDR1 0xFD82 -#define SPI_ADDR2 0xFD83 -#define SPI_ADDR3 0xFD84 -#define SPI_CA_NUMBER 0xFD85 -#define SPI_LENGTH0 0xFD86 -#define SPI_LENGTH1 0xFD87 -#define SPI_DATA 0xFD88 -#define SPI_DATA_NUMBER 0xFD89 -#define SPI_TRANSFER0 0xFD90 -#define SPI_TRANSFER1 0xFD91 -#define SPI_CONTROL 0xFD92 -#define SPI_SIG 0xFD93 -#define SPI_TCTL 0xFD94 -#define SPI_SLAVE_NUM 0xFD95 -#define SPI_CLK_DIVIDER0 0xFD96 -#define SPI_CLK_DIVIDER1 0xFD97 - -#define SRAM_BASE 0xE600 -#define RBUF_BASE 0xF400 -#define PPBUF_BASE1 0xF800 -#define PPBUF_BASE2 0xFA00 -#define IMAGE_FLAG_ADDR0 0xCE80 -#define IMAGE_FLAG_ADDR1 0xCE81 - -#define READ_OP 1 -#define WRITE_OP 2 - -#define LCTLR 0x80 - -#define POLLING_WAIT_CNT 1 -#define IDLE_MAX_COUNT 10 -#define SDIO_IDLE_COUNT 10 - -#define DEBOUNCE_CNT 5 - -void do_remaining_work(struct rtsx_chip *chip); -void try_to_switch_sdio_ctrl(struct rtsx_chip *chip); -void do_reset_sd_card(struct rtsx_chip *chip); -void do_reset_xd_card(struct rtsx_chip *chip); -void do_reset_ms_card(struct rtsx_chip *chip); -void rtsx_power_off_card(struct rtsx_chip *chip); -void rtsx_release_cards(struct rtsx_chip *chip); -void rtsx_reset_cards(struct rtsx_chip *chip); -void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip); -void rtsx_init_cards(struct rtsx_chip *chip); -int switch_ssc_clock(struct rtsx_chip *chip, int clk); -int switch_normal_clock(struct rtsx_chip *chip, int clk); -int enable_card_clock(struct rtsx_chip *chip, u8 card); -int disable_card_clock(struct rtsx_chip *chip, u8 card); -int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 sec_addr, u16 sec_cnt); -void trans_dma_enable(enum dma_data_direction dir, - struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size); -void toggle_gpio(struct rtsx_chip *chip, u8 gpio); -void turn_on_led(struct rtsx_chip *chip, u8 gpio); -void turn_off_led(struct rtsx_chip *chip, u8 gpio); - -int card_share_mode(struct rtsx_chip *chip, int card); -int select_card(struct rtsx_chip *chip, int card); -int detect_card_cd(struct rtsx_chip *chip, int card); -int check_card_exist(struct rtsx_chip *chip, unsigned int lun); -int check_card_ready(struct rtsx_chip *chip, unsigned int lun); -int check_card_wp(struct rtsx_chip *chip, unsigned int lun); -void eject_card(struct rtsx_chip *chip, unsigned int lun); -u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun); - -static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &chip->sd_card; - - if ((get_lun_card(chip, lun) == SD_CARD) && - (sd_card->sd_lock_status & SD_LOCKED)) - return 0; - - return chip->capacity[lun]; -#else - return chip->capacity[lun]; -#endif -} - -static inline int switch_clock(struct rtsx_chip *chip, int clk) -{ - int retval = 0; - - if (chip->asic_code) - retval = switch_ssc_clock(chip, clk); - else - retval = switch_normal_clock(chip, clk); - - return retval; -} - -int card_power_on(struct rtsx_chip *chip, u8 card); -int card_power_off(struct rtsx_chip *chip, u8 card); - -static inline int card_power_off_all(struct rtsx_chip *chip) -{ - int retval; - - retval = rtsx_write_register(chip, CARD_PWR_CTL, 0x0F, 0x0F); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static inline void rtsx_clear_xd_error(struct rtsx_chip *chip) -{ - rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, - XD_STOP | XD_CLR_ERR); -} - -static inline void rtsx_clear_sd_error(struct rtsx_chip *chip) -{ - rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); -} - -static inline void rtsx_clear_ms_error(struct rtsx_chip *chip) -{ - rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, - MS_STOP | MS_CLR_ERR); -} - -static inline void rtsx_clear_spi_error(struct rtsx_chip *chip) -{ - rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR, - SPI_STOP | SPI_CLR_ERR); -} - -#ifdef SUPPORT_SDIO_ASPM -void dynamic_configure_sdio_aspm(struct rtsx_chip *chip); -#endif - -#endif /* __REALTEK_RTSX_CARD_H */ diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c deleted file mode 100644 index 6375032918d4cf599d1c45e1d4c563c7b757abaa..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_chip.c +++ /dev/null @@ -1,2161 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/workqueue.h> -#include <linux/vmalloc.h> - -#include "rtsx.h" -#include "sd.h" -#include "xd.h" -#include "ms.h" - -static void rtsx_calibration(struct rtsx_chip *chip) -{ - rtsx_write_phy_register(chip, 0x1B, 0x135E); - wait_timeout(10); - rtsx_write_phy_register(chip, 0x00, 0x0280); - rtsx_write_phy_register(chip, 0x01, 0x7112); - rtsx_write_phy_register(chip, 0x01, 0x7110); - rtsx_write_phy_register(chip, 0x01, 0x7112); - rtsx_write_phy_register(chip, 0x01, 0x7113); - rtsx_write_phy_register(chip, 0x00, 0x0288); -} - -void rtsx_enable_card_int(struct rtsx_chip *chip) -{ - u32 reg = rtsx_readl(chip, RTSX_BIER); - int i; - - for (i = 0; i <= chip->max_lun; i++) { - if (chip->lun2card[i] & XD_CARD) - reg |= XD_INT_EN; - if (chip->lun2card[i] & SD_CARD) - reg |= SD_INT_EN; - if (chip->lun2card[i] & MS_CARD) - reg |= MS_INT_EN; - } - if (chip->hw_bypass_sd) - reg &= ~((u32)SD_INT_EN); - - rtsx_writel(chip, RTSX_BIER, reg); -} - -void rtsx_enable_bus_int(struct rtsx_chip *chip) -{ - u32 reg = 0; -#ifndef DISABLE_CARD_INT - int i; -#endif - - reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN; - -#ifndef DISABLE_CARD_INT - for (i = 0; i <= chip->max_lun; i++) { - dev_dbg(rtsx_dev(chip), "lun2card[%d] = 0x%02x\n", - i, chip->lun2card[i]); - - if (chip->lun2card[i] & XD_CARD) - reg |= XD_INT_EN; - if (chip->lun2card[i] & SD_CARD) - reg |= SD_INT_EN; - if (chip->lun2card[i] & MS_CARD) - reg |= MS_INT_EN; - } - if (chip->hw_bypass_sd) - reg &= ~((u32)SD_INT_EN); -#endif - - if (chip->ic_version >= IC_VER_C) - reg |= DELINK_INT_EN; -#ifdef SUPPORT_OCP - reg |= OC_INT_EN; -#endif - if (!chip->adma_mode) - reg |= DATA_DONE_INT_EN; - - /* Enable Bus Interrupt */ - rtsx_writel(chip, RTSX_BIER, reg); - - dev_dbg(rtsx_dev(chip), "RTSX_BIER: 0x%08x\n", reg); -} - -void rtsx_disable_bus_int(struct rtsx_chip *chip) -{ - rtsx_writel(chip, RTSX_BIER, 0); -} - -static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip) -{ - int retval; - - if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) { - if (chip->asic_code) { - retval = rtsx_write_register(chip, CARD_PULL_CTL5, - 0xFF, - MS_INS_PU | SD_WP_PU | - SD_CD_PU | SD_CMD_PU); - if (retval) - return retval; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - 0xFF, - FPGA_SD_PULL_CTL_EN); - if (retval) - return retval; - } - retval = rtsx_write_register(chip, CARD_SHARE_MODE, 0xFF, - CARD_SHARE_48_SD); - if (retval) - return retval; - - /* Enable SDIO internal clock */ - retval = rtsx_write_register(chip, 0xFF2C, 0x01, 0x01); - if (retval) - return retval; - - retval = rtsx_write_register(chip, SDIO_CTRL, 0xFF, - SDIO_BUS_CTRL | SDIO_CD_CTRL); - if (retval) - return retval; - - chip->sd_int = 1; - chip->sd_io = 1; - } else { - chip->need_reset |= SD_CARD; - } - - return STATUS_SUCCESS; -} - -#ifdef HW_AUTO_SWITCH_SD_BUS -static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip) -{ - u8 tmp; - bool sw_bypass_sd = false; - int retval; - - if (chip->driver_first_load) { - if (CHECK_PID(chip, 0x5288)) { - retval = rtsx_read_register(chip, 0xFE5A, &tmp); - if (retval) - return retval; - if (tmp & 0x08) - sw_bypass_sd = true; - } else if (CHECK_PID(chip, 0x5208)) { - retval = rtsx_read_register(chip, 0xFE70, &tmp); - if (retval) - return retval; - if (tmp & 0x80) - sw_bypass_sd = true; - } - } else { - if (chip->sdio_in_charge) - sw_bypass_sd = true; - } - dev_dbg(rtsx_dev(chip), "chip->sdio_in_charge = %d\n", - chip->sdio_in_charge); - dev_dbg(rtsx_dev(chip), "chip->driver_first_load = %d\n", - chip->driver_first_load); - dev_dbg(rtsx_dev(chip), "sw_bypass_sd = %d\n", - sw_bypass_sd); - - if (sw_bypass_sd) { - u8 cd_toggle_mask = 0; - - retval = rtsx_read_register(chip, TLPTISTAT, &tmp); - if (retval) - return retval; - cd_toggle_mask = 0x08; - - if (tmp & cd_toggle_mask) { - /* Disable sdio_bus_auto_switch */ - if (CHECK_PID(chip, 0x5288)) { - retval = rtsx_write_register(chip, 0xFE5A, - 0x08, 0x00); - if (retval) - return retval; - } else if (CHECK_PID(chip, 0x5208)) { - retval = rtsx_write_register(chip, 0xFE70, - 0x80, 0x00); - if (retval) - return retval; - } - - retval = rtsx_write_register(chip, TLPTISTAT, 0xFF, - tmp); - if (retval) - return retval; - - chip->need_reset |= SD_CARD; - } else { - dev_dbg(rtsx_dev(chip), "Chip inserted with SDIO!\n"); - - if (chip->asic_code) { - retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register - (chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, - 0); - if (retval) - return retval; - } - retval = card_share_mode(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - /* Enable sdio_bus_auto_switch */ - if (CHECK_PID(chip, 0x5288)) { - retval = rtsx_write_register(chip, 0xFE5A, - 0x08, 0x08); - if (retval) - return retval; - } else if (CHECK_PID(chip, 0x5208)) { - retval = rtsx_write_register(chip, 0xFE70, - 0x80, 0x80); - if (retval) - return retval; - } - - chip->chip_insert_with_sdio = 1; - chip->sd_io = 1; - } - } else { - retval = rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08); - if (retval) - return retval; - - chip->need_reset |= SD_CARD; - } - - return STATUS_SUCCESS; -} -#endif - -static int rtsx_reset_aspm(struct rtsx_chip *chip) -{ - int ret; - - if (chip->dynamic_aspm) { - if (!CHK_SDIO_EXIST(chip) || !CHECK_PID(chip, 0x5288)) - return STATUS_SUCCESS; - - ret = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, - chip->aspm_l0s_l1_en); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; - } - - if (CHECK_PID(chip, 0x5208)) { - ret = rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, 0x3F); - if (ret) - return ret; - } - ret = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - - chip->aspm_level[0] = chip->aspm_l0s_l1_en; - if (CHK_SDIO_EXIST(chip)) { - chip->aspm_level[1] = chip->aspm_l0s_l1_en; - ret = rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1, - 0xC0, 0xFF, chip->aspm_l0s_l1_en); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - } - - chip->aspm_enabled = 1; - - return STATUS_SUCCESS; -} - -static int rtsx_enable_pcie_intr(struct rtsx_chip *chip) -{ - int ret; - - if (!chip->asic_code || !CHECK_PID(chip, 0x5208)) { - rtsx_enable_bus_int(chip); - return STATUS_SUCCESS; - } - - if (chip->phy_debug_mode) { - ret = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0); - if (ret) - return ret; - rtsx_disable_bus_int(chip); - } else { - rtsx_enable_bus_int(chip); - } - - if (chip->ic_version >= IC_VER_D) { - u16 reg; - - ret = rtsx_read_phy_register(chip, 0x00, ®); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - - reg &= 0xFE7F; - reg |= 0x80; - ret = rtsx_write_phy_register(chip, 0x00, reg); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - - ret = rtsx_read_phy_register(chip, 0x1C, ®); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - - reg &= 0xFFF7; - ret = rtsx_write_phy_register(chip, 0x1C, reg); - if (ret != STATUS_SUCCESS) - return STATUS_FAIL; - } - - if (chip->driver_first_load && chip->ic_version < IC_VER_C) - rtsx_calibration(chip); - - return STATUS_SUCCESS; -} - -int rtsx_reset_chip(struct rtsx_chip *chip) -{ - int retval; - - rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr); - - rtsx_disable_aspm(chip); - - retval = rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00); - if (retval) - return retval; - - /* Disable card clock */ - retval = rtsx_write_register(chip, CARD_CLK_EN, 0x1E, 0); - if (retval) - return retval; - -#ifdef SUPPORT_OCP - /* SSC power on, OCD power on */ - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, 0); - if (retval) - return retval; - } else { - retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, - MS_OC_POWER_DOWN); - if (retval) - return retval; - } - - retval = rtsx_write_register(chip, OCPPARA1, OCP_TIME_MASK, - OCP_TIME_800); - if (retval) - return retval; - retval = rtsx_write_register(chip, OCPPARA2, OCP_THD_MASK, - OCP_THD_244_946); - if (retval) - return retval; - retval = rtsx_write_register(chip, OCPCTL, 0xFF, - CARD_OC_INT_EN | CARD_DETECT_EN); - if (retval) - return retval; -#else - /* OC power down */ - retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, - OC_POWER_DOWN); - if (retval) - return retval; -#endif - - if (!CHECK_PID(chip, 0x5288)) { - retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0xFF, 0x03); - if (retval) - return retval; - } - - /* Turn off LED */ - retval = rtsx_write_register(chip, CARD_GPIO, 0xFF, 0x03); - if (retval) - return retval; - - /* Reset delink mode */ - retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0); - if (retval) - return retval; - - /* Card driving select */ - retval = rtsx_write_register(chip, CARD_DRIVE_SEL, 0xFF, - chip->card_drive_sel); - if (retval) - return retval; - -#ifdef LED_AUTO_BLINK - retval = rtsx_write_register(chip, CARD_AUTO_BLINK, 0xFF, - LED_BLINK_SPEED | BLINK_EN | LED_GPIO0); - if (retval) - return retval; -#endif - - if (chip->asic_code) { - /* Enable SSC Clock */ - retval = rtsx_write_register(chip, SSC_CTL1, 0xFF, - SSC_8X_EN | SSC_SEL_4M); - if (retval) - return retval; - retval = rtsx_write_register(chip, SSC_CTL2, 0xFF, 0x12); - if (retval) - return retval; - } - - /* - * Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0) - * 0xFE5B - * bit[1] u_cd_rst_core_en rst_value = 0 - * bit[2] u_force_rst_core_en rst_value = 0 - * bit[5] u_mac_phy_rst_n_dbg rst_value = 1 - * bit[4] u_non_sticky_rst_n_dbg rst_value = 0 - */ - retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x16, 0x10); - if (retval) - return retval; - - /* Enable ASPM */ - if (chip->aspm_l0s_l1_en) { - retval = rtsx_reset_aspm(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - if (chip->asic_code && CHECK_PID(chip, 0x5208)) { - retval = rtsx_write_phy_register(chip, 0x07, 0x0129); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - retval = rtsx_write_config_byte(chip, LCTLR, - chip->aspm_l0s_l1_en); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = rtsx_write_config_byte(chip, 0x81, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_SDIO_EXIST(chip)) { - retval = rtsx_write_cfg_dw(chip, - CHECK_PID(chip, 0x5288) ? 2 : 1, - 0xC0, 0xFF00, 0x0100); - - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - if (CHECK_PID(chip, 0x5288) && !CHK_SDIO_EXIST(chip)) { - retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, - LINK_RDY_INT); - if (retval) - return retval; - - retval = rtsx_write_register(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80); - if (retval) - return retval; - - retval = rtsx_enable_pcie_intr(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - chip->need_reset = 0; - - chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - - if (chip->hw_bypass_sd) - goto nextcard; - dev_dbg(rtsx_dev(chip), "In %s, chip->int_reg = 0x%x\n", __func__, - chip->int_reg); - if (chip->int_reg & SD_EXIST) { -#ifdef HW_AUTO_SWITCH_SD_BUS - if (CHECK_PID(chip, 0x5208) && chip->ic_version < IC_VER_C) - retval = rtsx_pre_handle_sdio_old(chip); - else - retval = rtsx_pre_handle_sdio_new(chip); - - dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x (%s)\n", - (unsigned int)(chip->need_reset), __func__); -#else /* HW_AUTO_SWITCH_SD_BUS */ - retval = rtsx_pre_handle_sdio_old(chip); -#endif /* HW_AUTO_SWITCH_SD_BUS */ - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - } else { - chip->sd_io = 0; - retval = rtsx_write_register(chip, SDIO_CTRL, - SDIO_BUS_CTRL | SDIO_CD_CTRL, 0); - if (retval) - return retval; - } - -nextcard: - if (chip->int_reg & XD_EXIST) - chip->need_reset |= XD_CARD; - if (chip->int_reg & MS_EXIST) - chip->need_reset |= MS_CARD; - if (chip->int_reg & CARD_EXIST) { - retval = rtsx_write_register(chip, SSC_CTL1, SSC_RSTB, - SSC_RSTB); - if (retval) - return retval; - } - - dev_dbg(rtsx_dev(chip), "In %s, chip->need_reset = 0x%x\n", __func__, - (unsigned int)(chip->need_reset)); - - retval = rtsx_write_register(chip, RCCTL, 0x01, 0x00); - if (retval) - return retval; - - if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) { - /* Turn off main power when entering S3/S4 state */ - retval = rtsx_write_register(chip, MAIN_PWR_OFF_CTL, 0x03, - 0x03); - if (retval) - return retval; - } - - if (chip->remote_wakeup_en && !chip->auto_delink_en) { - retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x07); - if (retval) - return retval; - if (chip->aux_pwr_exist) { - retval = rtsx_write_register(chip, PME_FORCE_CTL, - 0xFF, 0x33); - if (retval) - return retval; - } - } else { - retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x04); - if (retval) - return retval; - retval = rtsx_write_register(chip, PME_FORCE_CTL, 0xFF, 0x30); - if (retval) - return retval; - } - - if (CHECK_PID(chip, 0x5208) && chip->ic_version >= IC_VER_D) { - retval = rtsx_write_register(chip, PETXCFG, 0x1C, 0x14); - if (retval) - return retval; - } - - if (chip->asic_code && CHECK_PID(chip, 0x5208)) { - retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - if (chip->ft2_fast_mode) { - retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF, - MS_PARTIAL_POWER_ON | - SD_PARTIAL_POWER_ON); - if (retval) - return retval; - udelay(chip->pmos_pwr_on_interval); - retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF, - MS_POWER_ON | SD_POWER_ON); - if (retval) - return retval; - - wait_timeout(200); - } - - /* Reset card */ - rtsx_reset_detected_cards(chip, 0); - - chip->driver_first_load = 0; - - return STATUS_SUCCESS; -} - -static inline int valid_sd_speed_prior(u32 sd_speed_prior) -{ - bool valid_para = true; - int i; - - for (i = 0; i < 4; i++) { - u8 tmp = (u8)(sd_speed_prior >> (i * 8)); - - if (tmp < 0x01 || tmp > 0x04) { - valid_para = false; - break; - } - } - - return valid_para; -} - -static inline int valid_sd_current_prior(u32 sd_current_prior) -{ - bool valid_para = true; - int i; - - for (i = 0; i < 4; i++) { - u8 tmp = (u8)(sd_current_prior >> (i * 8)); - - if (tmp > 0x03) { - valid_para = false; - break; - } - } - - return valid_para; -} - -static int rts5208_init(struct rtsx_chip *chip) -{ - int retval; - u16 reg = 0; - u8 val = 0; - - retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03); - if (retval) - return retval; - retval = rtsx_read_register(chip, CLK_SEL, &val); - if (retval) - return retval; - chip->asic_code = val == 0 ? 1 : 0; - - if (chip->asic_code) { - retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "Value of phy register 0x1C is 0x%x\n", - reg); - chip->ic_version = (reg >> 4) & 0x07; - chip->phy_debug_mode = reg & PHY_DEBUG_MODE ? 1 : 0; - - } else { - retval = rtsx_read_register(chip, 0xFE80, &val); - if (retval) - return retval; - chip->ic_version = val; - chip->phy_debug_mode = 0; - } - - retval = rtsx_read_register(chip, PDINFO, &val); - if (retval) - return retval; - dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val); - chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0; - - retval = rtsx_read_register(chip, 0xFE50, &val); - if (retval) - return retval; - chip->hw_bypass_sd = val & 0x01 ? 1 : 0; - - rtsx_read_config_byte(chip, 0x0E, &val); - if (val & 0x80) - SET_SDIO_EXIST(chip); - else - CLR_SDIO_EXIST(chip); - - if (chip->use_hw_setting) { - retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val); - if (retval) - return retval; - chip->auto_delink_en = val & 0x80 ? 1 : 0; - } - - return STATUS_SUCCESS; -} - -static int rts5288_init(struct rtsx_chip *chip) -{ - int retval; - u8 val = 0, max_func; - u32 lval = 0; - - retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03); - if (retval) - return retval; - retval = rtsx_read_register(chip, CLK_SEL, &val); - if (retval) - return retval; - chip->asic_code = val == 0 ? 1 : 0; - - chip->ic_version = 0; - chip->phy_debug_mode = 0; - - retval = rtsx_read_register(chip, PDINFO, &val); - if (retval) - return retval; - dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val); - chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0; - - retval = rtsx_read_register(chip, CARD_SHARE_MODE, &val); - if (retval) - return retval; - dev_dbg(rtsx_dev(chip), "CARD_SHARE_MODE: 0x%x\n", val); - chip->baro_pkg = val & 0x04 ? QFN : LQFP; - - retval = rtsx_read_register(chip, 0xFE5A, &val); - if (retval) - return retval; - chip->hw_bypass_sd = val & 0x10 ? 1 : 0; - - retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - max_func = (u8)((lval >> 29) & 0x07); - dev_dbg(rtsx_dev(chip), "Max function number: %d\n", max_func); - if (max_func == 0x02) - SET_SDIO_EXIST(chip); - else - CLR_SDIO_EXIST(chip); - - if (chip->use_hw_setting) { - retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val); - if (retval) - return retval; - chip->auto_delink_en = val & 0x80 ? 1 : 0; - - if (CHECK_BARO_PKG(chip, LQFP)) - chip->lun_mode = SD_MS_1LUN; - else - chip->lun_mode = DEFAULT_SINGLE; - } - - return STATUS_SUCCESS; -} - -int rtsx_init_chip(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - struct xd_info *xd_card = &chip->xd_card; - struct ms_info *ms_card = &chip->ms_card; - int retval; - unsigned int i; - - dev_dbg(rtsx_dev(chip), "Vendor ID: 0x%04x, Product ID: 0x%04x\n", - chip->vendor_id, chip->product_id); - - chip->ic_version = 0; - - memset(xd_card, 0, sizeof(struct xd_info)); - memset(sd_card, 0, sizeof(struct sd_info)); - memset(ms_card, 0, sizeof(struct ms_info)); - - chip->xd_reset_counter = 0; - chip->sd_reset_counter = 0; - chip->ms_reset_counter = 0; - - chip->xd_show_cnt = MAX_SHOW_CNT; - chip->sd_show_cnt = MAX_SHOW_CNT; - chip->ms_show_cnt = MAX_SHOW_CNT; - - chip->sd_io = 0; - chip->auto_delink_cnt = 0; - chip->auto_delink_allowed = 1; - rtsx_set_stat(chip, RTSX_STAT_INIT); - - chip->aspm_enabled = 0; - chip->chip_insert_with_sdio = 0; - chip->sdio_aspm = 0; - chip->sdio_idle = 0; - chip->sdio_counter = 0; - chip->cur_card = 0; - chip->phy_debug_mode = 0; - chip->sdio_func_exist = 0; - memset(chip->sdio_raw_data, 0, 12); - - for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) { - set_sense_type(chip, i, SENSE_TYPE_NO_SENSE); - chip->rw_fail_cnt[i] = 0; - } - - if (!valid_sd_speed_prior(chip->sd_speed_prior)) - chip->sd_speed_prior = 0x01040203; - - dev_dbg(rtsx_dev(chip), "sd_speed_prior = 0x%08x\n", - chip->sd_speed_prior); - - if (!valid_sd_current_prior(chip->sd_current_prior)) - chip->sd_current_prior = 0x00010203; - - dev_dbg(rtsx_dev(chip), "sd_current_prior = 0x%08x\n", - chip->sd_current_prior); - - if (chip->sd_ddr_tx_phase > 31 || chip->sd_ddr_tx_phase < 0) - chip->sd_ddr_tx_phase = 0; - - if (chip->mmc_ddr_tx_phase > 31 || chip->mmc_ddr_tx_phase < 0) - chip->mmc_ddr_tx_phase = 0; - - retval = rtsx_write_register(chip, FPDCTL, SSC_POWER_DOWN, 0); - if (retval) - return retval; - wait_timeout(200); - retval = rtsx_write_register(chip, CLK_DIV, 0x07, 0x07); - if (retval) - return retval; - dev_dbg(rtsx_dev(chip), "chip->use_hw_setting = %d\n", - chip->use_hw_setting); - - if (CHECK_PID(chip, 0x5208)) { - retval = rts5208_init(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - } else if (CHECK_PID(chip, 0x5288)) { - retval = rts5288_init(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - if (chip->ss_en == 2) - chip->ss_en = 0; - - dev_dbg(rtsx_dev(chip), "chip->asic_code = %d\n", chip->asic_code); - dev_dbg(rtsx_dev(chip), "chip->ic_version = 0x%x\n", chip->ic_version); - dev_dbg(rtsx_dev(chip), "chip->phy_debug_mode = %d\n", - chip->phy_debug_mode); - dev_dbg(rtsx_dev(chip), "chip->aux_pwr_exist = %d\n", - chip->aux_pwr_exist); - dev_dbg(rtsx_dev(chip), "chip->sdio_func_exist = %d\n", - chip->sdio_func_exist); - dev_dbg(rtsx_dev(chip), "chip->hw_bypass_sd = %d\n", - chip->hw_bypass_sd); - dev_dbg(rtsx_dev(chip), "chip->aspm_l0s_l1_en = %d\n", - chip->aspm_l0s_l1_en); - dev_dbg(rtsx_dev(chip), "chip->lun_mode = %d\n", chip->lun_mode); - dev_dbg(rtsx_dev(chip), "chip->auto_delink_en = %d\n", - chip->auto_delink_en); - dev_dbg(rtsx_dev(chip), "chip->ss_en = %d\n", chip->ss_en); - dev_dbg(rtsx_dev(chip), "chip->baro_pkg = %d\n", chip->baro_pkg); - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - chip->card2lun[SD_CARD] = 0; - chip->card2lun[MS_CARD] = 1; - chip->card2lun[XD_CARD] = 0xFF; - chip->lun2card[0] = SD_CARD; - chip->lun2card[1] = MS_CARD; - chip->max_lun = 1; - SET_SDIO_IGNORED(chip); - } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) { - chip->card2lun[SD_CARD] = 0; - chip->card2lun[MS_CARD] = 0; - chip->card2lun[XD_CARD] = 0xFF; - chip->lun2card[0] = SD_CARD | MS_CARD; - chip->max_lun = 0; - } else { - chip->card2lun[XD_CARD] = 0; - chip->card2lun[SD_CARD] = 0; - chip->card2lun[MS_CARD] = 0; - chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD; - chip->max_lun = 0; - } - - retval = rtsx_reset_chip(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -void rtsx_release_chip(struct rtsx_chip *chip) -{ - xd_free_l2p_tbl(chip); - ms_free_l2p_tbl(chip); - chip->card_exist = 0; - chip->card_ready = 0; -} - -#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK) -static inline void rtsx_blink_led(struct rtsx_chip *chip) -{ - if (chip->card_exist && chip->blink_led) { - if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) { - chip->led_toggle_counter++; - } else { - chip->led_toggle_counter = 0; - toggle_gpio(chip, LED_GPIO); - } - } -} -#endif - -static void rtsx_monitor_aspm_config(struct rtsx_chip *chip) -{ - bool reg_changed, maybe_support_aspm; - u32 tmp = 0; - u8 reg0 = 0, reg1 = 0; - - maybe_support_aspm = false; - reg_changed = false; - rtsx_read_config_byte(chip, LCTLR, ®0); - if (chip->aspm_level[0] != reg0) { - reg_changed = true; - chip->aspm_level[0] = reg0; - } - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { - rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp); - reg1 = (u8)tmp; - if (chip->aspm_level[1] != reg1) { - reg_changed = true; - chip->aspm_level[1] = reg1; - } - - if ((reg0 & 0x03) && (reg1 & 0x03)) - maybe_support_aspm = true; - - } else { - if (reg0 & 0x03) - maybe_support_aspm = true; - } - - if (reg_changed) { - if (maybe_support_aspm) - chip->aspm_l0s_l1_en = 0x03; - - dev_dbg(rtsx_dev(chip), - "aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n", - chip->aspm_level[0], chip->aspm_level[1]); - - if (chip->aspm_l0s_l1_en) { - chip->aspm_enabled = 1; - } else { - chip->aspm_enabled = 0; - chip->sdio_aspm = 0; - } - rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, - 0x30 | chip->aspm_level[0] | - (chip->aspm_level[1] << 2)); - } -} - -static void rtsx_manage_ocp(struct rtsx_chip *chip) -{ -#ifdef SUPPORT_OCP - if (!chip->ocp_int) - return; - - rtsx_read_register(chip, OCPSTAT, &chip->ocp_stat); - - if (chip->card_exist & SD_CARD) - sd_power_off_card3v3(chip); - else if (chip->card_exist & MS_CARD) - ms_power_off_card3v3(chip); - else if (chip->card_exist & XD_CARD) - xd_power_off_card3v3(chip); - - chip->ocp_int = 0; -#endif -} - -static void rtsx_manage_sd_lock(struct rtsx_chip *chip) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &chip->sd_card; - u8 val; - - if (!sd_card->sd_erase_status) - return; - - if (chip->card_exist & SD_CARD) { - rtsx_read_register(chip, 0xFD30, &val); - if (val & 0x02) { - sd_card->sd_erase_status = SD_NOT_ERASE; - sd_card->sd_lock_notify = 1; - chip->need_reinit |= SD_CARD; - } - } else { - sd_card->sd_erase_status = SD_NOT_ERASE; - } -#endif -} - -static bool rtsx_is_ss_allowed(struct rtsx_chip *chip) -{ - u32 val; - - if (!chip->ss_en || CHECK_PID(chip, 0x5288)) - return false; - - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) { - rtsx_read_cfg_dw(chip, 1, 0x04, &val); - if (val & 0x07) - return false; - } - - return true; -} - -static void rtsx_manage_ss(struct rtsx_chip *chip) -{ - if (!rtsx_is_ss_allowed(chip) || chip->sd_io) - return; - - if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) { - chip->ss_counter = 0; - return; - } - - if (chip->ss_counter < (chip->ss_idle_period / POLLING_INTERVAL)) - chip->ss_counter++; - else - rtsx_exclusive_enter_ss(chip); -} - -static void rtsx_manage_aspm(struct rtsx_chip *chip) -{ - u8 data; - - if (!CHECK_PID(chip, 0x5208)) - return; - - rtsx_monitor_aspm_config(chip); - -#ifdef SUPPORT_SDIO_ASPM - if (!CHK_SDIO_EXIST(chip) || CHK_SDIO_IGNORED(chip) || - !chip->aspm_l0s_l1_en || !chip->dynamic_aspm) - return; - - if (chip->sd_io) { - dynamic_configure_sdio_aspm(chip); - return; - } - - if (chip->sdio_aspm) - return; - - dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n"); - data = 0x30 | (chip->aspm_level[1] << 2); - rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, data); - chip->sdio_aspm = 1; -#endif -} - -static void rtsx_manage_idle(struct rtsx_chip *chip) -{ - if (chip->idle_counter < IDLE_MAX_COUNT) { - chip->idle_counter++; - return; - } - - if (rtsx_get_stat(chip) == RTSX_STAT_IDLE) - return; - - dev_dbg(rtsx_dev(chip), "Idle state!\n"); - rtsx_set_stat(chip, RTSX_STAT_IDLE); - -#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK) - chip->led_toggle_counter = 0; -#endif - rtsx_force_power_on(chip, SSC_PDCTL); - - turn_off_led(chip, LED_GPIO); - - if (chip->auto_power_down && !chip->card_ready && !chip->sd_io) - rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); -} - -static void rtsx_manage_2lun_mode(struct rtsx_chip *chip) -{ -#ifdef SUPPORT_OCP - u8 sd_oc, ms_oc; - - sd_oc = chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER); - ms_oc = chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER); - - if (sd_oc || ms_oc) - dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - - if (sd_oc && (chip->card_exist & SD_CARD)) { - rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); - card_power_off(chip, SD_CARD); - chip->card_fail |= SD_CARD; - } - - if (ms_oc && (chip->card_exist & MS_CARD)) { - rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); - card_power_off(chip, MS_CARD); - chip->card_fail |= MS_CARD; - } -#endif -} - -static void rtsx_manage_1lun_mode(struct rtsx_chip *chip) -{ -#ifdef SUPPORT_OCP - if (!(chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER))) - return; - - dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - - if (chip->card_exist & SD_CARD) { - rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); - chip->card_fail |= SD_CARD; - } else if (chip->card_exist & MS_CARD) { - rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0); - chip->card_fail |= MS_CARD; - } else if (chip->card_exist & XD_CARD) { - rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0); - chip->card_fail |= XD_CARD; - } - card_power_off(chip, SD_CARD); -#endif -} - -static void rtsx_delink_stage1(struct rtsx_chip *chip, int enter_L1, - int stage3_cnt) -{ - u8 val; - - rtsx_set_stat(chip, RTSX_STAT_DELINK); - - if (chip->asic_code && CHECK_PID(chip, 0x5208)) - rtsx_set_phy_reg_bit(chip, 0x1C, 2); - - if (chip->card_exist) - dev_dbg(rtsx_dev(chip), "False card inserted, do force delink\n"); - else - dev_dbg(rtsx_dev(chip), "No card inserted, do delink\n"); - - if (enter_L1) - rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1); - - if (chip->card_exist) - val = 0x02; - else - val = 0x0A; - - rtsx_write_register(chip, CHANGE_LINK_STATE, val, val); - - if (enter_L1) - rtsx_enter_L1(chip); - - if (chip->card_exist) - chip->auto_delink_cnt = stage3_cnt + 1; -} - -static void rtsx_delink_stage(struct rtsx_chip *chip) -{ - int delink_stage1_cnt, delink_stage2_cnt, delink_stage3_cnt; - int enter_L1; - - if (!chip->auto_delink_en || !chip->auto_delink_allowed || - chip->card_ready || chip->card_ejected || chip->sd_io) { - chip->auto_delink_cnt = 0; - return; - } - - enter_L1 = chip->auto_delink_in_L1 && - (chip->aspm_l0s_l1_en || chip->ss_en); - - delink_stage1_cnt = chip->delink_stage1_step; - delink_stage2_cnt = delink_stage1_cnt + chip->delink_stage2_step; - delink_stage3_cnt = delink_stage2_cnt + chip->delink_stage3_step; - - if (chip->auto_delink_cnt > delink_stage3_cnt) - return; - - if (chip->auto_delink_cnt == delink_stage1_cnt) - rtsx_delink_stage1(chip, enter_L1, delink_stage3_cnt); - - if (chip->auto_delink_cnt == delink_stage2_cnt) { - dev_dbg(rtsx_dev(chip), "Try to do force delink\n"); - - if (enter_L1) - rtsx_exit_L1(chip); - - if (chip->asic_code && CHECK_PID(chip, 0x5208)) - rtsx_set_phy_reg_bit(chip, 0x1C, 2); - - rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A); - } - - chip->auto_delink_cnt++; -} - -void rtsx_polling_func(struct rtsx_chip *chip) -{ - if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND)) - return; - - if (rtsx_chk_stat(chip, RTSX_STAT_DELINK)) - goto delink_stage; - - if (chip->polling_config) { - u8 val; - - rtsx_read_config_byte(chip, 0, &val); - } - - if (rtsx_chk_stat(chip, RTSX_STAT_SS)) - return; - - rtsx_manage_ocp(chip); - - rtsx_manage_sd_lock(chip); - - rtsx_init_cards(chip); - - rtsx_manage_ss(chip); - - rtsx_manage_aspm(chip); - - rtsx_manage_idle(chip); - - switch (rtsx_get_stat(chip)) { - case RTSX_STAT_RUN: -#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK) - rtsx_blink_led(chip); -#endif - do_remaining_work(chip); - break; - - case RTSX_STAT_IDLE: - if (chip->sd_io && !chip->sd_int) - try_to_switch_sdio_ctrl(chip); - - rtsx_enable_aspm(chip); - break; - - default: - break; - } - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) - rtsx_manage_2lun_mode(chip); - else - rtsx_manage_1lun_mode(chip); - -delink_stage: - rtsx_delink_stage(chip); -} - -/** - * rtsx_stop_cmd - stop command transfer and DMA transfer - * @chip: Realtek's card reader chip - * @card: flash card type - * - * Stop command transfer and DMA transfer. - * This function is called in error handler. - */ -void rtsx_stop_cmd(struct rtsx_chip *chip, int card) -{ - int i; - - for (i = 0; i <= 8; i++) { - int addr = RTSX_HCBAR + i * 4; - u32 reg; - - reg = rtsx_readl(chip, addr); - dev_dbg(rtsx_dev(chip), "BAR (0x%02x): 0x%08x\n", addr, reg); - } - rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD); - rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA); - - for (i = 0; i < 16; i++) { - u16 addr = 0xFE20 + (u16)i; - u8 val; - - rtsx_read_register(chip, addr, &val); - dev_dbg(rtsx_dev(chip), "0x%04X: 0x%02x\n", addr, val); - } - - rtsx_write_register(chip, DMACTL, 0x80, 0x80); - rtsx_write_register(chip, RBCTL, 0x80, 0x80); -} - -#define MAX_RW_REG_CNT 1024 - -int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data) -{ - int i; - u32 val = 3 << 30; - - val |= (u32)(addr & 0x3FFF) << 16; - val |= (u32)mask << 8; - val |= (u32)data; - - rtsx_writel(chip, RTSX_HAIMR, val); - - for (i = 0; i < MAX_RW_REG_CNT; i++) { - val = rtsx_readl(chip, RTSX_HAIMR); - if ((val & BIT(31)) == 0) { - if (data != (u8)val) - return STATUS_FAIL; - - return STATUS_SUCCESS; - } - } - - return STATUS_TIMEDOUT; -} - -int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data) -{ - u32 val = 2 << 30; - int i; - - if (data) - *data = 0; - - val |= (u32)(addr & 0x3FFF) << 16; - - rtsx_writel(chip, RTSX_HAIMR, val); - - for (i = 0; i < MAX_RW_REG_CNT; i++) { - val = rtsx_readl(chip, RTSX_HAIMR); - if ((val & BIT(31)) == 0) - break; - } - - if (i >= MAX_RW_REG_CNT) - return STATUS_TIMEDOUT; - - if (data) - *data = (u8)(val & 0xFF); - - return STATUS_SUCCESS; -} - -int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, - u32 val) -{ - int retval; - u8 mode = 0, tmp; - int i; - - for (i = 0; i < 4; i++) { - if (mask & 0xFF) { - retval = rtsx_write_register(chip, CFGDATA0 + i, - 0xFF, - (u8)(val & mask & 0xFF)); - if (retval) - return retval; - mode |= (1 << i); - } - mask >>= 8; - val >>= 8; - } - - if (mode) { - retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr); - if (retval) - return retval; - retval = rtsx_write_register(chip, CFGADDR1, 0xFF, - (u8)(addr >> 8)); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CFGRWCTL, 0xFF, - 0x80 | mode | - ((func_no & 0x03) << 4)); - if (retval) - return retval; - - for (i = 0; i < MAX_RW_REG_CNT; i++) { - retval = rtsx_read_register(chip, CFGRWCTL, &tmp); - if (retval) - return retval; - if ((tmp & 0x80) == 0) - break; - } - } - - return STATUS_SUCCESS; -} - -int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val) -{ - int retval; - int i; - u8 tmp; - u32 data = 0; - - retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr); - if (retval) - return retval; - retval = rtsx_write_register(chip, CFGADDR1, 0xFF, (u8)(addr >> 8)); - if (retval) - return retval; - retval = rtsx_write_register(chip, CFGRWCTL, 0xFF, - 0x80 | ((func_no & 0x03) << 4)); - if (retval) - return retval; - - for (i = 0; i < MAX_RW_REG_CNT; i++) { - retval = rtsx_read_register(chip, CFGRWCTL, &tmp); - if (retval) - return retval; - if ((tmp & 0x80) == 0) - break; - } - - for (i = 0; i < 4; i++) { - retval = rtsx_read_register(chip, CFGDATA0 + i, &tmp); - if (retval) - return retval; - data |= (u32)tmp << (i * 8); - } - - if (val) - *val = data; - - return STATUS_SUCCESS; -} - -int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, - int len) -{ - u32 *data, *mask; - u16 offset = addr % 4; - u16 aligned_addr = addr - offset; - int dw_len, i, j; - int retval; - size_t size; - - if (!buf) - return STATUS_NOMEM; - - if ((len + offset) % 4) - dw_len = (len + offset) / 4 + 1; - else - dw_len = (len + offset) / 4; - - dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len); - - size = array_size(dw_len, 4); - data = vzalloc(size); - if (!data) - return STATUS_NOMEM; - - mask = vzalloc(size); - if (!mask) { - vfree(data); - return STATUS_NOMEM; - } - - j = 0; - for (i = 0; i < len; i++) { - mask[j] |= 0xFF << (offset * 8); - data[j] |= buf[i] << (offset * 8); - if (++offset == 4) { - j++; - offset = 0; - } - } - - print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask, size); - print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data, size); - - for (i = 0; i < dw_len; i++) { - retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4, - mask[i], data[i]); - if (retval != STATUS_SUCCESS) { - vfree(data); - vfree(mask); - return STATUS_FAIL; - } - } - - vfree(data); - vfree(mask); - - return STATUS_SUCCESS; -} - -int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, - int len) -{ - u32 *data; - u16 offset = addr % 4; - u16 aligned_addr = addr - offset; - int dw_len, i, j; - int retval; - - if ((len + offset) % 4) - dw_len = (len + offset) / 4 + 1; - else - dw_len = (len + offset) / 4; - - dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len); - - data = vmalloc(array_size(dw_len, 4)); - if (!data) - return STATUS_NOMEM; - - for (i = 0; i < dw_len; i++) { - retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4, - data + i); - if (retval != STATUS_SUCCESS) { - vfree(data); - return STATUS_FAIL; - } - } - - if (buf) { - j = 0; - - for (i = 0; i < len; i++) { - buf[i] = (u8)(data[j] >> (offset * 8)); - if (++offset == 4) { - j++; - offset = 0; - } - } - } - - vfree(data); - - return STATUS_SUCCESS; -} - -int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val) -{ - int retval; - bool finished = false; - int i; - u8 tmp; - - retval = rtsx_write_register(chip, PHYDATA0, 0xFF, (u8)val); - if (retval) - return retval; - retval = rtsx_write_register(chip, PHYDATA1, 0xFF, (u8)(val >> 8)); - if (retval) - return retval; - retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr); - if (retval) - return retval; - retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x81); - if (retval) - return retval; - - for (i = 0; i < 100000; i++) { - retval = rtsx_read_register(chip, PHYRWCTL, &tmp); - if (retval) - return retval; - if (!(tmp & 0x80)) { - finished = true; - break; - } - } - - if (!finished) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val) -{ - int retval; - bool finished = false; - int i; - u16 data = 0; - u8 tmp; - - retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr); - if (retval) - return retval; - retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x80); - if (retval) - return retval; - - for (i = 0; i < 100000; i++) { - retval = rtsx_read_register(chip, PHYRWCTL, &tmp); - if (retval) - return retval; - if (!(tmp & 0x80)) { - finished = true; - break; - } - } - - if (!finished) - return STATUS_FAIL; - - retval = rtsx_read_register(chip, PHYDATA0, &tmp); - if (retval) - return retval; - data = tmp; - retval = rtsx_read_register(chip, PHYDATA1, &tmp); - if (retval) - return retval; - data |= (u16)tmp << 8; - - if (val) - *val = data; - - return STATUS_SUCCESS; -} - -int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val) -{ - int retval; - int i; - u8 data = 0; - - retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, 0x80 | addr); - if (retval) - return retval; - - for (i = 0; i < 100; i++) { - retval = rtsx_read_register(chip, EFUSE_CTRL, &data); - if (retval) - return retval; - if (!(data & 0x80)) - break; - udelay(1); - } - - if (data & 0x80) - return STATUS_TIMEDOUT; - - retval = rtsx_read_register(chip, EFUSE_DATA, &data); - if (retval) - return retval; - if (val) - *val = data; - - return STATUS_SUCCESS; -} - -int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val) -{ - int retval; - int i, j; - u8 data = 0, tmp = 0xFF; - - for (i = 0; i < 8; i++) { - if (val & (u8)(1 << i)) - continue; - - tmp &= (~(u8)(1 << i)); - dev_dbg(rtsx_dev(chip), "Write 0x%x to 0x%x\n", tmp, addr); - - retval = rtsx_write_register(chip, EFUSE_DATA, 0xFF, tmp); - if (retval) - return retval; - retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, - 0xA0 | addr); - if (retval) - return retval; - - for (j = 0; j < 100; j++) { - retval = rtsx_read_register(chip, EFUSE_CTRL, &data); - if (retval) - return retval; - if (!(data & 0x80)) - break; - wait_timeout(3); - } - - if (data & 0x80) - return STATUS_TIMEDOUT; - - wait_timeout(5); - } - - return STATUS_SUCCESS; -} - -int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) -{ - int retval; - u16 value; - - retval = rtsx_read_phy_register(chip, reg, &value); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (value & (1 << bit)) { - value &= ~(1 << bit); - retval = rtsx_write_phy_register(chip, reg, value); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit) -{ - int retval; - u16 value; - - retval = rtsx_read_phy_register(chip, reg, &value); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if ((value & (1 << bit)) == 0) { - value |= (1 << bit); - retval = rtsx_write_phy_register(chip, reg, value); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate) -{ - u32 ultmp; - - dev_dbg(rtsx_dev(chip), "%04x set pm_dstate to %d\n", - chip->product_id, dstate); - - if (CHK_SDIO_EXIST(chip)) { - u8 func_no; - - if (CHECK_PID(chip, 0x5288)) - func_no = 2; - else - func_no = 1; - - rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp); - dev_dbg(rtsx_dev(chip), "pm_dstate of function %d: 0x%x\n", - (int)func_no, ultmp); - rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate); - } - - rtsx_write_config_byte(chip, 0x44, dstate); - rtsx_write_config_byte(chip, 0x45, 0); -} - -void rtsx_enter_L1(struct rtsx_chip *chip) -{ - rtsx_handle_pm_dstate(chip, 2); -} - -void rtsx_exit_L1(struct rtsx_chip *chip) -{ - rtsx_write_config_byte(chip, 0x44, 0); - rtsx_write_config_byte(chip, 0x45, 0); -} - -void rtsx_enter_ss(struct rtsx_chip *chip) -{ - dev_dbg(rtsx_dev(chip), "Enter Selective Suspend State!\n"); - - rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT); - - if (chip->power_down_in_ss) { - rtsx_power_off_card(chip); - rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); - } - - if (CHK_SDIO_EXIST(chip)) - rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1, - 0xC0, 0xFF00, 0x0100); - - if (chip->auto_delink_en) { - rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01); - } else { - if (!chip->phy_debug_mode) { - u32 tmp; - - tmp = rtsx_readl(chip, RTSX_BIER); - tmp |= CARD_INT; - rtsx_writel(chip, RTSX_BIER, tmp); - } - - rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0); - } - - rtsx_enter_L1(chip); - - RTSX_CLR_DELINK(chip); - rtsx_set_stat(chip, RTSX_STAT_SS); -} - -void rtsx_exit_ss(struct rtsx_chip *chip) -{ - dev_dbg(rtsx_dev(chip), "Exit Selective Suspend State!\n"); - - rtsx_exit_L1(chip); - - if (chip->power_down_in_ss) { - rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL); - udelay(1000); - } - - if (RTSX_TST_DELINK(chip)) { - chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; - rtsx_reinit_cards(chip, 1); - RTSX_CLR_DELINK(chip); - } else if (chip->power_down_in_ss) { - chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; - rtsx_reinit_cards(chip, 0); - } -} - -int rtsx_pre_handle_interrupt(struct rtsx_chip *chip) -{ - u32 status, int_enable; - bool exit_ss = false; -#ifdef SUPPORT_OCP - u32 ocp_int = 0; - - ocp_int = OC_INT; -#endif - - if (chip->ss_en) { - chip->ss_counter = 0; - if (rtsx_get_stat(chip) == RTSX_STAT_SS) { - exit_ss = true; - rtsx_exit_L1(chip); - rtsx_set_stat(chip, RTSX_STAT_RUN); - } - } - - int_enable = rtsx_readl(chip, RTSX_BIER); - chip->int_reg = rtsx_readl(chip, RTSX_BIPR); - - if (((chip->int_reg & int_enable) == 0) || - chip->int_reg == 0xFFFFFFFF) - return STATUS_FAIL; - - status = chip->int_reg &= (int_enable | 0x7FFFFF); - - if (status & CARD_INT) { - chip->auto_delink_cnt = 0; - - if (status & SD_INT) { - if (status & SD_EXIST) { - set_bit(SD_NR, &chip->need_reset); - } else { - set_bit(SD_NR, &chip->need_release); - chip->sd_reset_counter = 0; - chip->sd_show_cnt = 0; - clear_bit(SD_NR, &chip->need_reset); - } - } else { - /* - * If multi-luns, it's possible that - * when plugging/unplugging one card - * there is another card which still - * exists in the slot. In this case, - * all existed cards should be reset. - */ - if (exit_ss && (status & SD_EXIST)) - set_bit(SD_NR, &chip->need_reinit); - } - if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) { - if (status & XD_INT) { - if (status & XD_EXIST) { - set_bit(XD_NR, &chip->need_reset); - } else { - set_bit(XD_NR, &chip->need_release); - chip->xd_reset_counter = 0; - chip->xd_show_cnt = 0; - clear_bit(XD_NR, &chip->need_reset); - } - } else { - if (exit_ss && (status & XD_EXIST)) - set_bit(XD_NR, &chip->need_reinit); - } - } - if (status & MS_INT) { - if (status & MS_EXIST) { - set_bit(MS_NR, &chip->need_reset); - } else { - set_bit(MS_NR, &chip->need_release); - chip->ms_reset_counter = 0; - chip->ms_show_cnt = 0; - clear_bit(MS_NR, &chip->need_reset); - } - } else { - if (exit_ss && (status & MS_EXIST)) - set_bit(MS_NR, &chip->need_reinit); - } - } - -#ifdef SUPPORT_OCP - chip->ocp_int = ocp_int & status; -#endif - - if (chip->sd_io && (chip->int_reg & DATA_DONE_INT)) - chip->int_reg &= ~(u32)DATA_DONE_INT; - - return STATUS_SUCCESS; -} - -void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat) -{ - int retval; - - dev_dbg(rtsx_dev(chip), "%s, pm_stat = %d\n", __func__, pm_stat); - - rtsx_set_stat(chip, RTSX_STAT_SUSPEND); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) - return; - - rtsx_release_cards(chip); - rtsx_disable_bus_int(chip); - turn_off_led(chip, LED_GPIO); - -#ifdef HW_AUTO_SWITCH_SD_BUS - if (chip->sd_io) { - chip->sdio_in_charge = 1; - if (CHECK_PID(chip, 0x5208)) { - rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08); - /* Enable sdio_bus_auto_switch */ - rtsx_write_register(chip, 0xFE70, 0x80, 0x80); - } else if (CHECK_PID(chip, 0x5288)) { - rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08); - /* Enable sdio_bus_auto_switch */ - rtsx_write_register(chip, 0xFE5A, 0x08, 0x08); - } - } -#endif - - if (CHECK_PID(chip, 0x5208) && chip->ic_version >= IC_VER_D) { - /* u_force_clkreq_0 */ - rtsx_write_register(chip, PETXCFG, 0x08, 0x08); - } - - if (pm_stat == PM_S1) { - dev_dbg(rtsx_dev(chip), "Host enter S1\n"); - rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, - HOST_ENTER_S1); - } else if (pm_stat == PM_S3) { - if (chip->s3_pwr_off_delay > 0) - wait_timeout(chip->s3_pwr_off_delay); - - dev_dbg(rtsx_dev(chip), "Host enter S3\n"); - rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, - HOST_ENTER_S3); - } - - if (chip->do_delink_before_power_down && chip->auto_delink_en) - rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2); - - rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL); - - chip->cur_clk = 0; - chip->cur_card = 0; - chip->card_exist = 0; -} - -void rtsx_enable_aspm(struct rtsx_chip *chip) -{ - if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && !chip->aspm_enabled) { - dev_dbg(rtsx_dev(chip), "Try to enable ASPM\n"); - chip->aspm_enabled = 1; - - if (chip->asic_code && CHECK_PID(chip, 0x5208)) - rtsx_write_phy_register(chip, 0x07, 0); - if (CHECK_PID(chip, 0x5208)) { - rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3, - 0x30 | chip->aspm_level[0]); - } else { - rtsx_write_config_byte(chip, LCTLR, - chip->aspm_l0s_l1_en); - } - - if (CHK_SDIO_EXIST(chip)) { - u16 val = chip->aspm_l0s_l1_en | 0x0100; - - rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1, - 0xC0, 0xFFF, val); - } - } -} - -void rtsx_disable_aspm(struct rtsx_chip *chip) -{ - if (CHECK_PID(chip, 0x5208)) - rtsx_monitor_aspm_config(chip); - - if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && chip->aspm_enabled) { - dev_dbg(rtsx_dev(chip), "Try to disable ASPM\n"); - chip->aspm_enabled = 0; - - if (chip->asic_code && CHECK_PID(chip, 0x5208)) - rtsx_write_phy_register(chip, 0x07, 0x0129); - if (CHECK_PID(chip, 0x5208)) - rtsx_write_register(chip, ASPM_FORCE_CTL, - 0xF3, 0x30); - else - rtsx_write_config_byte(chip, LCTLR, 0x00); - - wait_timeout(1); - } -} - -int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) -{ - int retval; - int i, j; - u16 reg_addr; - u8 *ptr; - - if (!buf) - return STATUS_ERROR; - - ptr = buf; - reg_addr = PPBUF_BASE2; - for (i = 0; i < buf_len / 256; i++) { - rtsx_init_cmd(chip); - - for (j = 0; j < 256; j++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); - - retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) - return STATUS_FAIL; - - memcpy(ptr, rtsx_get_cmd_data(chip), 256); - ptr += 256; - } - - if (buf_len % 256) { - rtsx_init_cmd(chip); - - for (j = 0; j < buf_len % 256; j++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0); - - retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) - return STATUS_FAIL; - } - - memcpy(ptr, rtsx_get_cmd_data(chip), buf_len % 256); - - return STATUS_SUCCESS; -} - -int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len) -{ - int retval; - int i, j; - u16 reg_addr; - u8 *ptr; - - if (!buf) - return STATUS_ERROR; - - ptr = buf; - reg_addr = PPBUF_BASE2; - for (i = 0; i < buf_len / 256; i++) { - rtsx_init_cmd(chip); - - for (j = 0; j < 256; j++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, - *ptr); - ptr++; - } - - retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) - return STATUS_FAIL; - } - - if (buf_len % 256) { - rtsx_init_cmd(chip); - - for (j = 0; j < buf_len % 256; j++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, - *ptr); - ptr++; - } - - retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int rtsx_check_chip_exist(struct rtsx_chip *chip) -{ - if (rtsx_readl(chip, 0) == 0xFFFFFFFF) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl) -{ - int retval; - u8 mask = 0; - - if (ctl & SSC_PDCTL) - mask |= SSC_POWER_DOWN; - -#ifdef SUPPORT_OCP - if (ctl & OC_PDCTL) { - mask |= SD_OC_POWER_DOWN; - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) - mask |= MS_OC_POWER_DOWN; - } -#endif - - if (mask) { - retval = rtsx_write_register(chip, FPDCTL, mask, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHECK_PID(chip, 0x5288)) - wait_timeout(200); - } - - return STATUS_SUCCESS; -} - -int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl) -{ - int retval; - u8 mask = 0, val = 0; - - if (ctl & SSC_PDCTL) - mask |= SSC_POWER_DOWN; - -#ifdef SUPPORT_OCP - if (ctl & OC_PDCTL) { - mask |= SD_OC_POWER_DOWN; - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) - mask |= MS_OC_POWER_DOWN; - } -#endif - - if (mask) { - val = mask; - retval = rtsx_write_register(chip, FPDCTL, mask, val); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h deleted file mode 100644 index bac65784d4a1983631a98e68e2810481ed9d1114..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_chip.h +++ /dev/null @@ -1,987 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_CHIP_H -#define __REALTEK_RTSX_CHIP_H - -#include "rtsx.h" - -#define SUPPORT_CPRM -#define SUPPORT_OCP -#define SUPPORT_SDIO_ASPM -#define SUPPORT_MAGIC_GATE -#define SUPPORT_MSXC -#define SUPPORT_SD_LOCK -/* Hardware switch bus_ctl and cd_ctl automatically */ -#define HW_AUTO_SWITCH_SD_BUS -/* Enable hardware interrupt write clear */ -#define HW_INT_WRITE_CLR -/* #define LED_AUTO_BLINK */ -/* #define DISABLE_CARD_INT */ - -#ifdef SUPPORT_MAGIC_GATE - /* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */ - #define MG_SET_ICV_SLOW - /* HW may miss ERR/CMDNK signal when sampling INT status. */ - #define MS_SAMPLE_INT_ERR - /* - * HW DO NOT support Wait_INT function - * during READ_BYTES transfer mode - */ - #define READ_BYTES_WAIT_INT -#endif - -#ifdef SUPPORT_MSXC -#define XC_POWERCLASS -#define SUPPORT_PCGL_1P18 -#endif - -#ifndef LED_AUTO_BLINK -#define REGULAR_BLINK -#endif - -#define LED_BLINK_SPEED 5 -#define LED_TOGGLE_INTERVAL 6 -#define GPIO_TOGGLE_THRESHOLD 1024 -#define LED_GPIO 0 - -#define POLLING_INTERVAL 30 - -#define TRACE_ITEM_CNT 64 - -#ifndef STATUS_SUCCESS -#define STATUS_SUCCESS 0 -#endif -#ifndef STATUS_FAIL -#define STATUS_FAIL 1 -#endif -#ifndef STATUS_TIMEDOUT -#define STATUS_TIMEDOUT 2 -#endif -#ifndef STATUS_NOMEM -#define STATUS_NOMEM 3 -#endif -#ifndef STATUS_READ_FAIL -#define STATUS_READ_FAIL 4 -#endif -#ifndef STATUS_WRITE_FAIL -#define STATUS_WRITE_FAIL 5 -#endif -#ifndef STATUS_ERROR -#define STATUS_ERROR 10 -#endif - -#define PM_S1 1 -#define PM_S3 3 - -/* - * Transport return codes - */ - -#define TRANSPORT_GOOD 0 /* Transport good, command good */ -#define TRANSPORT_FAILED 1 /* Transport good, command failed */ -#define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */ -#define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */ - -/* - * Start-Stop-Unit - */ -#define STOP_MEDIUM 0x00 /* access disable */ -#define MAKE_MEDIUM_READY 0x01 /* access enable */ -#define UNLOAD_MEDIUM 0x02 /* unload */ -#define LOAD_MEDIUM 0x03 /* load */ - -/* - * STANDARD_INQUIRY - */ -#define QULIFIRE 0x00 -#define AENC_FNC 0x00 -#define TRML_IOP 0x00 -#define REL_ADR 0x00 -#define WBUS_32 0x00 -#define WBUS_16 0x00 -#define SYNC 0x00 -#define LINKED 0x00 -#define CMD_QUE 0x00 -#define SFT_RE 0x00 - -#define VEN_ID_LEN 8 /* Vendor ID Length */ -#define PRDCT_ID_LEN 16 /* Product ID Length */ -#define PRDCT_REV_LEN 4 /* Product LOT Length */ - -/* Dynamic flag definitions: used in set_bit() etc. */ -/* 0x00040000 transfer is active */ -#define RTSX_FLIDX_TRANS_ACTIVE 18 -/* 0x00100000 abort is in progress */ -#define RTSX_FLIDX_ABORTING 20 -/* 0x00200000 disconnect in progress */ -#define RTSX_FLIDX_DISCONNECTING 21 - -#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \ - (1UL << US_FLIDX_DISCONNECTING)) - -/* 0x00400000 device reset in progress */ -#define RTSX_FLIDX_RESETTING 22 -/* 0x00800000 SCSI midlayer timed out */ -#define RTSX_FLIDX_TIMED_OUT 23 -#define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */ -#define RMB_DISC 0x80 /* The Device is Removable */ -#define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */ - -#define SCSI 0x00 /* Interface ID */ - -#define WRITE_PROTECTED_MEDIA 0x07 - -/*---- sense key ----*/ -#define ILI 0x20 /* ILI bit is on */ - -#define NO_SENSE 0x00 /* not exist sense key */ -#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */ -#define NOT_READY 0x02 /* Logical unit is not ready */ -#define MEDIA_ERR 0x03 /* medium/data error */ -#define HARDWARE_ERR 0x04 /* hardware error */ -#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */ -#define UNIT_ATTENTION 0x06 /* unit attention condition occur */ -#define DAT_PRTCT 0x07 /* read/write is desable */ -#define BLNC_CHK 0x08 /* find blank/DOF in read */ - /* write to unblank area */ -#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illegal */ -#define ABRT_CMD 0x0b /* Target make the command in error */ -#define EQUAL 0x0c /* Search Data end with Equal */ -#define VLM_OVRFLW 0x0d /* Some data are left in buffer */ -#define MISCMP 0x0e /* find inequality */ - -#define READ_ERR -1 -#define WRITE_ERR -2 - -#define FIRST_RESET 0x01 -#define USED_EXIST 0x02 - -/* - * SENSE_DATA - */ -/*---- valid ----*/ -#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */ -#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */ - -/*---- error code ----*/ -#define CUR_ERR 0x70 /* current error */ -#define DEF_ERR 0x71 /* specific command error */ - -/*---- sense key Information ----*/ -#define SNSKEYINFO_LEN 3 /* length of sense key information */ - -#define SKSV 0x80 -#define CDB_ILLEGAL 0x40 -#define DAT_ILLEGAL 0x00 -#define BPV 0x08 -#define BIT_ILLEGAL0 0 /* bit0 is illegal */ -#define BIT_ILLEGAL1 1 /* bit1 is illegal */ -#define BIT_ILLEGAL2 2 /* bit2 is illegal */ -#define BIT_ILLEGAL3 3 /* bit3 is illegal */ -#define BIT_ILLEGAL4 4 /* bit4 is illegal */ -#define BIT_ILLEGAL5 5 /* bit5 is illegal */ -#define BIT_ILLEGAL6 6 /* bit6 is illegal */ -#define BIT_ILLEGAL7 7 /* bit7 is illegal */ - -/*---- ASC ----*/ -#define ASC_NO_INFO 0x00 -#define ASC_MISCMP 0x1d -#define ASC_INVLD_CDB 0x24 -#define ASC_INVLD_PARA 0x26 -#define ASC_LU_NOT_READY 0x04 -#define ASC_WRITE_ERR 0x0c -#define ASC_READ_ERR 0x11 -#define ASC_LOAD_EJCT_ERR 0x53 -#define ASC_MEDIA_NOT_PRESENT 0x3A -#define ASC_MEDIA_CHANGED 0x28 -#define ASC_MEDIA_IN_PROCESS 0x04 -#define ASC_WRITE_PROTECT 0x27 -#define ASC_LUN_NOT_SUPPORTED 0x25 - -/*---- ASQC ----*/ -#define ASCQ_NO_INFO 0x00 -#define ASCQ_MEDIA_IN_PROCESS 0x01 -#define ASCQ_MISCMP 0x00 -#define ASCQ_INVLD_CDB 0x00 -#define ASCQ_INVLD_PARA 0x02 -#define ASCQ_LU_NOT_READY 0x02 -#define ASCQ_WRITE_ERR 0x02 -#define ASCQ_READ_ERR 0x00 -#define ASCQ_LOAD_EJCT_ERR 0x00 -#define ASCQ_WRITE_PROTECT 0x00 - -struct sense_data_t { - unsigned char err_code; /* error code */ - /* bit7 : valid */ - /* (1 : SCSI2) */ - /* (0 : Vendor * specific) */ - /* bit6-0 : error * code */ - /* (0x70 : current * error) */ - /* (0x71 : specific command error) */ - unsigned char seg_no; /* segment No. */ - unsigned char sense_key; /* byte5 : ILI */ - /* bit3-0 : sense key */ - unsigned char info[4]; /* information */ - unsigned char ad_sense_len; /* additional sense data length */ - unsigned char cmd_info[4]; /* command specific information */ - unsigned char asc; /* ASC */ - unsigned char ascq; /* ASCQ */ - unsigned char rfu; /* FRU */ - unsigned char sns_key_info[3];/* sense key specific information */ -}; - -/* PCI Operation Register Address */ -#define RTSX_HCBAR 0x00 -#define RTSX_HCBCTLR 0x04 -#define RTSX_HDBAR 0x08 -#define RTSX_HDBCTLR 0x0C -#define RTSX_HAIMR 0x10 -#define RTSX_BIPR 0x14 -#define RTSX_BIER 0x18 - -/* Host command buffer control register */ -#define STOP_CMD (0x01 << 28) - -/* Host data buffer control register */ -#define SDMA_MODE 0x00 -#define ADMA_MODE (0x02 << 26) -#define STOP_DMA (0x01 << 28) -#define TRIG_DMA (0x01 << 31) - -/* Bus interrupt pending register */ -#define CMD_DONE_INT BIT(31) -#define DATA_DONE_INT BIT(30) -#define TRANS_OK_INT BIT(29) -#define TRANS_FAIL_INT BIT(28) -#define XD_INT BIT(27) -#define MS_INT BIT(26) -#define SD_INT BIT(25) -#define GPIO0_INT BIT(24) -#define OC_INT BIT(23) -#define SD_WRITE_PROTECT BIT(19) -#define XD_EXIST BIT(18) -#define MS_EXIST BIT(17) -#define SD_EXIST BIT(16) -#define DELINK_INT GPIO0_INT -#define MS_OC_INT BIT(23) -#define SD_OC_INT BIT(22) - -#define CARD_INT (XD_INT | MS_INT | SD_INT) -#define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT) -#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | \ - GPIO0_INT | OC_INT) - -#define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST) - -/* Bus interrupt enable register */ -#define CMD_DONE_INT_EN BIT(31) -#define DATA_DONE_INT_EN BIT(30) -#define TRANS_OK_INT_EN BIT(29) -#define TRANS_FAIL_INT_EN BIT(28) -#define XD_INT_EN BIT(27) -#define MS_INT_EN BIT(26) -#define SD_INT_EN BIT(25) -#define GPIO0_INT_EN BIT(24) -#define OC_INT_EN BIT(23) -#define DELINK_INT_EN GPIO0_INT_EN -#define MS_OC_INT_EN BIT(23) -#define SD_OC_INT_EN BIT(22) - -#define READ_REG_CMD 0 -#define WRITE_REG_CMD 1 -#define CHECK_REG_CMD 2 - -#define HOST_TO_DEVICE 0 -#define DEVICE_TO_HOST 1 - -#define RTSX_RESV_BUF_LEN 4096 -#define HOST_CMDS_BUF_LEN 1024 -#define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN) - -#define SD_NR 2 -#define MS_NR 3 -#define XD_NR 4 -#define SPI_NR 7 -#define SD_CARD BIT(SD_NR) -#define MS_CARD BIT(MS_NR) -#define XD_CARD BIT(XD_NR) -#define SPI_CARD BIT(SPI_NR) - -#define MAX_ALLOWED_LUN_CNT 8 - -#define XD_FREE_TABLE_CNT 1200 -#define MS_FREE_TABLE_CNT 512 - -/* Bit Operation */ -#define SET_BIT(data, idx) ((data) |= 1 << (idx)) -#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx))) -#define CHK_BIT(data, idx) ((data) & (1 << (idx))) - -/* SG descriptor */ -#define RTSX_SG_INT 0x04 -#define RTSX_SG_END 0x02 -#define RTSX_SG_VALID 0x01 - -#define RTSX_SG_NO_OP 0x00 -#define RTSX_SG_TRANS_DATA (0x02 << 4) -#define RTSX_SG_LINK_DESC (0x03 << 4) - -struct rtsx_chip; - -typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 sec_addr, u16 sec_cnt); - -/* Supported Clock */ -enum card_clock {CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60, - CLK_80, CLK_100, CLK_120, CLK_150, CLK_200}; - -enum RTSX_STAT {RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS, - RTSX_STAT_DELINK, RTSX_STAT_SUSPEND, - RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT}; -enum IC_VER {IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3}; - -#define MAX_RESET_CNT 3 - -/* For MS Card */ -#define MAX_DEFECTIVE_BLOCK 10 - -struct zone_entry { - u16 *l2p_table; - u16 *free_table; - u16 defect_list[MAX_DEFECTIVE_BLOCK]; /* For MS card only */ - int set_index; - int get_index; - int unused_blk_cnt; - int disable_count; - /* To indicate whether the L2P table of this zone has been built. */ - int build_flag; -}; - -#define TYPE_SD 0x0000 -#define TYPE_MMC 0x0001 - -/* TYPE_SD */ -#define SD_HS 0x0100 -#define SD_SDR50 0x0200 -#define SD_DDR50 0x0400 -#define SD_SDR104 0x0800 -#define SD_HCXC 0x1000 - -/* TYPE_MMC */ -#define MMC_26M 0x0100 -#define MMC_52M 0x0200 -#define MMC_4BIT 0x0400 -#define MMC_8BIT 0x0800 -#define MMC_SECTOR_MODE 0x1000 -#define MMC_DDR52 0x2000 - -/* SD card */ -#define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD) -#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && \ - ((sd_card)->sd_type & SD_HS)) -#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && \ - ((sd_card)->sd_type & SD_SDR50)) -#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && \ - ((sd_card)->sd_type & SD_DDR50)) -#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && \ - ((sd_card)->sd_type & SD_SDR104)) -#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && \ - ((sd_card)->sd_type & SD_HCXC)) -#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && \ - ((sd_card)->capacity <= 0x4000000)) -#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && \ - ((sd_card)->capacity > 0x4000000)) -#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || \ - CHK_SD_DDR50(sd_card) || \ - CHK_SD_SDR104(sd_card)) - -#define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD) -#define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS) -#define SET_SD_SDR50(sd_card) ((sd_card)->sd_type |= SD_SDR50) -#define SET_SD_DDR50(sd_card) ((sd_card)->sd_type |= SD_DDR50) -#define SET_SD_SDR104(sd_card) ((sd_card)->sd_type |= SD_SDR104) -#define SET_SD_HCXC(sd_card) ((sd_card)->sd_type |= SD_HCXC) - -#define CLR_SD_HS(sd_card) ((sd_card)->sd_type &= ~SD_HS) -#define CLR_SD_SDR50(sd_card) ((sd_card)->sd_type &= ~SD_SDR50) -#define CLR_SD_DDR50(sd_card) ((sd_card)->sd_type &= ~SD_DDR50) -#define CLR_SD_SDR104(sd_card) ((sd_card)->sd_type &= ~SD_SDR104) -#define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC) - -/* MMC card */ -#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == \ - TYPE_MMC) -#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && \ - ((sd_card)->sd_type & MMC_26M)) -#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && \ - ((sd_card)->sd_type & MMC_52M)) -#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && \ - ((sd_card)->sd_type & MMC_4BIT)) -#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && \ - ((sd_card)->sd_type & MMC_8BIT)) -#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && \ - ((sd_card)->sd_type & MMC_SECTOR_MODE)) -#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && \ - ((sd_card)->sd_type & MMC_DDR52)) - -#define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC) -#define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M) -#define SET_MMC_52M(sd_card) ((sd_card)->sd_type |= MMC_52M) -#define SET_MMC_4BIT(sd_card) ((sd_card)->sd_type |= MMC_4BIT) -#define SET_MMC_8BIT(sd_card) ((sd_card)->sd_type |= MMC_8BIT) -#define SET_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type |= MMC_SECTOR_MODE) -#define SET_MMC_DDR52(sd_card) ((sd_card)->sd_type |= MMC_DDR52) - -#define CLR_MMC_26M(sd_card) ((sd_card)->sd_type &= ~MMC_26M) -#define CLR_MMC_52M(sd_card) ((sd_card)->sd_type &= ~MMC_52M) -#define CLR_MMC_4BIT(sd_card) ((sd_card)->sd_type &= ~MMC_4BIT) -#define CLR_MMC_8BIT(sd_card) ((sd_card)->sd_type &= ~MMC_8BIT) -#define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE) -#define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52) - -#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && \ - CHK_MMC_26M(sd_card)) -#define CLR_MMC_HS(sd_card) \ -do { \ - CLR_MMC_DDR52(sd_card); \ - CLR_MMC_52M(sd_card); \ - CLR_MMC_26M(sd_card); \ -} while (0) - -#define SD_SUPPORT_CLASS_TEN 0x01 -#define SD_SUPPORT_1V8 0x02 - -#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= \ - SD_SUPPORT_CLASS_TEN) -#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & \ - SD_SUPPORT_CLASS_TEN) -#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= \ - ~SD_SUPPORT_CLASS_TEN) -#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= \ - SD_SUPPORT_1V8) -#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & \ - SD_SUPPORT_1V8) -#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= \ - ~SD_SUPPORT_1V8) - -struct sd_info { - u16 sd_type; - u8 err_code; - u8 sd_data_buf_ready; - u32 sd_addr; - u32 capacity; - - u8 raw_csd[16]; - u8 raw_scr[8]; - - /* Sequential RW */ - int seq_mode; - enum dma_data_direction pre_dir; - u32 pre_sec_addr; - u16 pre_sec_cnt; - - int cleanup_counter; - - int sd_clock; - - int mmc_dont_switch_bus; - -#ifdef SUPPORT_CPRM - int sd_pass_thru_en; - int pre_cmd_err; - u8 last_rsp_type; - u8 rsp[17]; -#endif - - u8 func_group1_mask; - u8 func_group2_mask; - u8 func_group3_mask; - u8 func_group4_mask; - - u8 sd_switch_fail; - u8 sd_read_phase; - -#ifdef SUPPORT_SD_LOCK - u8 sd_lock_status; - u8 sd_erase_status; - u8 sd_lock_notify; -#endif - int need_retune; -}; - -struct xd_delay_write_tag { - u32 old_phyblock; - u32 new_phyblock; - u32 logblock; - u8 pageoff; - u8 delay_write_flag; -}; - -struct xd_info { - u8 maker_code; - u8 device_code; - u8 block_shift; - u8 page_off; - u8 addr_cycle; - u16 cis_block; - u8 multi_flag; - u8 err_code; - u32 capacity; - - struct zone_entry *zone; - int zone_cnt; - - struct xd_delay_write_tag delay_write; - int cleanup_counter; - - int xd_clock; -}; - -#define MODE_512_SEQ 0x01 -#define MODE_2K_SEQ 0x02 - -#define TYPE_MS 0x0000 -#define TYPE_MSPRO 0x0001 - -#define MS_4BIT 0x0100 -#define MS_8BIT 0x0200 -#define MS_HG 0x0400 -#define MS_XC 0x0800 - -#define HG8BIT (MS_HG | MS_8BIT) - -#define CHK_MSPRO(ms_card) (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO) -#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && \ - (((ms_card)->ms_type & HG8BIT) == HG8BIT)) -#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && \ - ((ms_card)->ms_type & MS_XC)) -#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && \ - ((ms_card)->ms_type & MS_HG)) - -#define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT)) -#define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT)) - -struct ms_delay_write_tag { - u16 old_phyblock; - u16 new_phyblock; - u16 logblock; - u8 pageoff; - u8 delay_write_flag; -}; - -struct ms_info { - u16 ms_type; - u8 block_shift; - u8 page_off; - u16 total_block; - u16 boot_block; - u32 capacity; - - u8 check_ms_flow; - u8 switch_8bit_fail; - u8 err_code; - - struct zone_entry *segment; - int segment_cnt; - - int pro_under_formatting; - int format_status; - u16 progress; - u8 raw_sys_info[96]; -#ifdef SUPPORT_PCGL_1P18 - u8 raw_model_name[48]; -#endif - - u8 multi_flag; - - /* Sequential RW */ - u8 seq_mode; - enum dma_data_direction pre_dir; - u32 pre_sec_addr; - u16 pre_sec_cnt; - u32 total_sec_cnt; - - struct ms_delay_write_tag delay_write; - - int cleanup_counter; - - int ms_clock; - -#ifdef SUPPORT_MAGIC_GATE - u8 magic_gate_id[16]; - u8 mg_entry_num; - int mg_auth; /* flag to indicate authentication process */ -#endif -}; - -struct spi_info { - u8 use_clk; - u8 write_en; - u16 clk_div; - u8 err_code; - - int spi_clock; -}; - -/************/ -/* LUN mode */ -/************/ -/* Single LUN, support xD/SD/MS */ -#define DEFAULT_SINGLE 0 -/* 2 LUN mode, support SD/MS */ -#define SD_MS_2LUN 1 -/* Single LUN, but only support SD/MS, for Barossa LQFP */ -#define SD_MS_1LUN 2 - -#define LAST_LUN_MODE 2 - -/* Barossa package */ -#define QFN 0 -#define LQFP 1 - -/******************/ -/* sd_ctl bit map */ -/******************/ -/* SD push point control, bit 0, 1 */ -#define SD_PUSH_POINT_CTL_MASK 0x03 -#define SD_PUSH_POINT_DELAY 0x01 -#define SD_PUSH_POINT_AUTO 0x02 -/* SD sample point control, bit 2, 3 */ -#define SD_SAMPLE_POINT_CTL_MASK 0x0C -#define SD_SAMPLE_POINT_DELAY 0x04 -#define SD_SAMPLE_POINT_AUTO 0x08 -/* SD DDR Tx phase set by user, bit 4 */ -#define SD_DDR_TX_PHASE_SET_BY_USER 0x10 -/* MMC DDR Tx phase set by user, bit 5 */ -#define MMC_DDR_TX_PHASE_SET_BY_USER 0x20 -/* Support MMC DDR mode, bit 6 */ -#define SUPPORT_MMC_DDR_MODE 0x40 -/* Reset MMC at first */ -#define RESET_MMC_FIRST 0x80 - -#define SEQ_START_CRITERIA 0x20 - -/* MS Power Class En */ -#define POWER_CLASS_2_EN 0x02 -#define POWER_CLASS_1_EN 0x01 - -#define MAX_SHOW_CNT 10 -#define MAX_RESET_CNT 3 - -#define SDIO_EXIST 0x01 -#define SDIO_IGNORED 0x02 - -#define CHK_SDIO_EXIST(chip) ((chip)->sdio_func_exist & SDIO_EXIST) -#define SET_SDIO_EXIST(chip) ((chip)->sdio_func_exist |= SDIO_EXIST) -#define CLR_SDIO_EXIST(chip) ((chip)->sdio_func_exist &= ~SDIO_EXIST) - -#define CHK_SDIO_IGNORED(chip) ((chip)->sdio_func_exist & SDIO_IGNORED) -#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= \ - SDIO_IGNORED) -#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= \ - ~SDIO_IGNORED) - -struct rtsx_chip { - struct rtsx_dev *rtsx; - - u32 int_reg; /* Bus interrupt pending register */ - char max_lun; - void *context; - - void *host_cmds_ptr; /* host commands buffer pointer */ - dma_addr_t host_cmds_addr; - int ci; /* Command Index */ - - void *host_sg_tbl_ptr; /* SG descriptor table */ - dma_addr_t host_sg_tbl_addr; - int sgi; /* SG entry index */ - - struct scsi_cmnd *srb; /* current srb */ - struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT]; - - int cur_clk; /* current card clock */ - - /* Current accessed card */ - int cur_card; - - unsigned long need_release; /* need release bit map */ - unsigned long need_reset; /* need reset bit map */ - /* - * Flag to indicate that this card is just resumed from SS state, - * and need released before being resetted - */ - unsigned long need_reinit; - - int rw_need_retry; - -#ifdef SUPPORT_OCP - u32 ocp_int; - u8 ocp_stat; -#endif - - u8 card_exist; /* card exist bit map (physical exist) */ - u8 card_ready; /* card ready bit map (reset successfully) */ - u8 card_fail; /* card reset fail bit map */ - u8 card_ejected; /* card ejected bit map */ - u8 card_wp; /* card write protected bit map */ - - u8 lun_mc; /* - * flag to indicate whether to answer - * MediaChange - */ - -#ifndef LED_AUTO_BLINK - int led_toggle_counter; -#endif - - int sd_reset_counter; - int xd_reset_counter; - int ms_reset_counter; - - /* card bus width */ - u8 card_bus_width[MAX_ALLOWED_LUN_CNT]; - /* card capacity */ - u32 capacity[MAX_ALLOWED_LUN_CNT]; - /* read/write card function pointer */ - card_rw_func rw_card[MAX_ALLOWED_LUN_CNT]; - /* read/write capacity, used for GPIO Toggle */ - u32 rw_cap[MAX_ALLOWED_LUN_CNT]; - /* card to lun mapping table */ - u8 card2lun[32]; - /* lun to card mapping table */ - u8 lun2card[MAX_ALLOWED_LUN_CNT]; - - int rw_fail_cnt[MAX_ALLOWED_LUN_CNT]; - - int sd_show_cnt; - int xd_show_cnt; - int ms_show_cnt; - - /* card information */ - struct sd_info sd_card; - struct xd_info xd_card; - struct ms_info ms_card; - - struct spi_info spi; - - int auto_delink_cnt; - int auto_delink_allowed; - - int aspm_enabled; - - int sdio_aspm; - int sdio_idle; - int sdio_counter; - u8 sdio_raw_data[12]; - - u8 sd_io; - u8 sd_int; - - u8 rtsx_flag; - - int ss_counter; - int idle_counter; - enum RTSX_STAT rtsx_stat; - - u16 vendor_id; - u16 product_id; - u8 ic_version; - - int driver_first_load; - -#ifdef HW_AUTO_SWITCH_SD_BUS - int sdio_in_charge; -#endif - - u8 aspm_level[2]; - - int chip_insert_with_sdio; - - /* Options */ - - int adma_mode; - - int auto_delink_en; - int ss_en; - u8 lun_mode; - u8 aspm_l0s_l1_en; - - int power_down_in_ss; - - int sdr104_en; - int ddr50_en; - int sdr50_en; - - int baro_pkg; - - int asic_code; - int phy_debug_mode; - int hw_bypass_sd; - int sdio_func_exist; - int aux_pwr_exist; - u8 ms_power_class_en; - - int mspro_formatter_enable; - - int remote_wakeup_en; - - int ignore_sd; - int use_hw_setting; - - int ss_idle_period; - - int dynamic_aspm; - - int fpga_sd_sdr104_clk; - int fpga_sd_ddr50_clk; - int fpga_sd_sdr50_clk; - int fpga_sd_hs_clk; - int fpga_mmc_52m_clk; - int fpga_ms_hg_clk; - int fpga_ms_4bit_clk; - int fpga_ms_1bit_clk; - - int asic_sd_sdr104_clk; - int asic_sd_ddr50_clk; - int asic_sd_sdr50_clk; - int asic_sd_hs_clk; - int asic_mmc_52m_clk; - int asic_ms_hg_clk; - int asic_ms_4bit_clk; - int asic_ms_1bit_clk; - - u8 ssc_depth_sd_sdr104; - u8 ssc_depth_sd_ddr50; - u8 ssc_depth_sd_sdr50; - u8 ssc_depth_sd_hs; - u8 ssc_depth_mmc_52m; - u8 ssc_depth_ms_hg; - u8 ssc_depth_ms_4bit; - u8 ssc_depth_low_speed; - - u8 card_drive_sel; - u8 sd30_drive_sel_1v8; - u8 sd30_drive_sel_3v3; - - u8 sd_400mA_ocp_thd; - u8 sd_800mA_ocp_thd; - u8 ms_ocp_thd; - - int ssc_en; - int msi_en; - - int xd_timeout; - int sd_timeout; - int ms_timeout; - int mspro_timeout; - - int auto_power_down; - - int sd_ddr_tx_phase; - int mmc_ddr_tx_phase; - int sd_default_tx_phase; - int sd_default_rx_phase; - - int pmos_pwr_on_interval; - int sd_voltage_switch_delay; - int s3_pwr_off_delay; - - int force_clkreq_0; - int ft2_fast_mode; - - int do_delink_before_power_down; - int polling_config; - int sdio_retry_cnt; - - int delink_stage1_step; - int delink_stage2_step; - int delink_stage3_step; - - int auto_delink_in_L1; - int hp_watch_bios_hotplug; - int support_ms_8bit; - - u8 blink_led; - u8 phy_voltage; - u8 max_payload; - - u32 sd_speed_prior; - u32 sd_current_prior; - u32 sd_ctl; -}; - -static inline struct device *rtsx_dev(const struct rtsx_chip *chip) -{ - return &chip->rtsx->pci->dev; -} - -#define rtsx_set_stat(chip, stat) \ -do { \ - if ((stat) != RTSX_STAT_IDLE) { \ - (chip)->idle_counter = 0; \ - } \ - (chip)->rtsx_stat = (enum RTSX_STAT)(stat); \ -} while (0) -#define rtsx_get_stat(chip) ((chip)->rtsx_stat) -#define rtsx_chk_stat(chip, stat) ((chip)->rtsx_stat == (stat)) - -#define RTSX_SET_DELINK(chip) ((chip)->rtsx_flag |= 0x01) -#define RTSX_CLR_DELINK(chip) ((chip)->rtsx_flag &= 0xFE) -#define RTSX_TST_DELINK(chip) ((chip)->rtsx_flag & 0x01) - -#define CHECK_PID(chip, pid) ((chip)->product_id == (pid)) -#define CHECK_BARO_PKG(chip, pkg) ((chip)->baro_pkg == (pkg)) -#define CHECK_LUN_MODE(chip, mode) ((chip)->lun_mode == (mode)) - -/* Power down control */ -#define SSC_PDCTL 0x01 -#define OC_PDCTL 0x02 - -int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl); -int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl); - -void rtsx_enable_card_int(struct rtsx_chip *chip); -void rtsx_enable_bus_int(struct rtsx_chip *chip); -void rtsx_disable_bus_int(struct rtsx_chip *chip); -int rtsx_reset_chip(struct rtsx_chip *chip); -int rtsx_init_chip(struct rtsx_chip *chip); -void rtsx_release_chip(struct rtsx_chip *chip); -void rtsx_polling_func(struct rtsx_chip *chip); -void rtsx_stop_cmd(struct rtsx_chip *chip, int card); -int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data); -int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data); -int rtsx_write_cfg_dw(struct rtsx_chip *chip, - u8 func_no, u16 addr, u32 mask, u32 val); -int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val); -int rtsx_write_cfg_seq(struct rtsx_chip *chip, - u8 func, u16 addr, u8 *buf, int len); -int rtsx_read_cfg_seq(struct rtsx_chip *chip, - u8 func, u16 addr, u8 *buf, int len); -int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val); -int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val); -int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val); -int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val); -int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit); -int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit); -void rtsx_enter_ss(struct rtsx_chip *chip); -void rtsx_exit_ss(struct rtsx_chip *chip); -int rtsx_pre_handle_interrupt(struct rtsx_chip *chip); -void rtsx_enter_L1(struct rtsx_chip *chip); -void rtsx_exit_L1(struct rtsx_chip *chip); -void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat); -void rtsx_enable_aspm(struct rtsx_chip *chip); -void rtsx_disable_aspm(struct rtsx_chip *chip); -int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len); -int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len); -int rtsx_check_chip_exist(struct rtsx_chip *chip); - -#endif /* __REALTEK_RTSX_CHIP_H */ diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c deleted file mode 100644 index c27cffb9ad8f13ed26ccfd56036470307e7df757..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_scsi.c +++ /dev/null @@ -1,3279 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/vmalloc.h> - -#include "rtsx.h" -#include "sd.h" -#include "ms.h" -#include "spi.h" - -void scsi_show_command(struct rtsx_chip *chip) -{ - struct scsi_cmnd *srb = chip->srb; - char *what = NULL; - bool unknown_cmd = false; - int len; - - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: - what = "TEST_UNIT_READY"; - break; - case REZERO_UNIT: - what = "REZERO_UNIT"; - break; - case REQUEST_SENSE: - what = "REQUEST_SENSE"; - break; - case FORMAT_UNIT: - what = "FORMAT_UNIT"; - break; - case READ_BLOCK_LIMITS: - what = "READ_BLOCK_LIMITS"; - break; - case REASSIGN_BLOCKS: - what = "REASSIGN_BLOCKS"; - break; - case READ_6: - what = "READ_6"; - break; - case WRITE_6: - what = "WRITE_6"; - break; - case SEEK_6: - what = "SEEK_6"; - break; - case READ_REVERSE: - what = "READ_REVERSE"; - break; - case WRITE_FILEMARKS: - what = "WRITE_FILEMARKS"; - break; - case SPACE: - what = "SPACE"; - break; - case INQUIRY: - what = "INQUIRY"; - break; - case RECOVER_BUFFERED_DATA: - what = "RECOVER_BUFFERED_DATA"; - break; - case MODE_SELECT: - what = "MODE_SELECT"; - break; - case RESERVE: - what = "RESERVE"; - break; - case RELEASE: - what = "RELEASE"; - break; - case COPY: - what = "COPY"; - break; - case ERASE: - what = "ERASE"; - break; - case MODE_SENSE: - what = "MODE_SENSE"; - break; - case START_STOP: - what = "START_STOP"; - break; - case RECEIVE_DIAGNOSTIC: - what = "RECEIVE_DIAGNOSTIC"; - break; - case SEND_DIAGNOSTIC: - what = "SEND_DIAGNOSTIC"; - break; - case ALLOW_MEDIUM_REMOVAL: - what = "ALLOW_MEDIUM_REMOVAL"; - break; - case SET_WINDOW: - what = "SET_WINDOW"; - break; - case READ_CAPACITY: - what = "READ_CAPACITY"; - break; - case READ_10: - what = "READ_10"; - break; - case WRITE_10: - what = "WRITE_10"; - break; - case SEEK_10: - what = "SEEK_10"; - break; - case WRITE_VERIFY: - what = "WRITE_VERIFY"; - break; - case VERIFY: - what = "VERIFY"; - break; - case SEARCH_HIGH: - what = "SEARCH_HIGH"; - break; - case SEARCH_EQUAL: - what = "SEARCH_EQUAL"; - break; - case SEARCH_LOW: - what = "SEARCH_LOW"; - break; - case SET_LIMITS: - what = "SET_LIMITS"; - break; - case READ_POSITION: - what = "READ_POSITION"; - break; - case SYNCHRONIZE_CACHE: - what = "SYNCHRONIZE_CACHE"; - break; - case LOCK_UNLOCK_CACHE: - what = "LOCK_UNLOCK_CACHE"; - break; - case READ_DEFECT_DATA: - what = "READ_DEFECT_DATA"; - break; - case MEDIUM_SCAN: - what = "MEDIUM_SCAN"; - break; - case COMPARE: - what = "COMPARE"; - break; - case COPY_VERIFY: - what = "COPY_VERIFY"; - break; - case WRITE_BUFFER: - what = "WRITE_BUFFER"; - break; - case READ_BUFFER: - what = "READ_BUFFER"; - break; - case UPDATE_BLOCK: - what = "UPDATE_BLOCK"; - break; - case READ_LONG: - what = "READ_LONG"; - break; - case WRITE_LONG: - what = "WRITE_LONG"; - break; - case CHANGE_DEFINITION: - what = "CHANGE_DEFINITION"; - break; - case WRITE_SAME: - what = "WRITE_SAME"; - break; - case GPCMD_READ_SUBCHANNEL: - what = "READ SUBCHANNEL"; - break; - case READ_TOC: - what = "READ_TOC"; - break; - case GPCMD_READ_HEADER: - what = "READ HEADER"; - break; - case GPCMD_PLAY_AUDIO_10: - what = "PLAY AUDIO (10)"; - break; - case GPCMD_PLAY_AUDIO_MSF: - what = "PLAY AUDIO MSF"; - break; - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - what = "GET EVENT/STATUS NOTIFICATION"; - break; - case GPCMD_PAUSE_RESUME: - what = "PAUSE/RESUME"; - break; - case LOG_SELECT: - what = "LOG_SELECT"; - break; - case LOG_SENSE: - what = "LOG_SENSE"; - break; - case GPCMD_STOP_PLAY_SCAN: - what = "STOP PLAY/SCAN"; - break; - case GPCMD_READ_DISC_INFO: - what = "READ DISC INFORMATION"; - break; - case GPCMD_READ_TRACK_RZONE_INFO: - what = "READ TRACK INFORMATION"; - break; - case GPCMD_RESERVE_RZONE_TRACK: - what = "RESERVE TRACK"; - break; - case GPCMD_SEND_OPC: - what = "SEND OPC"; - break; - case MODE_SELECT_10: - what = "MODE_SELECT_10"; - break; - case GPCMD_REPAIR_RZONE_TRACK: - what = "REPAIR TRACK"; - break; - case 0x59: - what = "READ MASTER CUE"; - break; - case MODE_SENSE_10: - what = "MODE_SENSE_10"; - break; - case GPCMD_CLOSE_TRACK: - what = "CLOSE TRACK/SESSION"; - break; - case 0x5C: - what = "READ BUFFER CAPACITY"; - break; - case 0x5D: - what = "SEND CUE SHEET"; - break; - case GPCMD_BLANK: - what = "BLANK"; - break; - case REPORT_LUNS: - what = "REPORT LUNS"; - break; - case MOVE_MEDIUM: - what = "MOVE_MEDIUM or PLAY AUDIO (12)"; - break; - case READ_12: - what = "READ_12"; - break; - case WRITE_12: - what = "WRITE_12"; - break; - case WRITE_VERIFY_12: - what = "WRITE_VERIFY_12"; - break; - case SEARCH_HIGH_12: - what = "SEARCH_HIGH_12"; - break; - case SEARCH_EQUAL_12: - what = "SEARCH_EQUAL_12"; - break; - case SEARCH_LOW_12: - what = "SEARCH_LOW_12"; - break; - case SEND_VOLUME_TAG: - what = "SEND_VOLUME_TAG"; - break; - case READ_ELEMENT_STATUS: - what = "READ_ELEMENT_STATUS"; - break; - case GPCMD_READ_CD_MSF: - what = "READ CD MSF"; - break; - case GPCMD_SCAN: - what = "SCAN"; - break; - case GPCMD_SET_SPEED: - what = "SET CD SPEED"; - break; - case GPCMD_MECHANISM_STATUS: - what = "MECHANISM STATUS"; - break; - case GPCMD_READ_CD: - what = "READ CD"; - break; - case 0xE1: - what = "WRITE CONTINUE"; - break; - case WRITE_LONG_2: - what = "WRITE_LONG_2"; - break; - case VENDOR_CMND: - what = "Realtek's vendor command"; - break; - default: - what = "(unknown command)"; - unknown_cmd = true; - break; - } - - if (srb->cmnd[0] != TEST_UNIT_READY) - dev_dbg(rtsx_dev(chip), "Command %s (%d bytes)\n", - what, srb->cmd_len); - - if (unknown_cmd) { - len = min_t(unsigned short, srb->cmd_len, 16); - dev_dbg(rtsx_dev(chip), "%*ph\n", len, srb->cmnd); - } -} - -void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type) -{ - switch (sense_type) { - case SENSE_TYPE_MEDIA_CHANGE: - set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_NOT_PRESENT: - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_LBA_OVER_RANGE: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_WRITE_PROTECT: - set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0); - break; - - case SENSE_TYPE_MEDIA_WRITE_ERR: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0); - break; - - case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD: - set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0, - ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); - break; - - case SENSE_TYPE_FORMAT_IN_PROGRESS: - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0); - break; - - case SENSE_TYPE_FORMAT_CMD_FAILED: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0); - break; - -#ifdef SUPPORT_MAGIC_GATE - case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0); - break; - - case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN: - set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0); - break; - - case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM: - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0); - break; - - case SENSE_TYPE_MG_WRITE_ERR: - set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0); - break; -#endif - -#ifdef SUPPORT_SD_LOCK - case SENSE_TYPE_MEDIA_READ_FORBIDDEN: - set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0); - break; -#endif - - case SENSE_TYPE_NO_SENSE: - default: - set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0); - break; - } -} - -void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0, - u16 sns_key_info1) -{ - struct sense_data_t *sense = &chip->sense_buffer[lun]; - - sense->err_code = err_code; - sense->sense_key = sense_key; - sense->info[0] = (u8)(info >> 24); - sense->info[1] = (u8)(info >> 16); - sense->info[2] = (u8)(info >> 8); - sense->info[3] = (u8)info; - - sense->ad_sense_len = sizeof(struct sense_data_t) - 8; - sense->asc = asc; - sense->ascq = ascq; - if (sns_key_info0 != 0) { - sense->sns_key_info[0] = SKSV | sns_key_info0; - sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 4; - sense->sns_key_info[2] = sns_key_info1 & 0x0f; - } -} - -static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (!(CHK_BIT(chip->lun_mc, lun))) { - SET_BIT(chip->lun_mc, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - -#ifdef SUPPORT_SD_LOCK - if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) { - struct sd_info *sd_card = &chip->sd_card; - - if (sd_card->sd_lock_notify) { - sd_card->sd_lock_notify = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } else if (sd_card->sd_lock_status & SD_LOCKED) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_READ_FORBIDDEN); - return TRANSPORT_FAILED; - } - } -#endif - - return TRANSPORT_GOOD; -} - -static unsigned char formatter_inquiry_str[20] = { - 'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K', -#ifdef SUPPORT_MAGIC_GATE - '-', 'M', 'G', /* Byte[47:49] */ -#else - 0x20, 0x20, 0x20, /* Byte[47:49] */ -#endif - -#ifdef SUPPORT_MAGIC_GATE - 0x0B, /* Byte[50]: MG, MS, MSPro, MSXC */ -#else - 0x09, /* Byte[50]: MS, MSPro, MSXC */ -#endif - 0x00, /* Byte[51]: Category Specific Commands */ - 0x00, /* Byte[52]: Access Control and feature */ - 0x20, 0x20, 0x20, /* Byte[53:55] */ -}; - -static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - char *inquiry_default = (char *)"Generic-xD/SD/M.S. 1.00"; - char *inquiry_sdms = (char *)"Generic-SD/MemoryStick 1.00"; - char *inquiry_sd = (char *)"Generic-SD/MMC 1.00"; - char *inquiry_ms = (char *)"Generic-MemoryStick 1.00"; - char *inquiry_string; - unsigned char sendbytes; - unsigned char *buf; - u8 card = get_lun_card(chip, lun); - bool pro_formatter_flag = false; - unsigned char inquiry_buf[] = { - QULIFIRE | DRCT_ACCESS_DEV, - RMB_DISC | 0x0D, - 0x00, - 0x01, - 0x1f, - 0x02, - 0, - REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE, - }; - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - if (chip->lun2card[lun] == SD_CARD) - inquiry_string = inquiry_sd; - else - inquiry_string = inquiry_ms; - - } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) { - inquiry_string = inquiry_sdms; - } else { - inquiry_string = inquiry_default; - } - - buf = vmalloc(scsi_bufflen(srb)); - if (!buf) - return TRANSPORT_ERROR; - -#ifdef SUPPORT_MAGIC_GATE - if (chip->mspro_formatter_enable && - (chip->lun2card[lun] & MS_CARD)) -#else - if (chip->mspro_formatter_enable) -#endif - if (!card || card == MS_CARD) - pro_formatter_flag = true; - - if (pro_formatter_flag) { - if (scsi_bufflen(srb) < 56) - sendbytes = (unsigned char)(scsi_bufflen(srb)); - else - sendbytes = 56; - - } else { - if (scsi_bufflen(srb) < 36) - sendbytes = (unsigned char)(scsi_bufflen(srb)); - else - sendbytes = 36; - } - - if (sendbytes > 8) { - memcpy(buf, inquiry_buf, 8); - memcpy(buf + 8, inquiry_string, min(sendbytes, 36) - 8); - if (pro_formatter_flag) { - /* Additional Length */ - buf[4] = 0x33; - } - } else { - memcpy(buf, inquiry_buf, sendbytes); - } - - if (pro_formatter_flag) { - if (sendbytes > 36) - memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36); - } - - scsi_set_resid(srb, 0); - - rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - scsi_set_resid(srb, scsi_bufflen(srb)); - - if (srb->cmnd[1] == 1) - return TRANSPORT_GOOD; - - switch (srb->cmnd[0x4]) { - case STOP_MEDIUM: - /* Media disabled */ - return TRANSPORT_GOOD; - - case UNLOAD_MEDIUM: - /* Media shall be unload */ - if (check_card_ready(chip, lun)) - eject_card(chip, lun); - return TRANSPORT_GOOD; - - case MAKE_MEDIUM_READY: - case LOAD_MEDIUM: - if (check_card_ready(chip, lun)) - return TRANSPORT_GOOD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - - break; - } - - return TRANSPORT_ERROR; -} - -static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int prevent; - - prevent = srb->cmnd[4] & 0x1; - - scsi_set_resid(srb, 0); - - if (prevent) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sense_data_t *sense; - unsigned int lun = SCSI_LUN(srb); - struct ms_info *ms_card = &chip->ms_card; - unsigned char *tmp, *buf; - - sense = &chip->sense_buffer[lun]; - - if ((get_lun_card(chip, lun) == MS_CARD) && - ms_card->pro_under_formatting) { - if (ms_card->format_status == FORMAT_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - ms_card->pro_under_formatting = 0; - ms_card->progress = 0; - } else if (ms_card->format_status == FORMAT_IN_PROGRESS) { - /* Logical Unit Not Ready Format in Progress */ - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16)(ms_card->progress)); - } else { - /* Format Command Failed */ - set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); - ms_card->pro_under_formatting = 0; - ms_card->progress = 0; - } - - rtsx_set_stat(chip, RTSX_STAT_RUN); - } - - buf = vmalloc(scsi_bufflen(srb)); - if (!buf) - return TRANSPORT_ERROR; - - tmp = (unsigned char *)sense; - memcpy(buf, tmp, scsi_bufflen(srb)); - - rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); - vfree(buf); - - scsi_set_resid(srb, 0); - /* Reset Sense Data */ - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - return TRANSPORT_GOOD; -} - -static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd, - int lun, u8 *buf, int buf_len) -{ - struct ms_info *ms_card = &chip->ms_card; - int sys_info_offset; - int data_size = buf_len; - bool support_format = false; - int i = 0; - - if (cmd == MODE_SENSE) { - sys_info_offset = 8; - if (data_size > 0x68) - data_size = 0x68; - - buf[i++] = 0x67; /* Mode Data Length */ - } else { - sys_info_offset = 12; - if (data_size > 0x6C) - data_size = 0x6C; - - buf[i++] = 0x00; /* Mode Data Length (MSB) */ - buf[i++] = 0x6A; /* Mode Data Length (LSB) */ - } - - /* Medium Type Code */ - if (check_card_ready(chip, lun)) { - if (CHK_MSXC(ms_card)) { - support_format = true; - buf[i++] = 0x40; - } else if (CHK_MSPRO(ms_card)) { - support_format = true; - buf[i++] = 0x20; - } else { - buf[i++] = 0x10; - } - - /* WP */ - if (check_card_wp(chip, lun)) - buf[i++] = 0x80; - else - buf[i++] = 0x00; - - } else { - buf[i++] = 0x00; /* MediaType */ - buf[i++] = 0x00; /* WP */ - } - - buf[i++] = 0x00; /* Reserved */ - - if (cmd == MODE_SENSE_10) { - buf[i++] = 0x00; /* Reserved */ - buf[i++] = 0x00; /* Block descriptor length(MSB) */ - buf[i++] = 0x00; /* Block descriptor length(LSB) */ - - /* The Following Data is the content of "Page 0x20" */ - if (data_size >= 9) - buf[i++] = 0x20; /* Page Code */ - if (data_size >= 10) - buf[i++] = 0x62; /* Page Length */ - if (data_size >= 11) - buf[i++] = 0x00; /* No Access Control */ - if (data_size >= 12) { - if (support_format) - buf[i++] = 0xC0; /* SF, SGM */ - else - buf[i++] = 0x00; - } - } else { - /* The Following Data is the content of "Page 0x20" */ - if (data_size >= 5) - buf[i++] = 0x20; /* Page Code */ - if (data_size >= 6) - buf[i++] = 0x62; /* Page Length */ - if (data_size >= 7) - buf[i++] = 0x00; /* No Access Control */ - if (data_size >= 8) { - if (support_format) - buf[i++] = 0xC0; /* SF, SGM */ - else - buf[i++] = 0x00; - } - } - - if (data_size > sys_info_offset) { - /* 96 Bytes Attribute Data */ - int len = data_size - sys_info_offset; - - len = (len < 96) ? len : 96; - - memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len); - } -} - -static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - unsigned int data_size; - int status; - bool pro_formatter_flag; - unsigned char page_code, *buf; - u8 card = get_lun_card(chip, lun); - -#ifndef SUPPORT_MAGIC_GATE - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - scsi_set_resid(srb, scsi_bufflen(srb)); - return TRANSPORT_FAILED; - } -#endif - - pro_formatter_flag = false; - data_size = 8; -#ifdef SUPPORT_MAGIC_GATE - if ((chip->lun2card[lun] & MS_CARD)) { - if (!card || card == MS_CARD) { - data_size = 108; - if (chip->mspro_formatter_enable) - pro_formatter_flag = true; - } - } -#else - if (card == MS_CARD) { - if (chip->mspro_formatter_enable) { - pro_formatter_flag = true; - data_size = 108; - } - } -#endif - - buf = kmalloc(data_size, GFP_KERNEL); - if (!buf) - return TRANSPORT_ERROR; - - page_code = srb->cmnd[2] & 0x3f; - - if (page_code == 0x3F || page_code == 0x1C || - page_code == 0x00 || - (pro_formatter_flag && page_code == 0x20)) { - if (srb->cmnd[0] == MODE_SENSE) { - if (page_code == 0x3F || page_code == 0x20) { - ms_mode_sense(chip, srb->cmnd[0], - lun, buf, data_size); - } else { - data_size = 4; - buf[0] = 0x03; - buf[1] = 0x00; - if (check_card_wp(chip, lun)) - buf[2] = 0x80; - else - buf[2] = 0x00; - - buf[3] = 0x00; - } - } else { - if (page_code == 0x3F || page_code == 0x20) { - ms_mode_sense(chip, srb->cmnd[0], - lun, buf, data_size); - } else { - data_size = 8; - buf[0] = 0x00; - buf[1] = 0x06; - buf[2] = 0x00; - if (check_card_wp(chip, lun)) - buf[3] = 0x80; - else - buf[3] = 0x00; - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x00; - buf[7] = 0x00; - } - } - status = TRANSPORT_GOOD; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - scsi_set_resid(srb, scsi_bufflen(srb)); - status = TRANSPORT_FAILED; - } - - if (status == TRANSPORT_GOOD) { - unsigned int len = min_t(unsigned int, scsi_bufflen(srb), - data_size); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - } - kfree(buf); - - return status; -} - -static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &chip->sd_card; -#endif - unsigned int lun = SCSI_LUN(srb); - int retval; - u32 start_sec; - u16 sec_cnt; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (!(CHK_BIT(chip->lun_mc, lun))) { - SET_BIT(chip->lun_mc, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_erase_status) { - /* Accessing to any card is forbidden - * until the erase procedure of SD is completed - */ - dev_dbg(rtsx_dev(chip), "SD card being erased!\n"); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN); - return TRANSPORT_FAILED; - } - - if (get_lun_card(chip, lun) == SD_CARD) { - if (sd_card->sd_lock_status & SD_LOCKED) { - dev_dbg(rtsx_dev(chip), "SD card locked!\n"); - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_READ_FORBIDDEN); - return TRANSPORT_FAILED; - } - } -#endif - - if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) { - start_sec = ((u32)srb->cmnd[2] << 24) | - ((u32)srb->cmnd[3] << 16) | - ((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]); - sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { - start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) | - ((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]); - sec_cnt = srb->cmnd[4]; - if (sec_cnt == 0) - sec_cnt = 256; - } else if ((srb->cmnd[0] == VENDOR_CMND) && - (srb->cmnd[1] == SCSI_APP_CMD) && - ((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) { - start_sec = ((u32)srb->cmnd[4] << 24) | - ((u32)srb->cmnd[5] << 16) | - ((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]); - sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10]; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - /* In some test, we will receive a start_sec like 0xFFFFFFFF. - * In this situation, start_sec + sec_cnt will overflow, so we - * need to judge start_sec at first - */ - if (start_sec > get_card_size(chip, lun) || - ((start_sec + sec_cnt) > get_card_size(chip, lun))) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE); - return TRANSPORT_FAILED; - } - - if (sec_cnt == 0) { - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - } - - if (chip->rw_fail_cnt[lun] == 3) { - dev_dbg(rtsx_dev(chip), "read/write fail three times in succession\n"); - if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - - return TRANSPORT_FAILED; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - if (check_card_wp(chip, lun)) { - dev_dbg(rtsx_dev(chip), "Write protected card!\n"); - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_PROTECT); - return TRANSPORT_FAILED; - } - } - - retval = card_rw(srb, chip, start_sec, sec_cnt); - if (retval != STATUS_SUCCESS) { - if (chip->need_release & chip->lun2card[lun]) { - chip->rw_fail_cnt[lun] = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - } else { - chip->rw_fail_cnt[lun]++; - if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type - (chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - } - retval = TRANSPORT_FAILED; - goto exit; - } else { - chip->rw_fail_cnt[lun] = 0; - retval = TRANSPORT_GOOD; - } - - scsi_set_resid(srb, 0); - -exit: - return retval; -} - -static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned char *buf; - unsigned int lun = SCSI_LUN(srb); - unsigned int buf_len; - u8 card = get_lun_card(chip, lun); - u32 card_size; - int desc_cnt; - int i = 0; - - if (!check_card_ready(chip, lun)) { - if (!chip->mspro_formatter_enable) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - } - - buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12; - - buf = kmalloc(buf_len, GFP_KERNEL); - if (!buf) - return TRANSPORT_ERROR; - - buf[i++] = 0; - buf[i++] = 0; - buf[i++] = 0; - - /* Capacity List Length */ - if (buf_len > 12 && chip->mspro_formatter_enable && - (chip->lun2card[lun] & MS_CARD) && - (!card || card == MS_CARD)) { - buf[i++] = 0x10; - desc_cnt = 2; - } else { - buf[i++] = 0x08; - desc_cnt = 1; - } - - while (desc_cnt) { - if (check_card_ready(chip, lun)) { - card_size = get_card_size(chip, lun); - buf[i++] = (unsigned char)(card_size >> 24); - buf[i++] = (unsigned char)(card_size >> 16); - buf[i++] = (unsigned char)(card_size >> 8); - buf[i++] = (unsigned char)card_size; - - if (desc_cnt == 2) - buf[i++] = 2; - else - buf[i++] = 0; - } else { - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - buf[i++] = 0xFF; - - if (desc_cnt == 2) - buf[i++] = 3; - else - buf[i++] = 0; - } - - buf[i++] = 0x00; - buf[i++] = 0x02; - buf[i++] = 0x00; - - desc_cnt--; - } - - buf_len = min_t(unsigned int, scsi_bufflen(srb), buf_len); - rtsx_stor_set_xfer_buf(buf, buf_len, srb); - kfree(buf); - - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned char *buf; - unsigned int lun = SCSI_LUN(srb); - u32 card_size; - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (!(CHK_BIT(chip->lun_mc, lun))) { - SET_BIT(chip->lun_mc, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - buf = kmalloc(8, GFP_KERNEL); - if (!buf) - return TRANSPORT_ERROR; - - card_size = get_card_size(chip, lun); - buf[0] = (unsigned char)((card_size - 1) >> 24); - buf[1] = (unsigned char)((card_size - 1) >> 16); - buf[2] = (unsigned char)((card_size - 1) >> 8); - buf[3] = (unsigned char)(card_size - 1); - - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x02; - buf[7] = 0x00; - - rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); - kfree(buf); - - scsi_set_resid(srb, 0); - - return TRANSPORT_GOOD; -} - -static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short len, i; - int retval; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len; i++) { - retval = spi_read_eeprom(chip, i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - } - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short len, i; - int retval; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - if (len == 511) { - retval = spi_erase_eeprom_chip(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } else { - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), - len); - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - for (i = 0; i < len; i++) { - retval = spi_write_eeprom(chip, i, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr, len, i; - int retval; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3]; - len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (addr < 0xFC00) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len; i++) { - retval = rtsx_read_register(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - } - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr, len, i; - int retval; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3]; - len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (addr < 0xFC00) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len; i++) { - retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (get_lun_card(chip, lun) != SD_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - scsi_set_resid(srb, 0); - rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb); - - return TRANSPORT_GOOD; -} - -static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - u8 gpio = srb->cmnd[2]; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - if (gpio > 3) - gpio = 1; - toggle_gpio(chip, gpio); - - return TRANSPORT_GOOD; -} - -static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - u8 addr, buf[4]; - u32 val; - unsigned int len; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = srb->cmnd[4]; - - val = rtsx_readl(chip, addr); - dev_dbg(rtsx_dev(chip), "Host register (0x%x): 0x%x\n", addr, val); - - buf[0] = (u8)(val >> 24); - buf[1] = (u8)(val >> 16); - buf[2] = (u8)(val >> 8); - buf[3] = (u8)val; - - len = min_t(unsigned int, scsi_bufflen(srb), 4); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - return TRANSPORT_GOOD; -} - -static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - u8 addr, buf[4]; - u32 val; - unsigned int len; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = srb->cmnd[4]; - - len = min_t(unsigned int, scsi_bufflen(srb), 4); - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2] - << 8) | buf[3]; - - rtsx_writel(chip, addr, val); - - return TRANSPORT_GOOD; -} - -static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - if (srb->cmnd[3] == 1) { - /* Variable Clock */ - struct xd_info *xd_card = &chip->xd_card; - struct sd_info *sd_card = &chip->sd_card; - struct ms_info *ms_card = &chip->ms_card; - - switch (srb->cmnd[4]) { - case XD_CARD: - xd_card->xd_clock = srb->cmnd[5]; - break; - - case SD_CARD: - sd_card->sd_clock = srb->cmnd[5]; - break; - - case MS_CARD: - ms_card->ms_clock = srb->cmnd[5]; - break; - - default: - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - } else if (srb->cmnd[3] == 2) { - if (srb->cmnd[4]) { - chip->blink_led = 1; - } else { - int retval; - - chip->blink_led = 0; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && - (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - turn_off_led(chip, LED_GPIO); - } - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - - if (srb->cmnd[3] == 1) { - struct xd_info *xd_card = &chip->xd_card; - struct sd_info *sd_card = &chip->sd_card; - struct ms_info *ms_card = &chip->ms_card; - u8 tmp; - - switch (srb->cmnd[4]) { - case XD_CARD: - tmp = (u8)(xd_card->xd_clock); - break; - - case SD_CARD: - tmp = (u8)(sd_card->sd_clock); - break; - - case MS_CARD: - tmp = (u8)(ms_card->ms_clock); - break; - - default: - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - rtsx_stor_set_xfer_buf(&tmp, 1, srb); - } else if (srb->cmnd[3] == 2) { - u8 tmp = chip->blink_led; - - rtsx_stor_set_xfer_buf(&tmp, 1, srb); - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - unsigned int lun = SCSI_LUN(srb); - u16 len; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; - len = min_t(u16, len, scsi_bufflen(srb)); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) - dev_dbg(rtsx_dev(chip), "Read from device\n"); - else - dev_dbg(rtsx_dev(chip), "Write to device\n"); - - retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len, - scsi_sg_count(srb), srb->sc_data_direction, - 1000); - if (retval < 0) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - - return TRANSPORT_FAILED; - } - scsi_set_resid(srb, 0); - - return TRANSPORT_GOOD; -} - -static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - struct ms_info *ms_card = &chip->ms_card; - int buf_len; - unsigned int lun = SCSI_LUN(srb); - u8 card = get_lun_card(chip, lun); - u8 status[32]; -#ifdef SUPPORT_OCP - u8 oc_now_mask = 0, oc_ever_mask = 0; -#endif - - memset(status, 0, 32); - - status[0] = (u8)(chip->product_id); - status[1] = chip->ic_version; - - if (chip->auto_delink_en) - status[2] = 0x10; - else - status[2] = 0x00; - - status[3] = 20; - status[4] = 10; - status[5] = 05; - status[6] = 21; - - if (chip->card_wp) - status[7] = 0x20; - else - status[7] = 0x00; - -#ifdef SUPPORT_OCP - status[8] = 0; - if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && - chip->lun2card[lun] == MS_CARD) { - oc_now_mask = MS_OC_NOW; - oc_ever_mask = MS_OC_EVER; - } else { - oc_now_mask = SD_OC_NOW; - oc_ever_mask = SD_OC_EVER; - } - - if (chip->ocp_stat & oc_now_mask) - status[8] |= 0x02; - - if (chip->ocp_stat & oc_ever_mask) - status[8] |= 0x01; -#endif - - if (card == SD_CARD) { - if (CHK_SD(sd_card)) { - if (CHK_SD_HCXC(sd_card)) { - if (sd_card->capacity > 0x4000000) - status[0x0E] = 0x02; - else - status[0x0E] = 0x01; - } else { - status[0x0E] = 0x00; - } - - if (CHK_SD_SDR104(sd_card)) - status[0x0F] = 0x03; - else if (CHK_SD_DDR50(sd_card)) - status[0x0F] = 0x04; - else if (CHK_SD_SDR50(sd_card)) - status[0x0F] = 0x02; - else if (CHK_SD_HS(sd_card)) - status[0x0F] = 0x01; - else - status[0x0F] = 0x00; - } else { - if (CHK_MMC_SECTOR_MODE(sd_card)) - status[0x0E] = 0x01; - else - status[0x0E] = 0x00; - - if (CHK_MMC_DDR52(sd_card)) - status[0x0F] = 0x03; - else if (CHK_MMC_52M(sd_card)) - status[0x0F] = 0x02; - else if (CHK_MMC_26M(sd_card)) - status[0x0F] = 0x01; - else - status[0x0F] = 0x00; - } - } else if (card == MS_CARD) { - if (CHK_MSPRO(ms_card)) { - if (CHK_MSXC(ms_card)) - status[0x0E] = 0x01; - else - status[0x0E] = 0x00; - - if (CHK_HG8BIT(ms_card)) - status[0x0F] = 0x01; - else - status[0x0F] = 0x00; - } - } - -#ifdef SUPPORT_SD_LOCK - if (card == SD_CARD) { - status[0x17] = 0x80; - if (sd_card->sd_erase_status) - status[0x17] |= 0x01; - if (sd_card->sd_lock_status & SD_LOCKED) { - status[0x17] |= 0x02; - status[0x07] |= 0x40; - } - if (sd_card->sd_lock_status & SD_PWD_EXIST) - status[0x17] |= 0x04; - } else { - status[0x17] = 0x00; - } - - dev_dbg(rtsx_dev(chip), "status[0x17] = 0x%x\n", status[0x17]); -#endif - - status[0x18] = 0x8A; - status[0x1A] = 0x28; -#ifdef SUPPORT_SD_LOCK - status[0x1F] = 0x01; -#endif - - buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status)); - rtsx_stor_set_xfer_buf(status, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int phy_debug_mode; - int retval; - u16 reg; - - if (!CHECK_PID(chip, 0x5208)) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - phy_debug_mode = (int)(srb->cmnd[3]); - - if (phy_debug_mode) { - chip->phy_debug_mode = 1; - retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - rtsx_disable_bus_int(chip); - - retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - reg |= 0x0001; - retval = rtsx_write_phy_register(chip, 0x1C, reg); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - } else { - chip->phy_debug_mode = 0; - retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - rtsx_enable_bus_int(chip); - - retval = rtsx_read_phy_register(chip, 0x1C, ®); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - reg &= 0xFFFE; - retval = rtsx_write_phy_register(chip, 0x1C, reg); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval = STATUS_SUCCESS; - unsigned int lun = SCSI_LUN(srb); - u8 cmd_type, mask, value, idx; - u16 addr; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - switch (srb->cmnd[3]) { - case INIT_BATCHCMD: - rtsx_init_cmd(chip); - break; - - case ADD_BATCHCMD: - cmd_type = srb->cmnd[4]; - if (cmd_type > 2) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - addr = (srb->cmnd[5] << 8) | srb->cmnd[6]; - mask = srb->cmnd[7]; - value = srb->cmnd[8]; - rtsx_add_cmd(chip, cmd_type, addr, mask, value); - break; - - case SEND_BATCHCMD: - retval = rtsx_send_cmd(chip, 0, 1000); - break; - - case GET_BATCHRSP: - idx = srb->cmnd[4]; - value = *(rtsx_get_cmd_data(chip) + idx); - if (scsi_bufflen(srb) < 1) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - rtsx_stor_set_xfer_buf(&value, 1, srb); - scsi_set_resid(srb, 0); - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - switch (srb->cmnd[3]) { - case INIT_BATCHCMD: - case ADD_BATCHCMD: - case SEND_BATCHCMD: - case GET_BATCHRSP: - return rw_mem_cmd_buf(srb, chip); - default: - return TRANSPORT_ERROR; - } -} - -static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr, len, i; - int retval; - u8 *buf; - u16 val; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; - - if (len % 2) - len -= len % 2; - - if (len) { - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len / 2; i++) { - retval = rtsx_read_phy_register(chip, addr + i, &val); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type - (chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - buf[2 * i] = (u8)(val >> 8); - buf[2 * i + 1] = (u8)val; - } - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), - len); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr, len, i; - int retval; - u8 *buf; - u16 val; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; - - if (len % 2) - len -= len % 2; - - if (len) { - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), - len); - - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len / 2; i++) { - val = ((u16)buf[2 * i] << 8) | buf[2 * i + 1]; - retval = rtsx_write_phy_register(chip, addr + i, val); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } - - vfree(buf); - } - - return TRANSPORT_GOOD; -} - -static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr; - int retval; - u8 mode; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - mode = srb->cmnd[3]; - addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - - if (mode == 0) { - retval = spi_erase_eeprom_chip(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } else if (mode == 1) { - retval = spi_erase_eeprom_byte(chip, addr); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } else { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return TRANSPORT_GOOD; -} - -static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr, len, i; - int retval; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; - - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len; i++) { - retval = spi_read_eeprom(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - } - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned short addr, len, i; - int retval; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5]; - len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7]; - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len; i++) { - retval = spi_write_eeprom(chip, addr + i, buf[i]); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - return TRANSPORT_FAILED; - } - } - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - u8 addr, len, i; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = srb->cmnd[4]; - len = srb->cmnd[5]; - - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - for (i = 0; i < len; i++) { - retval = rtsx_read_efuse(chip, addr + i, buf + i); - if (retval != STATUS_SUCCESS) { - vfree(buf); - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - } - - len = (u8)min_t(unsigned int, scsi_bufflen(srb), len); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval, result = TRANSPORT_GOOD; - u16 val; - u8 addr, len, i; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - addr = srb->cmnd[4]; - len = srb->cmnd[5]; - - len = (u8)min_t(unsigned int, scsi_bufflen(srb), len); - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - retval = rtsx_force_power_on(chip, SSC_PDCTL); - if (retval != STATUS_SUCCESS) { - vfree(buf); - return TRANSPORT_ERROR; - } - - if (chip->asic_code) { - retval = rtsx_read_phy_register(chip, 0x08, &val); - if (retval != STATUS_SUCCESS) { - vfree(buf); - return TRANSPORT_ERROR; - } - - retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_OFF); - if (retval != STATUS_SUCCESS) { - vfree(buf); - return TRANSPORT_ERROR; - } - - wait_timeout(600); - - retval = rtsx_write_phy_register(chip, 0x08, - 0x4C00 | chip->phy_voltage); - if (retval != STATUS_SUCCESS) { - vfree(buf); - return TRANSPORT_ERROR; - } - - retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_ON); - if (retval != STATUS_SUCCESS) { - vfree(buf); - return TRANSPORT_ERROR; - } - - wait_timeout(600); - } - - retval = card_power_on(chip, SPI_CARD); - if (retval != STATUS_SUCCESS) { - vfree(buf); - return TRANSPORT_ERROR; - } - - wait_timeout(50); - - for (i = 0; i < len; i++) { - retval = rtsx_write_efuse(chip, addr + i, buf[i]); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_WRITE_ERR); - result = TRANSPORT_FAILED; - goto exit; - } - } - -exit: - vfree(buf); - - retval = card_power_off(chip, SPI_CARD); - if (retval != STATUS_SUCCESS) - return TRANSPORT_ERROR; - - if (chip->asic_code) { - retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_OFF); - if (retval != STATUS_SUCCESS) - return TRANSPORT_ERROR; - - wait_timeout(600); - - retval = rtsx_write_phy_register(chip, 0x08, val); - if (retval != STATUS_SUCCESS) - return TRANSPORT_ERROR; - - retval = rtsx_write_register(chip, PWR_GATE_CTRL, - LDO3318_PWR_MASK, LDO_ON); - if (retval != STATUS_SUCCESS) - return TRANSPORT_ERROR; - } - - return result; -} - -static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - bool func_max; - u8 func; - u16 addr, len; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - func = srb->cmnd[3]; - addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; - len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7]; - - dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x, len = %d\n", - __func__, func, addr, len); - - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) - func_max = true; - else - func_max = false; - - if (func > func_max) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - retval = rtsx_read_cfg_seq(chip, func, addr, buf, len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - vfree(buf); - return TRANSPORT_FAILED; - } - - len = (u16)min_t(unsigned int, scsi_bufflen(srb), len); - rtsx_stor_set_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - bool func_max; - u8 func; - u16 addr, len; - u8 *buf; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - func = srb->cmnd[3]; - addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; - len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7]; - - dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x\n", - __func__, func, addr); - - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) - func_max = true; - else - func_max = false; - - if (func > func_max) { - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len); - buf = vmalloc(len); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - len); - - retval = rtsx_write_cfg_seq(chip, func, addr, buf, len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR); - vfree(buf); - return TRANSPORT_FAILED; - } - - vfree(buf); - - return TRANSPORT_GOOD; -} - -static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int result; - - switch (srb->cmnd[2]) { - case PP_READ10: - case PP_WRITE10: - result = read_write(srb, chip); - break; - - case READ_HOST_REG: - result = read_host_reg(srb, chip); - break; - - case WRITE_HOST_REG: - result = write_host_reg(srb, chip); - break; - - case GET_VAR: - result = get_variable(srb, chip); - break; - - case SET_VAR: - result = set_variable(srb, chip); - break; - - case DMA_READ: - case DMA_WRITE: - result = dma_access_ring_buffer(srb, chip); - break; - - case READ_PHY: - result = read_phy_register(srb, chip); - break; - - case WRITE_PHY: - result = write_phy_register(srb, chip); - break; - - case ERASE_EEPROM2: - result = erase_eeprom2(srb, chip); - break; - - case READ_EEPROM2: - result = read_eeprom2(srb, chip); - break; - - case WRITE_EEPROM2: - result = write_eeprom2(srb, chip); - break; - - case READ_EFUSE: - result = read_efuse(srb, chip); - break; - - case WRITE_EFUSE: - result = write_efuse(srb, chip); - break; - - case READ_CFG: - result = read_cfg_byte(srb, chip); - break; - - case WRITE_CFG: - result = write_cfg_byte(srb, chip); - break; - - case SET_CHIP_MODE: - result = set_chip_mode(srb, chip); - break; - - case SUIT_CMD: - result = suit_cmd(srb, chip); - break; - - case GET_DEV_STATUS: - result = get_dev_status(srb, chip); - break; - - default: - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return result; -} - -static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - u8 rtsx_status[16]; - int buf_len; - unsigned int lun = SCSI_LUN(srb); - - rtsx_status[0] = (u8)(chip->vendor_id >> 8); - rtsx_status[1] = (u8)(chip->vendor_id); - - rtsx_status[2] = (u8)(chip->product_id >> 8); - rtsx_status[3] = (u8)(chip->product_id); - - rtsx_status[4] = (u8)lun; - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - if (chip->lun2card[lun] == SD_CARD) - rtsx_status[5] = 2; - else - rtsx_status[5] = 3; - } else { - if (chip->card_exist) { - if (chip->card_exist & XD_CARD) - rtsx_status[5] = 4; - else if (chip->card_exist & SD_CARD) - rtsx_status[5] = 2; - else if (chip->card_exist & MS_CARD) - rtsx_status[5] = 3; - else - rtsx_status[5] = 7; - } else { - rtsx_status[5] = 7; - } - } - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) - rtsx_status[6] = 2; - else - rtsx_status[6] = 1; - - rtsx_status[7] = (u8)(chip->product_id); - rtsx_status[8] = chip->ic_version; - - if (check_card_exist(chip, lun)) - rtsx_status[9] = 1; - else - rtsx_status[9] = 0; - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) - rtsx_status[10] = 0; - else - rtsx_status[10] = 1; - - if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) { - if (chip->lun2card[lun] == SD_CARD) - rtsx_status[11] = SD_CARD; - else - rtsx_status[11] = MS_CARD; - } else { - rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD; - } - - if (check_card_ready(chip, lun)) - rtsx_status[12] = 1; - else - rtsx_status[12] = 0; - - if (get_lun_card(chip, lun) == XD_CARD) { - rtsx_status[13] = 0x40; - } else if (get_lun_card(chip, lun) == SD_CARD) { - struct sd_info *sd_card = &chip->sd_card; - - rtsx_status[13] = 0x20; - if (CHK_SD(sd_card)) { - if (CHK_SD_HCXC(sd_card)) - rtsx_status[13] |= 0x04; - if (CHK_SD_HS(sd_card)) - rtsx_status[13] |= 0x02; - } else { - rtsx_status[13] |= 0x08; - if (CHK_MMC_52M(sd_card)) - rtsx_status[13] |= 0x02; - if (CHK_MMC_SECTOR_MODE(sd_card)) - rtsx_status[13] |= 0x04; - } - } else if (get_lun_card(chip, lun) == MS_CARD) { - struct ms_info *ms_card = &chip->ms_card; - - if (CHK_MSPRO(ms_card)) { - rtsx_status[13] = 0x38; - if (CHK_HG8BIT(ms_card)) - rtsx_status[13] |= 0x04; -#ifdef SUPPORT_MSXC - if (CHK_MSXC(ms_card)) - rtsx_status[13] |= 0x01; -#endif - } else { - rtsx_status[13] = 0x30; - } - } else { - if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) { -#ifdef SUPPORT_SDIO - if (chip->sd_io && chip->sd_int) - rtsx_status[13] = 0x60; - else - rtsx_status[13] = 0x70; -#else - rtsx_status[13] = 0x70; -#endif - } else { - if (chip->lun2card[lun] == SD_CARD) - rtsx_status[13] = 0x20; - else - rtsx_status[13] = 0x30; - } - } - - rtsx_status[14] = 0x78; - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) - rtsx_status[15] = 0x83; - else - rtsx_status[15] = 0x82; - - buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rtsx_status)); - rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - return TRANSPORT_GOOD; -} - -static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - u8 card, bus_width; - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - card = get_lun_card(chip, lun); - if (card == SD_CARD || card == MS_CARD) { - bus_width = chip->card_bus_width[lun]; - } else { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return TRANSPORT_FAILED; - } - - scsi_set_resid(srb, 0); - rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb); - - return TRANSPORT_GOOD; -} - -static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int result; - unsigned int lun = SCSI_LUN(srb); - u8 gpio_dir; - - if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - rtsx_force_power_on(chip, SSC_PDCTL); - - rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir); - rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06); - - switch (srb->cmnd[2]) { - case SCSI_SPI_GETSTATUS: - result = spi_get_status(srb, chip); - break; - - case SCSI_SPI_SETPARAMETER: - result = spi_set_parameter(srb, chip); - break; - - case SCSI_SPI_READFALSHID: - result = spi_read_flash_id(srb, chip); - break; - - case SCSI_SPI_READFLASH: - result = spi_read_flash(srb, chip); - break; - - case SCSI_SPI_WRITEFLASH: - result = spi_write_flash(srb, chip); - break; - - case SCSI_SPI_WRITEFLASHSTATUS: - result = spi_write_flash_status(srb, chip); - break; - - case SCSI_SPI_ERASEFLASH: - result = spi_erase_flash(srb, chip); - break; - - default: - rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir); - - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir); - - if (result != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - return TRANSPORT_GOOD; -} - -static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int result; - - switch (srb->cmnd[1]) { - case READ_STATUS: - result = read_status(srb, chip); - break; - - case READ_MEM: - result = read_mem(srb, chip); - break; - - case WRITE_MEM: - result = write_mem(srb, chip); - break; - - case READ_EEPROM: - result = read_eeprom(srb, chip); - break; - - case WRITE_EEPROM: - result = write_eeprom(srb, chip); - break; - - case TOGGLE_GPIO: - result = toggle_gpio_cmd(srb, chip); - break; - - case GET_SD_CSD: - result = get_sd_csd(srb, chip); - break; - - case GET_BUS_WIDTH: - result = get_card_bus_width(srb, chip); - break; - - case SCSI_APP_CMD: - result = app_cmd(srb, chip); - break; - - case SPI_VENDOR_COMMAND: - result = spi_vendor_cmd(srb, chip); - break; - - default: - set_sense_type(chip, SCSI_LUN(srb), - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return result; -} - -#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK) -void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - u16 sec_cnt; - - if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) { - sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) { - sec_cnt = srb->cmnd[4]; - if (sec_cnt == 0) - sec_cnt = 256; - } else { - return; - } - - if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) { - toggle_gpio(chip, LED_GPIO); - chip->rw_cap[lun] = 0; - } else { - chip->rw_cap[lun] += sec_cnt; - } -} -#endif - -static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - unsigned int lun = SCSI_LUN(srb); - bool quick_format; - int retval; - - if (get_lun_card(chip, lun) != MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - return TRANSPORT_FAILED; - } - - if (srb->cmnd[3] != 0x4D || srb->cmnd[4] != 0x47 || - srb->cmnd[5] != 0x66 || srb->cmnd[6] != 0x6D || - srb->cmnd[7] != 0x74) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - - if (!check_card_ready(chip, lun) || - (get_card_size(chip, lun) == 0)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - if (srb->cmnd[8] & 0x01) - quick_format = false; - else - quick_format = true; - - if (!(chip->card_ready & MS_CARD)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - - if (chip->card_wp & MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - return TRANSPORT_FAILED; - } - - if (!CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - return TRANSPORT_FAILED; - } - - retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED); - return TRANSPORT_FAILED; - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -#ifdef SUPPORT_PCGL_1P18 -static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - unsigned int lun = SCSI_LUN(srb); - u8 dev_info_id, data_len; - u8 *buf; - unsigned int buf_len; - int i; - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - if (get_lun_card(chip, lun) != MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - return TRANSPORT_FAILED; - } - - if (srb->cmnd[2] != 0xB0 || srb->cmnd[4] != 0x4D || - srb->cmnd[5] != 0x53 || srb->cmnd[6] != 0x49 || - srb->cmnd[7] != 0x44) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - dev_info_id = srb->cmnd[3]; - if ((CHK_MSXC(ms_card) && dev_info_id == 0x10) || - (!CHK_MSXC(ms_card) && dev_info_id == 0x13) || - !CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (dev_info_id == 0x15) { - buf_len = 0x3C; - data_len = 0x3A; - } else { - buf_len = 0x6C; - data_len = 0x6A; - } - - buf = kmalloc(buf_len, GFP_KERNEL); - if (!buf) - return TRANSPORT_ERROR; - - i = 0; - /* GET Memory Stick Media Information Response Header */ - buf[i++] = 0x00; /* Data length MSB */ - buf[i++] = data_len; /* Data length LSB */ - /* Device Information Type Code */ - if (CHK_MSXC(ms_card)) - buf[i++] = 0x03; - else - buf[i++] = 0x02; - - /* SGM bit */ - buf[i++] = 0x01; - /* Reserved */ - buf[i++] = 0x00; - buf[i++] = 0x00; - buf[i++] = 0x00; - /* Number of Device Information */ - buf[i++] = 0x01; - - /* Device Information Body */ - - /* Device Information ID Number */ - buf[i++] = dev_info_id; - /* Device Information Length */ - if (dev_info_id == 0x15) - data_len = 0x31; - else - data_len = 0x61; - - buf[i++] = 0x00; /* Data length MSB */ - buf[i++] = data_len; /* Data length LSB */ - /* Valid Bit */ - buf[i++] = 0x80; - if (dev_info_id == 0x10 || dev_info_id == 0x13) { - /* System Information */ - memcpy(buf + i, ms_card->raw_sys_info, 96); - } else { - /* Model Name */ - memcpy(buf + i, ms_card->raw_model_name, 48); - } - - rtsx_stor_set_xfer_buf(buf, buf_len, srb); - scsi_set_resid(srb, scsi_bufflen(srb) - buf_len); - - kfree(buf); - return STATUS_SUCCESS; -} -#endif - -static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval = TRANSPORT_ERROR; - - if (srb->cmnd[2] == MS_FORMAT) - retval = ms_format_cmnd(srb, chip); -#ifdef SUPPORT_PCGL_1P18 - else if (srb->cmnd[2] == GET_MS_INFORMATION) - retval = get_ms_information(srb, chip); -#endif - - return retval; -} - -#ifdef SUPPORT_CPRM -static int sd_extension_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - unsigned int lun = SCSI_LUN(srb); - int result; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - sd_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - if (get_lun_card(chip, lun) != SD_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - return TRANSPORT_FAILED; - } - - switch (srb->cmnd[0]) { - case SD_PASS_THRU_MODE: - result = sd_pass_thru_mode(srb, chip); - break; - - case SD_EXECUTE_NO_DATA: - result = sd_execute_no_data(srb, chip); - break; - - case SD_EXECUTE_READ: - result = sd_execute_read_data(srb, chip); - break; - - case SD_EXECUTE_WRITE: - result = sd_execute_write_data(srb, chip); - break; - - case SD_GET_RSP: - result = sd_get_cmd_rsp(srb, chip); - break; - - case SD_HW_RST: - result = sd_hw_rst(srb, chip); - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - return result; -} -#endif - -#ifdef SUPPORT_MAGIC_GATE -static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 key_format; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - ms_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - if (get_lun_card(chip, lun) != MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - return TRANSPORT_FAILED; - } - - if (srb->cmnd[7] != KC_MG_R_PRO) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (!CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return TRANSPORT_FAILED; - } - - key_format = srb->cmnd[10] & 0x3F; - dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format); - - switch (key_format) { - case KF_GET_LOC_EKB: - if ((scsi_bufflen(srb) == 0x41C) && - srb->cmnd[8] == 0x04 && - srb->cmnd[9] == 0x1C) { - retval = mg_get_local_EKB(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - case KF_RSP_CHG: - if ((scsi_bufflen(srb) == 0x24) && - srb->cmnd[8] == 0x00 && - srb->cmnd[9] == 0x24) { - retval = mg_get_rsp_chg(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - case KF_GET_ICV: - ms_card->mg_entry_num = srb->cmnd[5]; - if ((scsi_bufflen(srb) == 0x404) && - srb->cmnd[8] == 0x04 && - srb->cmnd[9] == 0x04 && - srb->cmnd[2] == 0x00 && - srb->cmnd[3] == 0x00 && - srb->cmnd[4] == 0x00 && - srb->cmnd[5] < 32) { - retval = mg_get_ICV(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct ms_info *ms_card = &chip->ms_card; - unsigned int lun = SCSI_LUN(srb); - int retval; - u8 key_format; - - rtsx_disable_aspm(chip); - - if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) { - rtsx_exit_ss(chip); - wait_timeout(100); - } - rtsx_set_stat(chip, RTSX_STAT_RUN); - - ms_cleanup_work(chip); - - if (!check_card_ready(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return TRANSPORT_FAILED; - } - if (check_card_wp(chip, lun)) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT); - return TRANSPORT_FAILED; - } - if (get_lun_card(chip, lun) != MS_CARD) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT); - return TRANSPORT_FAILED; - } - - if (srb->cmnd[7] != KC_MG_R_PRO) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (!CHK_MSPRO(ms_card)) { - set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM); - return TRANSPORT_FAILED; - } - - key_format = srb->cmnd[10] & 0x3F; - dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format); - - switch (key_format) { - case KF_SET_LEAF_ID: - if ((scsi_bufflen(srb) == 0x0C) && - srb->cmnd[8] == 0x00 && - srb->cmnd[9] == 0x0C) { - retval = mg_set_leaf_id(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - case KF_CHG_HOST: - if ((scsi_bufflen(srb) == 0x0C) && - srb->cmnd[8] == 0x00 && - srb->cmnd[9] == 0x0C) { - retval = mg_chg(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - case KF_RSP_HOST: - if ((scsi_bufflen(srb) == 0x0C) && - srb->cmnd[8] == 0x00 && - srb->cmnd[9] == 0x0C) { - retval = mg_rsp(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - case KF_SET_ICV: - ms_card->mg_entry_num = srb->cmnd[5]; - if ((scsi_bufflen(srb) == 0x404) && - srb->cmnd[8] == 0x04 && - srb->cmnd[9] == 0x04 && - srb->cmnd[2] == 0x00 && - srb->cmnd[3] == 0x00 && - srb->cmnd[4] == 0x00 && - srb->cmnd[5] < 32) { - retval = mg_set_ICV(srb, chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ -#ifdef SUPPORT_SD_LOCK - struct sd_info *sd_card = &chip->sd_card; -#endif - struct ms_info *ms_card = &chip->ms_card; - unsigned int lun = SCSI_LUN(srb); - int result; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_erase_status) { - /* Block all SCSI command except for - * REQUEST_SENSE and rs_ppstatus - */ - if (!(srb->cmnd[0] == VENDOR_CMND && - srb->cmnd[1] == SCSI_APP_CMD && - srb->cmnd[2] == GET_DEV_STATUS) && - srb->cmnd[0] != REQUEST_SENSE) { - /* Logical Unit Not Ready Format in Progress */ - set_sense_data(chip, lun, CUR_ERR, - 0x02, 0, 0x04, 0x04, 0, 0); - return TRANSPORT_FAILED; - } - } -#endif - - if ((get_lun_card(chip, lun) == MS_CARD) && - ms_card->format_status == FORMAT_IN_PROGRESS) { - if (srb->cmnd[0] != REQUEST_SENSE && - srb->cmnd[0] != INQUIRY) { - /* Logical Unit Not Ready Format in Progress */ - set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, - 0, (u16)(ms_card->progress)); - return TRANSPORT_FAILED; - } - } - - switch (srb->cmnd[0]) { - case READ_10: - case WRITE_10: - case READ_6: - case WRITE_6: - result = read_write(srb, chip); -#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK) - led_shine(srb, chip); -#endif - break; - - case TEST_UNIT_READY: - result = test_unit_ready(srb, chip); - break; - - case INQUIRY: - result = inquiry(srb, chip); - break; - - case READ_CAPACITY: - result = read_capacity(srb, chip); - break; - - case START_STOP: - result = start_stop_unit(srb, chip); - break; - - case ALLOW_MEDIUM_REMOVAL: - result = allow_medium_removal(srb, chip); - break; - - case REQUEST_SENSE: - result = request_sense(srb, chip); - break; - - case MODE_SENSE: - case MODE_SENSE_10: - result = mode_sense(srb, chip); - break; - - case 0x23: - result = read_format_capacity(srb, chip); - break; - - case VENDOR_CMND: - result = vendor_cmnd(srb, chip); - break; - - case MS_SP_CMND: - result = ms_sp_cmnd(srb, chip); - break; - -#ifdef SUPPORT_CPRM - case SD_PASS_THRU_MODE: - case SD_EXECUTE_NO_DATA: - case SD_EXECUTE_READ: - case SD_EXECUTE_WRITE: - case SD_GET_RSP: - case SD_HW_RST: - result = sd_extension_cmnd(srb, chip); - break; -#endif - -#ifdef SUPPORT_MAGIC_GATE - case CMD_MSPRO_MG_RKEY: - result = mg_report_key(srb, chip); - break; - - case CMD_MSPRO_MG_SKEY: - result = mg_send_key(srb, chip); - break; -#endif - - case FORMAT_UNIT: - case MODE_SELECT: - case VERIFY: - result = TRANSPORT_GOOD; - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - result = TRANSPORT_FAILED; - } - - return result; -} diff --git a/drivers/staging/rts5208/rtsx_scsi.h b/drivers/staging/rts5208/rtsx_scsi.h deleted file mode 100644 index df6138c97aaad5e00677f7685464bc0201646a90..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_scsi.h +++ /dev/null @@ -1,131 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_SCSI_H -#define __REALTEK_RTSX_SCSI_H - -#include "rtsx.h" -#include "rtsx_chip.h" - -#define MS_SP_CMND 0xFA -#define MS_FORMAT 0xA0 -#define GET_MS_INFORMATION 0xB0 - -#define VENDOR_CMND 0xF0 - -#define READ_STATUS 0x09 - -#define READ_EEPROM 0x04 -#define WRITE_EEPROM 0x05 -#define READ_MEM 0x0D -#define WRITE_MEM 0x0E -#define GET_BUS_WIDTH 0x13 -#define GET_SD_CSD 0x14 -#define TOGGLE_GPIO 0x15 -#define TRACE_MSG 0x18 - -#define SCSI_APP_CMD 0x10 - -#define PP_READ10 0x1A -#define PP_WRITE10 0x0A -#define READ_HOST_REG 0x1D -#define WRITE_HOST_REG 0x0D -#define SET_VAR 0x05 -#define GET_VAR 0x15 -#define DMA_READ 0x16 -#define DMA_WRITE 0x06 -#define GET_DEV_STATUS 0x10 -#define SET_CHIP_MODE 0x27 -#define SUIT_CMD 0xE0 -#define WRITE_PHY 0x07 -#define READ_PHY 0x17 -#define WRITE_EEPROM2 0x03 -#define READ_EEPROM2 0x13 -#define ERASE_EEPROM2 0x23 -#define WRITE_EFUSE 0x04 -#define READ_EFUSE 0x14 -#define WRITE_CFG 0x0E -#define READ_CFG 0x1E - -#define SPI_VENDOR_COMMAND 0x1C - -#define SCSI_SPI_GETSTATUS 0x00 -#define SCSI_SPI_SETPARAMETER 0x01 -#define SCSI_SPI_READFALSHID 0x02 -#define SCSI_SPI_READFLASH 0x03 -#define SCSI_SPI_WRITEFLASH 0x04 -#define SCSI_SPI_WRITEFLASHSTATUS 0x05 -#define SCSI_SPI_ERASEFLASH 0x06 - -#define INIT_BATCHCMD 0x41 -#define ADD_BATCHCMD 0x42 -#define SEND_BATCHCMD 0x43 -#define GET_BATCHRSP 0x44 - -#define CHIP_NORMALMODE 0x00 -#define CHIP_DEBUGMODE 0x01 - -/* SD Pass Through Command Extension */ -#define SD_PASS_THRU_MODE 0xD0 -#define SD_EXECUTE_NO_DATA 0xD1 -#define SD_EXECUTE_READ 0xD2 -#define SD_EXECUTE_WRITE 0xD3 -#define SD_GET_RSP 0xD4 -#define SD_HW_RST 0xD6 - -#ifdef SUPPORT_MAGIC_GATE -#define CMD_MSPRO_MG_RKEY 0xA4 /* Report Key Command */ -#define CMD_MSPRO_MG_SKEY 0xA3 /* Send Key Command */ - -/* CBWCB field: key class */ -#define KC_MG_R_PRO 0xBE /* MG-R PRO*/ - -/* CBWCB field: key format */ -#define KF_SET_LEAF_ID 0x31 /* Set Leaf ID */ -#define KF_GET_LOC_EKB 0x32 /* Get Local EKB */ -#define KF_CHG_HOST 0x33 /* Challenge (host) */ -#define KF_RSP_CHG 0x34 /* Response and Challenge (device) */ -#define KF_RSP_HOST 0x35 /* Response (host) */ -#define KF_GET_ICV 0x36 /* Get ICV */ -#define KF_SET_ICV 0x37 /* SSet ICV */ -#endif - -/* Sense type */ -#define SENSE_TYPE_NO_SENSE 0 -#define SENSE_TYPE_MEDIA_CHANGE 1 -#define SENSE_TYPE_MEDIA_NOT_PRESENT 2 -#define SENSE_TYPE_MEDIA_LBA_OVER_RANGE 3 -#define SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT 4 -#define SENSE_TYPE_MEDIA_WRITE_PROTECT 5 -#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6 -#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7 -#define SENSE_TYPE_MEDIA_WRITE_ERR 8 -#define SENSE_TYPE_FORMAT_IN_PROGRESS 9 -#define SENSE_TYPE_FORMAT_CMD_FAILED 10 -#ifdef SUPPORT_MAGIC_GATE -#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB 0x0b -#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN 0x0c -#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM 0x0d -#define SENSE_TYPE_MG_WRITE_ERR 0x0e -#endif -#ifdef SUPPORT_SD_LOCK -/* FOR Locked SD card*/ -#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10 -#endif - -void scsi_show_command(struct rtsx_chip *chip); -void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type); -void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, - u8 sense_key, u32 info, u8 asc, u8 ascq, - u8 sns_key_info0, u16 sns_key_info1); -int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip); - -#endif /* __REALTEK_RTSX_SCSI_H */ diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h deleted file mode 100644 index 77094809c814564d1b407cb967e0f2d63437db9d..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_sys.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __RTSX_SYS_H -#define __RTSX_SYS_H - -#include "rtsx.h" -#include "rtsx_chip.h" -#include "rtsx_card.h" - -static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip) -{ - struct rtsx_dev *dev = chip->rtsx; - - spin_lock(&dev->reg_lock); - rtsx_enter_ss(chip); - spin_unlock(&dev->reg_lock); -} - -static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag) -{ - rtsx_reset_cards(chip); -} - -#define RTSX_MSG_IN_INT(x) - -#endif /* __RTSX_SYS_H */ - diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c deleted file mode 100644 index d5ad49de4c568544f96026574597f081d5564248..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_transport.c +++ /dev/null @@ -1,768 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> - -#include "rtsx.h" - -/*********************************************************************** - * Scatter-gather transfer buffer access routines - ***********************************************************************/ - -/* - * Copy a buffer of length buflen to/from the srb's transfer buffer. - * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer - * points to a list of s-g entries and we ignore srb->request_bufflen. - * For non-scatter-gather transfers, srb->request_buffer points to the - * transfer buffer itself and srb->request_bufflen is the buffer's length.) - * Update the *index and *offset variables so that the next copy will - * pick up from where this one left off. - */ - -unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, - struct scsi_cmnd *srb, - unsigned int *index, - unsigned int *offset, - enum xfer_buf_dir dir) -{ - unsigned int cnt; - - /* If not using scatter-gather, just transfer the data directly. */ - if (scsi_sg_count(srb) == 0) { - unsigned char *sgbuffer; - - if (*offset >= scsi_bufflen(srb)) - return 0; - cnt = min(buflen, scsi_bufflen(srb) - *offset); - - sgbuffer = (unsigned char *)scsi_sglist(srb) + *offset; - - if (dir == TO_XFER_BUF) - memcpy(sgbuffer, buffer, cnt); - else - memcpy(buffer, sgbuffer, cnt); - *offset += cnt; - - /* - * Using scatter-gather. We have to go through the list one entry - * at a time. Each s-g entry contains some number of pages which - * have to be copied one at a time. - */ - } else { - struct scatterlist *sg = - (struct scatterlist *)scsi_sglist(srb) - + *index; - - /* - * This loop handles a single s-g list entry, which may - * include multiple pages. Find the initial page structure - * and the starting offset within the page, and update - * the *offset and *index values for the next loop. - */ - cnt = 0; - while (cnt < buflen && *index < scsi_sg_count(srb)) { - struct page *page = sg_page(sg) + - ((sg->offset + *offset) >> PAGE_SHIFT); - unsigned int poff = (sg->offset + *offset) & - (PAGE_SIZE - 1); - unsigned int sglen = sg->length - *offset; - - if (sglen > buflen - cnt) { - /* Transfer ends within this s-g entry */ - sglen = buflen - cnt; - *offset += sglen; - } else { - /* Transfer continues to next s-g entry */ - *offset = 0; - ++*index; - ++sg; - } - - while (sglen > 0) { - unsigned int plen = min(sglen, (unsigned int) - PAGE_SIZE - poff); - - if (dir == TO_XFER_BUF) - memcpy_to_page(page, poff, buffer + cnt, plen); - else - memcpy_from_page(buffer + cnt, page, poff, plen); - - /* Start at the beginning of the next page */ - poff = 0; - ++page; - cnt += plen; - sglen -= plen; - } - } - } - - /* Return the amount actually transferred */ - return cnt; -} - -/* - * Store the contents of buffer into srb's transfer buffer and set the - * SCSI residue. - */ -void rtsx_stor_set_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb) -{ - unsigned int index = 0, offset = 0; - - rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, - TO_XFER_BUF); - if (buflen < scsi_bufflen(srb)) - scsi_set_resid(srb, scsi_bufflen(srb) - buflen); -} - -void rtsx_stor_get_xfer_buf(unsigned char *buffer, - unsigned int buflen, struct scsi_cmnd *srb) -{ - unsigned int index = 0, offset = 0; - - rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, - FROM_XFER_BUF); - if (buflen < scsi_bufflen(srb)) - scsi_set_resid(srb, scsi_bufflen(srb) - buflen); -} - -/*********************************************************************** - * Transport routines - ***********************************************************************/ - -/* - * Invoke the transport and basic error-handling/recovery methods - * - * This is used to send the message to the device and receive the response. - */ -void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int result; - - result = rtsx_scsi_handler(srb, chip); - - /* - * if the command gets aborted by the higher layers, we need to - * short-circuit all other processing. - */ - if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) { - dev_dbg(rtsx_dev(chip), "-- command was aborted\n"); - srb->result = DID_ABORT << 16; - goto handle_errors; - } - - /* if there is a transport error, reset and don't auto-sense */ - if (result == TRANSPORT_ERROR) { - dev_dbg(rtsx_dev(chip), "-- transport indicates error, resetting\n"); - srb->result = DID_ERROR << 16; - goto handle_errors; - } - - srb->result = SAM_STAT_GOOD; - - /* - * If we have a failure, we're going to do a REQUEST_SENSE - * automatically. Note that we differentiate between a command - * "failure" and an "error" in the transport mechanism. - */ - if (result == TRANSPORT_FAILED) { - /* set the result so the higher layers expect this data */ - srb->result = SAM_STAT_CHECK_CONDITION; - memcpy(srb->sense_buffer, - (unsigned char *)&chip->sense_buffer[SCSI_LUN(srb)], - sizeof(struct sense_data_t)); - } - - return; - -handle_errors: - return; -} - -void rtsx_add_cmd(struct rtsx_chip *chip, - u8 cmd_type, u16 reg_addr, u8 mask, u8 data) -{ - __le32 *cb = (__le32 *)(chip->host_cmds_ptr); - u32 val = 0; - - val |= (u32)(cmd_type & 0x03) << 30; - val |= (u32)(reg_addr & 0x3FFF) << 16; - val |= (u32)mask << 8; - val |= (u32)data; - - spin_lock_irq(&chip->rtsx->reg_lock); - if (chip->ci < (HOST_CMDS_BUF_LEN / 4)) - cb[(chip->ci)++] = cpu_to_le32(val); - - spin_unlock_irq(&chip->rtsx->reg_lock); -} - -void rtsx_send_cmd_no_wait(struct rtsx_chip *chip) -{ - u32 val = BIT(31); - - rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr); - - val |= (u32)(chip->ci * 4) & 0x00FFFFFF; - /* Hardware Auto Response */ - val |= 0x40000000; - rtsx_writel(chip, RTSX_HCBCTLR, val); -} - -int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout) -{ - struct rtsx_dev *rtsx = chip->rtsx; - struct completion trans_done; - u32 val = BIT(31); - long timeleft; - int err = 0; - - if (card == SD_CARD) - rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) - rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) - rtsx->check_card_cd = XD_EXIST; - else - rtsx->check_card_cd = 0; - - spin_lock_irq(&rtsx->reg_lock); - - /* set up data structures for the wakeup system */ - rtsx->done = &trans_done; - rtsx->trans_result = TRANS_NOT_READY; - init_completion(&trans_done); - rtsx->trans_state = STATE_TRANS_CMD; - - rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr); - - val |= (u32)(chip->ci * 4) & 0x00FFFFFF; - /* Hardware Auto Response */ - val |= 0x40000000; - rtsx_writel(chip, RTSX_HCBCTLR, val); - - spin_unlock_irq(&rtsx->reg_lock); - - /* Wait for TRANS_OK_INT */ - timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); - if (timeleft <= 0) { - dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", - chip->int_reg); - err = -ETIMEDOUT; - goto finish_send_cmd; - } - - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) - err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) - err = 0; - - spin_unlock_irq(&rtsx->reg_lock); - -finish_send_cmd: - rtsx->done = NULL; - rtsx->trans_state = STATE_TRANS_NONE; - - if (err < 0) - rtsx_stop_cmd(chip, card); - - return err; -} - -static inline void rtsx_add_sg_tbl(struct rtsx_chip *chip, - u32 addr, u32 len, u8 option) -{ - __le64 *sgb = (__le64 *)(chip->host_sg_tbl_ptr); - u64 val = 0; - u32 temp_len = 0; - u8 temp_opt = 0; - - do { - if (len > 0x80000) { - temp_len = 0x80000; - temp_opt = option & (~RTSX_SG_END); - } else { - temp_len = len; - temp_opt = option; - } - val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt; - - if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8)) - sgb[(chip->sgi)++] = cpu_to_le64(val); - - len -= temp_len; - addr += temp_len; - } while (len); -} - -static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, - struct scatterlist *sg, int num_sg, - unsigned int *index, - unsigned int *offset, int size, - enum dma_data_direction dma_dir, - int timeout) -{ - struct rtsx_dev *rtsx = chip->rtsx; - struct completion trans_done; - u8 dir; - int sg_cnt, i, resid; - int err = 0; - long timeleft; - struct scatterlist *sg_ptr; - u32 val = TRIG_DMA; - - if (!sg || num_sg <= 0 || !offset || !index) - return -EIO; - - if (dma_dir == DMA_TO_DEVICE) - dir = HOST_TO_DEVICE; - else if (dma_dir == DMA_FROM_DEVICE) - dir = DEVICE_TO_HOST; - else - return -ENXIO; - - if (card == SD_CARD) - rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) - rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) - rtsx->check_card_cd = XD_EXIST; - else - rtsx->check_card_cd = 0; - - spin_lock_irq(&rtsx->reg_lock); - - /* set up data structures for the wakeup system */ - rtsx->done = &trans_done; - - rtsx->trans_state = STATE_TRANS_SG; - rtsx->trans_result = TRANS_NOT_READY; - - spin_unlock_irq(&rtsx->reg_lock); - - sg_cnt = dma_map_sg(&rtsx->pci->dev, sg, num_sg, dma_dir); - - resid = size; - sg_ptr = sg; - chip->sgi = 0; - /* - * Usually the next entry will be @sg@ + 1, but if this sg element - * is part of a chained scatterlist, it could jump to the start of - * a new scatterlist array. So here we use sg_next to move to - * the proper sg. - */ - for (i = 0; i < *index; i++) - sg_ptr = sg_next(sg_ptr); - for (i = *index; i < sg_cnt; i++) { - dma_addr_t addr; - unsigned int len; - u8 option; - - addr = sg_dma_address(sg_ptr); - len = sg_dma_len(sg_ptr); - - dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n", - (unsigned int)addr, len); - dev_dbg(rtsx_dev(chip), "*index = %d, *offset = %d\n", - *index, *offset); - - addr += *offset; - - if ((len - *offset) > resid) { - *offset += resid; - len = resid; - resid = 0; - } else { - resid -= (len - *offset); - len -= *offset; - *offset = 0; - *index = *index + 1; - } - option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; - if ((i == sg_cnt - 1) || !resid) - option |= RTSX_SG_END; - - rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); - - if (!resid) - break; - - sg_ptr = sg_next(sg_ptr); - } - - dev_dbg(rtsx_dev(chip), "SG table count = %d\n", chip->sgi); - - val |= (u32)(dir & 0x01) << 29; - val |= ADMA_MODE; - - spin_lock_irq(&rtsx->reg_lock); - - init_completion(&trans_done); - - rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr); - rtsx_writel(chip, RTSX_HDBCTLR, val); - - spin_unlock_irq(&rtsx->reg_lock); - - timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); - if (timeleft <= 0) { - dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", - __func__, __LINE__); - dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", - chip->int_reg); - err = -ETIMEDOUT; - goto out; - } - - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) { - err = -EIO; - spin_unlock_irq(&rtsx->reg_lock); - goto out; - } - spin_unlock_irq(&rtsx->reg_lock); - - /* Wait for TRANS_OK_INT */ - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_NOT_READY) { - init_completion(&trans_done); - spin_unlock_irq(&rtsx->reg_lock); - timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); - if (timeleft <= 0) { - dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", - __func__, __LINE__); - dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", - chip->int_reg); - err = -ETIMEDOUT; - goto out; - } - } else { - spin_unlock_irq(&rtsx->reg_lock); - } - - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) - err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) - err = 0; - - spin_unlock_irq(&rtsx->reg_lock); - -out: - rtsx->done = NULL; - rtsx->trans_state = STATE_TRANS_NONE; - dma_unmap_sg(&rtsx->pci->dev, sg, num_sg, dma_dir); - - if (err < 0) - rtsx_stop_cmd(chip, card); - - return err; -} - -static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, - struct scatterlist *sg, int num_sg, - enum dma_data_direction dma_dir, - int timeout) -{ - struct rtsx_dev *rtsx = chip->rtsx; - struct completion trans_done; - u8 dir; - int buf_cnt, i; - int err = 0; - long timeleft; - struct scatterlist *sg_ptr; - - if (!sg || num_sg <= 0) - return -EIO; - - if (dma_dir == DMA_TO_DEVICE) - dir = HOST_TO_DEVICE; - else if (dma_dir == DMA_FROM_DEVICE) - dir = DEVICE_TO_HOST; - else - return -ENXIO; - - if (card == SD_CARD) - rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) - rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) - rtsx->check_card_cd = XD_EXIST; - else - rtsx->check_card_cd = 0; - - spin_lock_irq(&rtsx->reg_lock); - - /* set up data structures for the wakeup system */ - rtsx->done = &trans_done; - - rtsx->trans_state = STATE_TRANS_SG; - rtsx->trans_result = TRANS_NOT_READY; - - spin_unlock_irq(&rtsx->reg_lock); - - buf_cnt = dma_map_sg(&rtsx->pci->dev, sg, num_sg, dma_dir); - - sg_ptr = sg; - - for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) { - u32 val = TRIG_DMA; - int sg_cnt, j; - - if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8)) - sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8); - else - sg_cnt = HOST_SG_TBL_BUF_LEN / 8; - - chip->sgi = 0; - for (j = 0; j < sg_cnt; j++) { - dma_addr_t addr = sg_dma_address(sg_ptr); - unsigned int len = sg_dma_len(sg_ptr); - u8 option; - - dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n", - (unsigned int)addr, len); - - option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; - if (j == (sg_cnt - 1)) - option |= RTSX_SG_END; - - rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); - - sg_ptr = sg_next(sg_ptr); - } - - dev_dbg(rtsx_dev(chip), "SG table count = %d\n", chip->sgi); - - val |= (u32)(dir & 0x01) << 29; - val |= ADMA_MODE; - - spin_lock_irq(&rtsx->reg_lock); - - init_completion(&trans_done); - - rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr); - rtsx_writel(chip, RTSX_HDBCTLR, val); - - spin_unlock_irq(&rtsx->reg_lock); - - timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); - if (timeleft <= 0) { - dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", - __func__, __LINE__); - dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", - chip->int_reg); - err = -ETIMEDOUT; - goto out; - } - - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) { - err = -EIO; - spin_unlock_irq(&rtsx->reg_lock); - goto out; - } - spin_unlock_irq(&rtsx->reg_lock); - - sg_ptr += sg_cnt; - } - - /* Wait for TRANS_OK_INT */ - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_NOT_READY) { - init_completion(&trans_done); - spin_unlock_irq(&rtsx->reg_lock); - timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); - if (timeleft <= 0) { - dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", - __func__, __LINE__); - dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", - chip->int_reg); - err = -ETIMEDOUT; - goto out; - } - } else { - spin_unlock_irq(&rtsx->reg_lock); - } - - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) - err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) - err = 0; - - spin_unlock_irq(&rtsx->reg_lock); - -out: - rtsx->done = NULL; - rtsx->trans_state = STATE_TRANS_NONE; - dma_unmap_sg(&rtsx->pci->dev, sg, num_sg, dma_dir); - - if (err < 0) - rtsx_stop_cmd(chip, card); - - return err; -} - -static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, - size_t len, enum dma_data_direction dma_dir, - int timeout) -{ - struct rtsx_dev *rtsx = chip->rtsx; - struct completion trans_done; - dma_addr_t addr; - u8 dir; - int err = 0; - u32 val = BIT(31); - long timeleft; - - if (!buf || len <= 0) - return -EIO; - - if (dma_dir == DMA_TO_DEVICE) - dir = HOST_TO_DEVICE; - else if (dma_dir == DMA_FROM_DEVICE) - dir = DEVICE_TO_HOST; - else - return -ENXIO; - - addr = dma_map_single(&rtsx->pci->dev, buf, len, dma_dir); - if (dma_mapping_error(&rtsx->pci->dev, addr)) - return -ENOMEM; - - if (card == SD_CARD) - rtsx->check_card_cd = SD_EXIST; - else if (card == MS_CARD) - rtsx->check_card_cd = MS_EXIST; - else if (card == XD_CARD) - rtsx->check_card_cd = XD_EXIST; - else - rtsx->check_card_cd = 0; - - val |= (u32)(dir & 0x01) << 29; - val |= (u32)(len & 0x00FFFFFF); - - spin_lock_irq(&rtsx->reg_lock); - - /* set up data structures for the wakeup system */ - rtsx->done = &trans_done; - - init_completion(&trans_done); - - rtsx->trans_state = STATE_TRANS_BUF; - rtsx->trans_result = TRANS_NOT_READY; - - rtsx_writel(chip, RTSX_HDBAR, addr); - rtsx_writel(chip, RTSX_HDBCTLR, val); - - spin_unlock_irq(&rtsx->reg_lock); - - /* Wait for TRANS_OK_INT */ - timeleft = wait_for_completion_interruptible_timeout(&trans_done, - msecs_to_jiffies(timeout)); - if (timeleft <= 0) { - dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", - __func__, __LINE__); - dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", - chip->int_reg); - err = -ETIMEDOUT; - goto out; - } - - spin_lock_irq(&rtsx->reg_lock); - if (rtsx->trans_result == TRANS_RESULT_FAIL) - err = -EIO; - else if (rtsx->trans_result == TRANS_RESULT_OK) - err = 0; - - spin_unlock_irq(&rtsx->reg_lock); - -out: - rtsx->done = NULL; - rtsx->trans_state = STATE_TRANS_NONE; - dma_unmap_single(&rtsx->pci->dev, addr, len, dma_dir); - - if (err < 0) - rtsx_stop_cmd(chip, card); - - return err; -} - -int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, - void *buf, size_t len, int use_sg, - unsigned int *index, unsigned int *offset, - enum dma_data_direction dma_dir, int timeout) -{ - int err = 0; - - /* don't transfer data during abort processing */ - if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) - return -EIO; - - if (use_sg) { - struct scatterlist *sg = buf; - - err = rtsx_transfer_sglist_adma_partial(chip, card, sg, use_sg, - index, offset, (int)len, - dma_dir, timeout); - } else { - err = rtsx_transfer_buf(chip, card, - buf, len, dma_dir, timeout); - } - if (err < 0) { - if (RTSX_TST_DELINK(chip)) { - RTSX_CLR_DELINK(chip); - chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; - rtsx_reinit_cards(chip, 1); - } - } - - return err; -} - -int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len, - int use_sg, enum dma_data_direction dma_dir, int timeout) -{ - int err = 0; - - dev_dbg(rtsx_dev(chip), "use_sg = %d\n", use_sg); - - /* don't transfer data during abort processing */ - if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) - return -EIO; - - if (use_sg) { - err = rtsx_transfer_sglist_adma(chip, card, buf, - use_sg, dma_dir, timeout); - } else { - err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout); - } - - if (err < 0) { - if (RTSX_TST_DELINK(chip)) { - RTSX_CLR_DELINK(chip); - chip->need_reinit = SD_CARD | MS_CARD | XD_CARD; - rtsx_reinit_cards(chip, 1); - } - } - - return err; -} - diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h deleted file mode 100644 index 097efed24b79857e42ca6bdbfbf670bd74243ac0..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/rtsx_transport.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_TRANSPORT_H -#define __REALTEK_RTSX_TRANSPORT_H - -#include "rtsx.h" -#include "rtsx_chip.h" - -#define WAIT_TIME 2000 - -unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer, - unsigned int buflen, - struct scsi_cmnd *srb, - unsigned int *index, - unsigned int *offset, - enum xfer_buf_dir dir); -void rtsx_stor_set_xfer_buf(unsigned char *buffer, unsigned int buflen, - struct scsi_cmnd *srb); -void rtsx_stor_get_xfer_buf(unsigned char *buffer, unsigned int buflen, - struct scsi_cmnd *srb); -void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip); - -#define rtsx_init_cmd(chip) ((chip)->ci = 0) - -void rtsx_add_cmd(struct rtsx_chip *chip, u8 cmd_type, u16 reg_addr, u8 mask, - u8 data); -void rtsx_send_cmd_no_wait(struct rtsx_chip *chip); -int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout); - -static inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip) -{ -#ifdef CMD_USING_SG - return (u8 *)(chip->host_sg_tbl_ptr); -#else - return (u8 *)(chip->host_cmds_ptr); -#endif -} - -int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len, - int use_sg, enum dma_data_direction dma_dir, - int timeout); - -int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf, - size_t len, int use_sg, unsigned int *index, - unsigned int *offset, - enum dma_data_direction dma_dir, int timeout); - -#endif /* __REALTEK_RTSX_TRANSPORT_H */ diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c deleted file mode 100644 index 74c4f476b3a4a12449b8283ffb7f8ac86947df64..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/sd.c +++ /dev/null @@ -1,4717 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> - -#include "rtsx.h" -#include "sd.h" - -#define SD_MAX_RETRY_COUNT 3 - -static u16 REG_SD_CFG1; -static u16 REG_SD_CFG2; -static u16 REG_SD_CFG3; -static u16 REG_SD_STAT1; -static u16 REG_SD_STAT2; -static u16 REG_SD_BUS_STAT; -static u16 REG_SD_PAD_CTL; -static u16 REG_SD_SAMPLE_POINT_CTL; -static u16 REG_SD_PUSH_POINT_CTL; -static u16 REG_SD_CMD0; -static u16 REG_SD_CMD1; -static u16 REG_SD_CMD2; -static u16 REG_SD_CMD3; -static u16 REG_SD_CMD4; -static u16 REG_SD_CMD5; -static u16 REG_SD_BYTE_CNT_L; -static u16 REG_SD_BYTE_CNT_H; -static u16 REG_SD_BLOCK_CNT_L; -static u16 REG_SD_BLOCK_CNT_H; -static u16 REG_SD_TRANSFER; -static u16 REG_SD_VPCLK0_CTL; -static u16 REG_SD_VPCLK1_CTL; -static u16 REG_SD_DCMPS0_CTL; -static u16 REG_SD_DCMPS1_CTL; - -static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &chip->sd_card; - - sd_card->err_code |= err_code; -} - -static inline void sd_clr_err_code(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - - sd_card->err_code = 0; -} - -static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct sd_info *sd_card = &chip->sd_card; - - return sd_card->err_code & err_code; -} - -static void sd_init_reg_addr(struct rtsx_chip *chip) -{ - REG_SD_CFG1 = 0xFD31; - REG_SD_CFG2 = 0xFD33; - REG_SD_CFG3 = 0xFD3E; - REG_SD_STAT1 = 0xFD30; - REG_SD_STAT2 = 0; - REG_SD_BUS_STAT = 0; - REG_SD_PAD_CTL = 0; - REG_SD_SAMPLE_POINT_CTL = 0; - REG_SD_PUSH_POINT_CTL = 0; - REG_SD_CMD0 = 0xFD34; - REG_SD_CMD1 = 0xFD35; - REG_SD_CMD2 = 0xFD36; - REG_SD_CMD3 = 0xFD37; - REG_SD_CMD4 = 0xFD38; - REG_SD_CMD5 = 0xFD5A; - REG_SD_BYTE_CNT_L = 0xFD39; - REG_SD_BYTE_CNT_H = 0xFD3A; - REG_SD_BLOCK_CNT_L = 0xFD3B; - REG_SD_BLOCK_CNT_H = 0xFD3C; - REG_SD_TRANSFER = 0xFD32; - REG_SD_VPCLK0_CTL = 0; - REG_SD_VPCLK1_CTL = 0; - REG_SD_DCMPS0_CTL = 0; - REG_SD_DCMPS1_CTL = 0; -} - -static int sd_check_data0_status(struct rtsx_chip *chip) -{ - int retval; - u8 stat; - - retval = rtsx_read_register(chip, REG_SD_STAT1, &stat); - if (retval) - return retval; - - if (!(stat & SD_DAT0_STATUS)) { - sd_set_err_code(chip, SD_BUSY); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int timeout = 100; - u16 reg_addr; - u8 *ptr; - int stat_idx = 0; - int rty_cnt = 0; - - sd_clr_err_code(chip); - - dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg); - - if (rsp_type == SD_RSP_TYPE_R1b) - timeout = 3000; - -RTY_SEND_CMD: - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | - SD_STAT_IDLE); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 16; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 5; - } - - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - u8 val; - - rtsx_read_register(chip, REG_SD_STAT1, &val); - dev_dbg(rtsx_dev(chip), "SD_STAT1: 0x%x\n", val); - - rtsx_read_register(chip, REG_SD_CFG3, &val); - dev_dbg(rtsx_dev(chip), "SD_CFG3: 0x%x\n", val); - - if (retval == -ETIMEDOUT) { - if (rsp_type & SD_WAIT_BUSY_END) { - retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - return retval; - } - } else { - sd_set_err_code(chip, SD_TO_ERR); - } - retval = STATUS_TIMEDOUT; - } else { - retval = STATUS_FAIL; - } - rtsx_clear_sd_error(chip); - - return retval; - } - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - ptr = rtsx_get_cmd_data(chip) + 1; - - if ((ptr[0] & 0xC0) != 0) { - sd_set_err_code(chip, SD_STS_ERR); - return STATUS_FAIL; - } - - if (!(rsp_type & SD_NO_CHECK_CRC7)) { - if (ptr[stat_idx] & SD_CRC7_ERR) { - if (cmd_idx == WRITE_MULTIPLE_BLOCK) { - sd_set_err_code(chip, SD_CRC_ERR); - return STATUS_FAIL; - } - if (rty_cnt < SD_MAX_RETRY_COUNT) { - wait_timeout(20); - rty_cnt++; - goto RTY_SEND_CMD; - } else { - sd_set_err_code(chip, SD_CRC_ERR); - return STATUS_FAIL; - } - } - } - - if (rsp_type == SD_RSP_TYPE_R1 || rsp_type == SD_RSP_TYPE_R1b) { - if (cmd_idx != SEND_RELATIVE_ADDR && - cmd_idx != SEND_IF_COND) { - if (cmd_idx != STOP_TRANSMISSION) { - if (ptr[1] & 0x80) - return STATUS_FAIL; - } -#ifdef SUPPORT_SD_LOCK - if (ptr[1] & 0x7D) { -#else - if (ptr[1] & 0x7F) { -#endif - dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n", - ptr[1]); - return STATUS_FAIL; - } - if (ptr[2] & 0xFF) { - dev_dbg(rtsx_dev(chip), "ptr[2]: 0x%02x\n", - ptr[2]); - return STATUS_FAIL; - } - if (ptr[3] & 0x80) { - dev_dbg(rtsx_dev(chip), "ptr[3]: 0x%02x\n", - ptr[3]); - return STATUS_FAIL; - } - if (ptr[3] & 0x01) - sd_card->sd_data_buf_ready = 1; - else - sd_card->sd_data_buf_ready = 0; - } - } - - if (rsp && rsp_len) - memcpy(rsp, ptr, rsp_len); - - return STATUS_SUCCESS; -} - -static int sd_read_data(struct rtsx_chip *chip, - u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt, - u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len, - int timeout) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i; - - sd_clr_err_code(chip); - - if (!buf) - buf_len = 0; - - if (buf_len > 512) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - if (cmd_len) { - dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (min(cmd_len, 6)); i++) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, - 0xFF, cmd[i]); - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - (u8)byte_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - (u8)(byte_cnt >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - (u8)blk_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - (u8)(blk_cnt >> 8)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - if (trans_mode != SD_TM_AUTO_TUNING) - rtsx_add_cmd(chip, WRITE_REG_CMD, - CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - trans_mode | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - return STATUS_FAIL; - } - - if (buf && buf_len) { - retval = rtsx_read_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode, - u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, - u8 bus_width, u8 *buf, int buf_len, int timeout) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i; - - sd_clr_err_code(chip); - - if (!buf) - buf_len = 0; - - if (buf_len > 512) { - /* This function can't write data more than one page */ - return STATUS_FAIL; - } - - if (buf && buf_len) { - retval = rtsx_write_ppbuf(chip, buf, buf_len); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - rtsx_init_cmd(chip); - - if (cmd_len) { - dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40); - for (i = 0; i < (min(cmd_len, 6)); i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - REG_SD_CMD0 + i, 0xFF, cmd[i]); - } - } - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - (u8)byte_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - (u8)(byte_cnt >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - (u8)blk_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - (u8)(blk_cnt >> 8)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - trans_mode | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_check_csd(struct rtsx_chip *chip, char check_wp) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i; - u8 csd_ver, trans_speed; - u8 rsp[16]; - - for (i = 0; i < 6; i++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - return STATUS_FAIL; - } - - retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, - SD_RSP_TYPE_R2, rsp, 16); - if (retval == STATUS_SUCCESS) - break; - } - - if (i == 6) - return STATUS_FAIL; - - memcpy(sd_card->raw_csd, rsp + 1, 15); - - dev_dbg(rtsx_dev(chip), "CSD Response:\n"); - dev_dbg(rtsx_dev(chip), "%*ph\n", 16, sd_card->raw_csd); - - csd_ver = (rsp[1] & 0xc0) >> 6; - dev_dbg(rtsx_dev(chip), "csd_ver = %d\n", csd_ver); - - trans_speed = rsp[4]; - if ((trans_speed & 0x07) == 0x02) { - if ((trans_speed & 0xf8) >= 0x30) { - if (chip->asic_code) - sd_card->sd_clock = 47; - else - sd_card->sd_clock = CLK_50; - - } else if ((trans_speed & 0xf8) == 0x28) { - if (chip->asic_code) - sd_card->sd_clock = 39; - else - sd_card->sd_clock = CLK_40; - - } else if ((trans_speed & 0xf8) == 0x20) { - if (chip->asic_code) - sd_card->sd_clock = 29; - else - sd_card->sd_clock = CLK_30; - - } else if ((trans_speed & 0xf8) >= 0x10) { - if (chip->asic_code) - sd_card->sd_clock = 23; - else - sd_card->sd_clock = CLK_20; - - } else if ((trans_speed & 0x08) >= 0x08) { - if (chip->asic_code) - sd_card->sd_clock = 19; - else - sd_card->sd_clock = CLK_20; - } else { - return STATUS_FAIL; - } - } else { - return STATUS_FAIL; - } - - if (CHK_MMC_SECTOR_MODE(sd_card)) { - sd_card->capacity = 0; - } else { - if ((!CHK_SD_HCXC(sd_card)) || csd_ver == 0) { - u8 blk_size, c_size_mult; - u16 c_size; - - blk_size = rsp[6] & 0x0F; - c_size = ((u16)(rsp[7] & 0x03) << 10) - + ((u16)rsp[8] << 2) - + ((u16)(rsp[9] & 0xC0) >> 6); - c_size_mult = (u8)((rsp[10] & 0x03) << 1); - c_size_mult += (rsp[11] & 0x80) >> 7; - sd_card->capacity = (((u32)(c_size + 1)) * - (1 << (c_size_mult + 2))) - << (blk_size - 9); - } else { - u32 total_sector = 0; - - total_sector = (((u32)rsp[8] & 0x3f) << 16) | - ((u32)rsp[9] << 8) | (u32)rsp[10]; - sd_card->capacity = (total_sector + 1) << 10; - } - } - - if (check_wp) { - if (rsp[15] & 0x30) - chip->card_wp |= SD_CARD; - - dev_dbg(rtsx_dev(chip), "CSD WP Status: 0x%x\n", rsp[15]); - } - - return STATUS_SUCCESS; -} - -static int sd_set_sample_push_timing(struct rtsx_chip *chip) -{ - int retval; - struct sd_info *sd_card = &chip->sd_card; - u8 val = 0; - - if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) - val |= 0x10; - - if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) { - if (chip->asic_code) { - if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) { - if (val & 0x10) - val |= 0x04; - else - val |= 0x08; - } - } else { - if (val & 0x10) - val |= 0x04; - else - val |= 0x08; - } - } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == - SD_SAMPLE_POINT_DELAY) { - if (val & 0x10) - val |= 0x04; - else - val |= 0x08; - } - - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x1C, val); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static void sd_choose_proper_clock(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - - if (CHK_SD_SDR104(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_sdr104_clk; - else - sd_card->sd_clock = chip->fpga_sd_sdr104_clk; - - } else if (CHK_SD_DDR50(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_ddr50_clk; - else - sd_card->sd_clock = chip->fpga_sd_ddr50_clk; - - } else if (CHK_SD_SDR50(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_sdr50_clk; - else - sd_card->sd_clock = chip->fpga_sd_sdr50_clk; - - } else if (CHK_SD_HS(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_sd_hs_clk; - else - sd_card->sd_clock = chip->fpga_sd_hs_clk; - - } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = chip->asic_mmc_52m_clk; - else - sd_card->sd_clock = chip->fpga_mmc_52m_clk; - - } else if (CHK_MMC_26M(sd_card)) { - if (chip->asic_code) - sd_card->sd_clock = 48; - else - sd_card->sd_clock = CLK_50; - } -} - -static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div) -{ - int retval; - u8 mask = 0, val = 0; - - mask = 0x60; - if (clk_div == SD_CLK_DIVIDE_0) - val = 0x00; - else if (clk_div == SD_CLK_DIVIDE_128) - val = 0x40; - else if (clk_div == SD_CLK_DIVIDE_256) - val = 0x20; - - retval = rtsx_write_register(chip, REG_SD_CFG1, mask, val); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int sd_set_init_para(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - sd_choose_proper_clock(chip); - - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int sd_select_card(struct rtsx_chip *chip, int select) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd_idx, cmd_type; - u32 addr; - - if (select) { - cmd_idx = SELECT_CARD; - cmd_type = SD_RSP_TYPE_R1; - addr = sd_card->sd_addr; - } else { - cmd_idx = DESELECT_CARD; - cmd_type = SD_RSP_TYPE_R0; - addr = 0; - } - - retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -#ifdef SUPPORT_SD_LOCK -static int sd_update_lock_status(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 rsp[5]; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, rsp, 5); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (rsp[1] & 0x02) - sd_card->sd_lock_status |= SD_LOCKED; - else - sd_card->sd_lock_status &= ~SD_LOCKED; - - dev_dbg(rtsx_dev(chip), "sd_card->sd_lock_status = 0x%x\n", - sd_card->sd_lock_status); - - if (rsp[1] & 0x01) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} -#endif - -static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, - u8 data_ready, int polling_cnt) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval, i; - u8 rsp[5]; - - for (i = 0; i < polling_cnt; i++) { - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, - rsp, 5); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (((rsp[3] & 0x1E) == state) && - ((rsp[3] & 0x01) == data_ready)) - return STATUS_SUCCESS; - } - - return STATUS_FAIL; -} - -static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage) -{ - int retval; - - if (voltage == SD_IO_3V3) { - if (chip->asic_code) { - retval = rtsx_write_phy_register(chip, 0x08, - 0x4FC0 | - chip->phy_voltage); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, SD_PAD_CTL, - SD_IO_USING_1V8, 0); - if (retval) - return retval; - } - } else if (voltage == SD_IO_1V8) { - if (chip->asic_code) { - retval = rtsx_write_phy_register(chip, 0x08, - 0x4C40 | - chip->phy_voltage); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, SD_PAD_CTL, - SD_IO_USING_1V8, - SD_IO_USING_1V8); - if (retval) - return retval; - } - } else { - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_voltage_switch(struct rtsx_chip *chip) -{ - int retval; - u8 stat; - - retval = rtsx_write_register(chip, SD_BUS_STAT, - SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, - SD_CLK_TOGGLE_EN); - if (retval) - return retval; - - retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - udelay(chip->sd_voltage_switch_delay); - - retval = rtsx_read_register(chip, SD_BUS_STAT, &stat); - if (retval) - return retval; - if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) { - return STATUS_FAIL; - } - - retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF, - SD_CLK_FORCE_STOP); - if (retval) - return retval; - retval = sd_change_bank_voltage(chip, SD_IO_1V8); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - wait_timeout(50); - - retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF, - SD_CLK_TOGGLE_EN); - if (retval) - return retval; - wait_timeout(10); - - retval = rtsx_read_register(chip, SD_BUS_STAT, &stat); - if (retval) - return retval; - if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) != - (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS | - SD_DAT1_STATUS | SD_DAT0_STATUS)) { - dev_dbg(rtsx_dev(chip), "SD_BUS_STAT: 0x%x\n", stat); - rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | - SD_CLK_FORCE_STOP, 0); - rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0); - return STATUS_FAIL; - } - - retval = rtsx_write_register(chip, SD_BUS_STAT, - SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir) -{ - int retval; - - if (tune_dir == TUNE_RX) { - retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, - DCM_RESET | DCM_RX); - if (retval) - return retval; - retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_RX); - if (retval) - return retval; - } else { - retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, - DCM_RESET | DCM_TX); - if (retval) - return retval; - retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_TX); - if (retval) - return retval; - } - - return STATUS_SUCCESS; -} - -static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir) -{ - struct sd_info *sd_card = &chip->sd_card; - u16 SD_VP_CTL, SD_DCMPS_CTL; - u8 val; - int retval; - bool ddr_rx = false; - - dev_dbg(rtsx_dev(chip), "%s (sample_point = %d, tune_dir = %d)\n", - __func__, sample_point, tune_dir); - - if (tune_dir == TUNE_RX) { - SD_VP_CTL = SD_VPRX_CTL; - SD_DCMPS_CTL = SD_DCMPS_RX_CTL; - if (CHK_SD_DDR50(sd_card)) - ddr_rx = true; - } else { - SD_VP_CTL = SD_VPTX_CTL; - SD_DCMPS_CTL = SD_DCMPS_TX_CTL; - } - - if (chip->asic_code) { - retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK, - CHANGE_CLK); - if (retval) - return retval; - retval = rtsx_write_register(chip, SD_VP_CTL, 0x1F, - sample_point); - if (retval) - return retval; - retval = rtsx_write_register(chip, SD_VPCLK0_CTL, - PHASE_NOT_RESET, 0); - if (retval) - return retval; - retval = rtsx_write_register(chip, SD_VPCLK0_CTL, - PHASE_NOT_RESET, PHASE_NOT_RESET); - if (retval) - return retval; - retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK, 0); - if (retval) - return retval; - } else { - rtsx_read_register(chip, SD_VP_CTL, &val); - dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val); - rtsx_read_register(chip, SD_DCMPS_CTL, &val); - dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val); - - if (ddr_rx) { - retval = rtsx_write_register(chip, SD_VP_CTL, - PHASE_CHANGE, - PHASE_CHANGE); - if (retval) - return retval; - udelay(50); - retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF, - PHASE_CHANGE | - PHASE_NOT_RESET | - sample_point); - if (retval) - return retval; - } else { - retval = rtsx_write_register(chip, CLK_CTL, - CHANGE_CLK, CHANGE_CLK); - if (retval) - return retval; - udelay(50); - retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF, - PHASE_NOT_RESET | - sample_point); - if (retval) - return retval; - } - udelay(100); - - rtsx_init_cmd(chip); - rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, - DCMPS_CHANGE); - rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, - DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE); - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval != STATUS_SUCCESS) - goto fail; - - val = *rtsx_get_cmd_data(chip); - if (val & DCMPS_ERROR) - goto fail; - - if ((val & DCMPS_CURRENT_PHASE) != sample_point) - goto fail; - - retval = rtsx_write_register(chip, SD_DCMPS_CTL, - DCMPS_CHANGE, 0); - if (retval) - return retval; - if (ddr_rx) { - retval = rtsx_write_register(chip, SD_VP_CTL, - PHASE_CHANGE, 0); - if (retval) - return retval; - } else { - retval = rtsx_write_register(chip, CLK_CTL, - CHANGE_CLK, 0); - if (retval) - return retval; - } - - udelay(50); - } - - retval = rtsx_write_register(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); - if (retval) - return retval; - - return STATUS_SUCCESS; - -fail: - rtsx_read_register(chip, SD_VP_CTL, &val); - dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val); - rtsx_read_register(chip, SD_DCMPS_CTL, &val); - dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val); - - rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0); - rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0); - mdelay(10); - sd_reset_dcm(chip, tune_dir); - return STATUS_FAIL; -} - -static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd[5], buf[8]; - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - cmd[0] = 0x40 | SEND_SCR; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, - buf, 8, 250); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - return STATUS_FAIL; - } - - memcpy(sd_card->raw_scr, buf, 8); - - if ((buf[0] & 0x0F) == 0) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, - u8 func_to_switch, u8 *buf, int buf_len) -{ - u8 support_mask = 0, query_switch = 0, switch_busy = 0; - int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0; - - if (func_group == SD_FUNC_GROUP_1) { - support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case HS_SUPPORT: - support_mask = HS_SUPPORT_MASK; - query_switch = HS_QUERY_SWITCH_OK; - switch_busy = HS_SWITCH_BUSY; - break; - - case SDR50_SUPPORT: - support_mask = SDR50_SUPPORT_MASK; - query_switch = SDR50_QUERY_SWITCH_OK; - switch_busy = SDR50_SWITCH_BUSY; - break; - - case SDR104_SUPPORT: - support_mask = SDR104_SUPPORT_MASK; - query_switch = SDR104_QUERY_SWITCH_OK; - switch_busy = SDR104_SWITCH_BUSY; - break; - - case DDR50_SUPPORT: - support_mask = DDR50_SUPPORT_MASK; - query_switch = DDR50_QUERY_SWITCH_OK; - switch_busy = DDR50_SWITCH_BUSY; - break; - - default: - return STATUS_FAIL; - } - } else if (func_group == SD_FUNC_GROUP_3) { - support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case DRIVING_TYPE_A: - support_mask = DRIVING_TYPE_A_MASK; - query_switch = TYPE_A_QUERY_SWITCH_OK; - switch_busy = TYPE_A_SWITCH_BUSY; - break; - - case DRIVING_TYPE_C: - support_mask = DRIVING_TYPE_C_MASK; - query_switch = TYPE_C_QUERY_SWITCH_OK; - switch_busy = TYPE_C_SWITCH_BUSY; - break; - - case DRIVING_TYPE_D: - support_mask = DRIVING_TYPE_D_MASK; - query_switch = TYPE_D_QUERY_SWITCH_OK; - switch_busy = TYPE_D_SWITCH_BUSY; - break; - - default: - return STATUS_FAIL; - } - } else if (func_group == SD_FUNC_GROUP_4) { - support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET; - query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET; - check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET; - - switch (func_to_switch) { - case CURRENT_LIMIT_400: - support_mask = CURRENT_LIMIT_400_MASK; - query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY; - break; - - case CURRENT_LIMIT_600: - support_mask = CURRENT_LIMIT_600_MASK; - query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY; - break; - - case CURRENT_LIMIT_800: - support_mask = CURRENT_LIMIT_800_MASK; - query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK; - switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY; - break; - - default: - return STATUS_FAIL; - } - } else { - return STATUS_FAIL; - } - - if (func_group == SD_FUNC_GROUP_1) { - if (!(buf[support_offset] & support_mask) || - ((buf[query_switch_offset] & 0x0F) != query_switch)) { - return STATUS_FAIL; - } - } - - /* Check 'Busy Status' */ - if (buf[DATA_STRUCTURE_VER_OFFSET] == 0x01 && - ((buf[check_busy_offset] & switch_busy) == switch_busy)) { - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, u8 func_group, - u8 func_to_switch, u8 bus_width) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd[5], buf[64]; - - dev_dbg(rtsx_dev(chip), "%s (mode = %d, func_group = %d, func_to_switch = %d)\n", - __func__, mode, func_group, func_to_switch); - - cmd[0] = 0x40 | SWITCH; - cmd[1] = mode; - - if (func_group == SD_FUNC_GROUP_1) { - cmd[2] = 0xFF; - cmd[3] = 0xFF; - cmd[4] = 0xF0 + func_to_switch; - } else if (func_group == SD_FUNC_GROUP_3) { - cmd[2] = 0xFF; - cmd[3] = 0xF0 + func_to_switch; - cmd[4] = 0xFF; - } else if (func_group == SD_FUNC_GROUP_4) { - cmd[2] = 0xFF; - cmd[3] = 0x0F + (func_to_switch << 4); - cmd[4] = 0xFF; - } else { - cmd[1] = SD_CHECK_MODE; - cmd[2] = 0xFF; - cmd[3] = 0xFF; - cmd[4] = 0xFF; - } - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, - buf, 64, 250); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - return STATUS_FAIL; - } - - dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf); - - if (func_group == NO_ARGUMENT) { - sd_card->func_group1_mask = buf[0x0D]; - sd_card->func_group2_mask = buf[0x0B]; - sd_card->func_group3_mask = buf[0x09]; - sd_card->func_group4_mask = buf[0x07]; - - dev_dbg(rtsx_dev(chip), "func_group1_mask = 0x%02x\n", - buf[0x0D]); - dev_dbg(rtsx_dev(chip), "func_group2_mask = 0x%02x\n", - buf[0x0B]); - dev_dbg(rtsx_dev(chip), "func_group3_mask = 0x%02x\n", - buf[0x09]); - dev_dbg(rtsx_dev(chip), "func_group4_mask = 0x%02x\n", - buf[0x07]); - } else { - /* Maximum current consumption, check whether current is - * acceptable; bit[511:496] = 0x0000 means some error happened. - */ - u16 cc = ((u16)buf[0] << 8) | buf[1]; - - dev_dbg(rtsx_dev(chip), "Maximum current consumption: %dmA\n", - cc); - if (cc == 0 || cc > 800) - return STATUS_FAIL; - - retval = sd_query_switch_result(chip, func_group, - func_to_switch, buf, 64); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (cc > 400 || func_to_switch > CURRENT_LIMIT_400) { - retval = rtsx_write_register(chip, OCPPARA2, - SD_OCP_THD_MASK, - chip->sd_800mA_ocp_thd); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PWR_CTL, - PMOS_STRG_MASK, - PMOS_STRG_800mA); - if (retval) - return retval; - } - } - - return STATUS_SUCCESS; -} - -static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch) -{ - if (func_group == SD_FUNC_GROUP_1) { - if (func_to_switch > HS_SUPPORT) - func_to_switch--; - - } else if (func_group == SD_FUNC_GROUP_4) { - if (func_to_switch > CURRENT_LIMIT_200) - func_to_switch--; - } - - return func_to_switch; -} - -static int sd_check_switch(struct rtsx_chip *chip, - u8 func_group, u8 func_to_switch, u8 bus_width) -{ - int retval; - int i; - bool switch_good = false; - - for (i = 0; i < 3; i++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - return STATUS_FAIL; - } - - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group, - func_to_switch, bus_width); - if (retval == STATUS_SUCCESS) { - u8 stat; - - retval = sd_check_switch_mode(chip, SD_SWITCH_MODE, - func_group, - func_to_switch, - bus_width); - if (retval == STATUS_SUCCESS) { - switch_good = true; - break; - } - - retval = rtsx_read_register(chip, SD_STAT1, &stat); - if (retval) - return retval; - if (stat & SD_CRC16_ERR) { - dev_dbg(rtsx_dev(chip), "SD CRC16 error when switching mode\n"); - return STATUS_FAIL; - } - } - - func_to_switch = downgrade_switch_mode(func_group, - func_to_switch); - - wait_timeout(20); - } - - if (!switch_good) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i; - u8 func_to_switch = 0; - - /* Get supported functions */ - retval = sd_check_switch_mode(chip, SD_CHECK_MODE, NO_ARGUMENT, - NO_ARGUMENT, bus_width); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail); - - /* Function Group 1: Access Mode */ - for (i = 0; i < 4; i++) { - switch ((u8)(chip->sd_speed_prior >> (i * 8))) { - case SDR104_SUPPORT: - if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) && - chip->sdr104_en) { - func_to_switch = SDR104_SUPPORT; - } - break; - - case DDR50_SUPPORT: - if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) && - chip->ddr50_en) { - func_to_switch = DDR50_SUPPORT; - } - break; - - case SDR50_SUPPORT: - if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) && - chip->sdr50_en) { - func_to_switch = SDR50_SUPPORT; - } - break; - - case HS_SUPPORT: - if (sd_card->func_group1_mask & HS_SUPPORT_MASK) - func_to_switch = HS_SUPPORT; - - break; - - default: - continue; - } - - if (func_to_switch) - break; - } - dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_1: func_to_switch = 0x%02x", - func_to_switch); - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_SDR_RST) && - func_to_switch == DDR50_SUPPORT && - (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) { - func_to_switch = SDR50_SUPPORT; - dev_dbg(rtsx_dev(chip), "Using SDR50 instead of DDR50 for SD Lock\n"); - } -#endif - - if (func_to_switch) { - retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, - bus_width); - if (retval != STATUS_SUCCESS) { - if (func_to_switch == SDR104_SUPPORT) { - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK; - } else if (func_to_switch == DDR50_SUPPORT) { - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | - DDR50_SUPPORT_MASK; - } else if (func_to_switch == SDR50_SUPPORT) { - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | - DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK; - } - return STATUS_FAIL; - } - - if (func_to_switch == SDR104_SUPPORT) - SET_SD_SDR104(sd_card); - else if (func_to_switch == DDR50_SUPPORT) - SET_SD_DDR50(sd_card); - else if (func_to_switch == SDR50_SUPPORT) - SET_SD_SDR50(sd_card); - else - SET_SD_HS(sd_card); - } - - if (CHK_SD_DDR50(sd_card)) { - retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06, - 0x04); - if (retval) - return retval; - retval = sd_set_sample_push_timing(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - if (!func_to_switch || func_to_switch == HS_SUPPORT) { - /* Do not try to switch current limit if the card doesn't - * support UHS mode or we don't want it to support UHS mode - */ - return STATUS_SUCCESS; - } - - /* Function Group 4: Current Limit */ - func_to_switch = 0xFF; - - for (i = 0; i < 4; i++) { - switch ((u8)(chip->sd_current_prior >> (i * 8))) { - case CURRENT_LIMIT_800: - if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) - func_to_switch = CURRENT_LIMIT_800; - - break; - - case CURRENT_LIMIT_600: - if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) - func_to_switch = CURRENT_LIMIT_600; - - break; - - case CURRENT_LIMIT_400: - if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) - func_to_switch = CURRENT_LIMIT_400; - - break; - - case CURRENT_LIMIT_200: - if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) - func_to_switch = CURRENT_LIMIT_200; - - break; - - default: - continue; - } - - if (func_to_switch != 0xFF) - break; - } - - dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_4: func_to_switch = 0x%02x", - func_to_switch); - - if (func_to_switch <= CURRENT_LIMIT_800) { - retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, - bus_width); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) - return STATUS_FAIL; - } - dev_dbg(rtsx_dev(chip), "Switch current limit finished! (%d)\n", - retval); - } - - if (CHK_SD_DDR50(sd_card)) { - retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06, 0); - if (retval) - return retval; - } - - return STATUS_SUCCESS; -} - -static int sd_wait_data_idle(struct rtsx_chip *chip) -{ - int retval = STATUS_TIMEDOUT; - int i; - u8 val = 0; - - for (i = 0; i < 100; i++) { - retval = rtsx_read_register(chip, SD_DATA_STATE, &val); - if (retval) - return retval; - if (val & SD_DATA_IDLE) { - retval = STATUS_SUCCESS; - break; - } - udelay(100); - } - dev_dbg(rtsx_dev(chip), "SD_DATA_STATE: 0x%02x\n", val); - - return retval; -} - -static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - int retval; - u8 cmd[5]; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - cmd[0] = 0x40 | SEND_TUNING_PATTERN; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_AUTO_TUNING, cmd, 5, 0x40, 1, - SD_BUS_WIDTH_4, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - (void)sd_wait_data_idle(chip); - - rtsx_clear_sd_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd[5]; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "sd ddr tuning rx\n"); - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - cmd[0] = 0x40 | SD_STATUS; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, - SD_BUS_WIDTH_4, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - (void)sd_wait_data_idle(chip); - - rtsx_clear_sd_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int mmc_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd[5], bus_width; - - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - - retval = sd_change_phase(chip, sample_point, TUNE_RX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "mmc ddr tuning rx\n"); - - cmd[0] = 0x40 | SEND_EXT_CSD; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 0x200, 1, - bus_width, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - (void)sd_wait_data_idle(chip); - - rtsx_clear_sd_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - SD_RSP_80CLK_TIMEOUT_EN); - if (retval) - return retval; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) { - rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - return STATUS_FAIL; - } - } - - retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - 0); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd[5], bus_width; - - retval = sd_change_phase(chip, sample_point, TUNE_TX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (CHK_SD(sd_card)) { - bus_width = SD_BUS_WIDTH_4; - } else { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } - - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - SD_RSP_80CLK_TIMEOUT_EN); - if (retval) - return retval; - - cmd[0] = 0x40 | PROGRAM_CSD; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, cmd, 5, 16, 1, - bus_width, sd_card->raw_csd, 16, 100); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0); - return STATUS_FAIL; - } - - retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - 0); - if (retval) - return retval; - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - - return STATUS_SUCCESS; -} - -static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, - u8 tune_dir) -{ - struct sd_info *sd_card = &chip->sd_card; - struct timing_phase_path path[MAX_PHASE + 1]; - int i, j, cont_path_cnt; - bool new_block; - int max_len, final_path_idx; - u8 final_phase = 0xFF; - - if (phase_map == 0xFFFFFFFF) { - if (tune_dir == TUNE_RX) - final_phase = (u8)chip->sd_default_rx_phase; - else - final_phase = (u8)chip->sd_default_tx_phase; - - goto search_finish; - } - - cont_path_cnt = 0; - new_block = true; - j = 0; - for (i = 0; i < MAX_PHASE + 1; i++) { - if (phase_map & (1 << i)) { - if (new_block) { - new_block = false; - j = cont_path_cnt++; - path[j].start = i; - path[j].end = i; - } else { - path[j].end = i; - } - } else { - new_block = true; - if (cont_path_cnt) { - int idx = cont_path_cnt - 1; - - path[idx].len = path[idx].end - - path[idx].start + 1; - path[idx].mid = path[idx].start + - path[idx].len / 2; - } - } - } - - if (cont_path_cnt == 0) { - dev_dbg(rtsx_dev(chip), "No continuous phase path\n"); - goto search_finish; - } else { - int idx = cont_path_cnt - 1; - - path[idx].len = path[idx].end - path[idx].start + 1; - path[idx].mid = path[idx].start + path[idx].len / 2; - } - - if (path[0].start == 0 && - path[cont_path_cnt - 1].end == MAX_PHASE) { - path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1; - path[0].len += path[cont_path_cnt - 1].len; - path[0].mid = path[0].start + path[0].len / 2; - if (path[0].mid < 0) - path[0].mid += MAX_PHASE + 1; - - cont_path_cnt--; - } - - max_len = 0; - final_phase = 0; - final_path_idx = 0; - for (i = 0; i < cont_path_cnt; i++) { - if (path[i].len > max_len) { - max_len = path[i].len; - final_phase = (u8)path[i].mid; - final_path_idx = i; - } - - dev_dbg(rtsx_dev(chip), "path[%d].start = %d\n", - i, path[i].start); - dev_dbg(rtsx_dev(chip), "path[%d].end = %d\n", i, path[i].end); - dev_dbg(rtsx_dev(chip), "path[%d].len = %d\n", i, path[i].len); - dev_dbg(rtsx_dev(chip), "path[%d].mid = %d\n", i, path[i].mid); - dev_dbg(rtsx_dev(chip), "\n"); - } - - if (tune_dir == TUNE_TX) { - if (CHK_SD_SDR104(sd_card)) { - if (max_len > 15) { - int temp_mid = (max_len - 16) / 2; - int temp_final_phase = - path[final_path_idx].end - - (max_len - (6 + temp_mid)); - - if (temp_final_phase < 0) - final_phase = (u8)(temp_final_phase + - MAX_PHASE + 1); - else - final_phase = (u8)temp_final_phase; - } - } else if (CHK_SD_SDR50(sd_card)) { - if (max_len > 12) { - int temp_mid = (max_len - 13) / 2; - int temp_final_phase = - path[final_path_idx].end - - (max_len - (3 + temp_mid)); - - if (temp_final_phase < 0) - final_phase = (u8)(temp_final_phase + - MAX_PHASE + 1); - else - final_phase = (u8)temp_final_phase; - } - } - } - -search_finish: - dev_dbg(rtsx_dev(chip), "Final chosen phase: %d\n", final_phase); - return final_phase; -} - -static int sd_tuning_rx(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i, j; - u32 raw_phase_map[3], phase_map; - u8 final_phase; - int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); - - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - tuning_cmd = sd_ddr_tuning_rx_cmd; - else - tuning_cmd = sd_sdr_tuning_rx_cmd; - - } else { - if (CHK_MMC_DDR52(sd_card)) - tuning_cmd = mmc_ddr_tuning_rx_cmd; - else - return STATUS_FAIL; - } - - for (i = 0; i < 3; i++) { - raw_phase_map[i] = 0; - for (j = MAX_PHASE; j >= 0; j--) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - return STATUS_FAIL; - } - - retval = tuning_cmd(chip, (u8)j); - if (retval == STATUS_SUCCESS) - raw_phase_map[i] |= 1 << j; - } - } - - phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) - dev_dbg(rtsx_dev(chip), "RX raw_phase_map[%d] = 0x%08x\n", - i, raw_phase_map[i]); - - dev_dbg(rtsx_dev(chip), "RX phase_map = 0x%08x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX); - if (final_phase == 0xFF) - return STATUS_FAIL; - - retval = sd_change_phase(chip, final_phase, TUNE_RX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i; - u32 phase_map; - u8 final_phase; - - retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - SD_RSP_80CLK_TIMEOUT_EN); - if (retval) - return retval; - - phase_map = 0; - for (i = MAX_PHASE; i >= 0; i--) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - return STATUS_FAIL; - } - - retval = sd_change_phase(chip, (u8)i, TUNE_TX); - if (retval != STATUS_SUCCESS) - continue; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval == STATUS_SUCCESS || - !sd_check_err_code(chip, SD_RSP_TIMEOUT)) - phase_map |= 1 << i; - } - - retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, - 0); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase_map = 0x%08x\n", - phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) - return STATUS_FAIL; - - retval = sd_change_phase(chip, final_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase: %d\n", - (int)final_phase); - - return STATUS_SUCCESS; -} - -static int sd_tuning_tx(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int i, j; - u32 raw_phase_map[3], phase_map; - u8 final_phase; - int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point); - - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - tuning_cmd = sd_ddr_tuning_tx_cmd; - else - tuning_cmd = sd_sdr_tuning_tx_cmd; - - } else { - if (CHK_MMC_DDR52(sd_card)) - tuning_cmd = sd_ddr_tuning_tx_cmd; - else - return STATUS_FAIL; - } - - for (i = 0; i < 3; i++) { - raw_phase_map[i] = 0; - for (j = MAX_PHASE; j >= 0; j--) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - rtsx_write_register(chip, SD_CFG3, - SD_RSP_80CLK_TIMEOUT_EN, 0); - return STATUS_FAIL; - } - - retval = tuning_cmd(chip, (u8)j); - if (retval == STATUS_SUCCESS) - raw_phase_map[i] |= 1 << j; - } - } - - phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2]; - for (i = 0; i < 3; i++) - dev_dbg(rtsx_dev(chip), "TX raw_phase_map[%d] = 0x%08x\n", - i, raw_phase_map[i]); - - dev_dbg(rtsx_dev(chip), "TX phase_map = 0x%08x\n", phase_map); - - final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX); - if (final_phase == 0xFF) - return STATUS_FAIL; - - retval = sd_change_phase(chip, final_phase, TUNE_TX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_sdr_tuning(struct rtsx_chip *chip) -{ - int retval; - - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_ddr_tuning(struct rtsx_chip *chip) -{ - int retval; - - if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, - TUNE_TX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int mmc_ddr_tuning(struct rtsx_chip *chip) -{ - int retval; - - if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_ddr_pre_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, - TUNE_TX); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - retval = sd_tuning_rx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) { - retval = sd_tuning_tx(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int sd_switch_clock(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - int re_tuning = 0; - - retval = select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (re_tuning) { - if (CHK_SD(sd_card)) { - if (CHK_SD_DDR50(sd_card)) - retval = sd_ddr_tuning(chip); - else - retval = sd_sdr_tuning(chip); - } else { - if (CHK_MMC_DDR52(sd_card)) - retval = mmc_ddr_tuning(chip); - } - - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_prepare_reset(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - if (chip->asic_code) - sd_card->sd_clock = 29; - else - sd_card->sd_clock = CLK_30; - - sd_card->sd_type = 0; - sd_card->seq_mode = 0; - sd_card->sd_data_buf_ready = 0; - sd_card->capacity = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - chip->capacity[chip->card2lun[SD_CARD]] = 0; - chip->sd_io = 0; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return retval; - - retval = rtsx_write_register(chip, REG_SD_CFG1, 0xFF, 0x40); - if (retval) - return retval; - - retval = rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, - SD_STOP | SD_CLR_ERR); - if (retval) - return retval; - - retval = select_card(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_pull_ctl_disable(struct rtsx_chip *chip) -{ - int retval; - - if (CHECK_PID(chip, 0x5208)) { - retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | SD_D7_PD | SD_CLK_PD | - SD_D5_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, - SD_D6_PD | SD_D0_PD | SD_D1_PD | - XD_D5_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF, - SD_D4_PD | XD_CE_PD | XD_CLE_PD | - XD_CD_PU); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PD | SD_D2_PD | - XD_ALE_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | - SD_CMD_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - if (retval) - return retval; - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - retval = rtsx_write_register(chip, CARD_PULL_CTL1, - 0xFF, 0x55); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL2, - 0xFF, 0x55); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL3, - 0xFF, 0x4B); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL4, - 0xFF, 0x69); - if (retval) - return retval; - } - } - - return STATUS_SUCCESS; -} - -int sd_pull_ctl_enable(struct rtsx_chip *chip) -{ - int retval; - - rtsx_init_cmd(chip); - - if (CHECK_PID(chip, 0x5208)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - 0xA8); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - 0x5A); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - 0x95); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - 0xAA); - } - } - - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sd_init_power(struct rtsx_chip *chip) -{ - int retval; - - retval = sd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (!chip->ft2_fast_mode) - wait_timeout(250); - - retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (chip->asic_code) { - retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, 0); - if (retval) - return retval; - } - - if (!chip->ft2_fast_mode) { - retval = card_power_on(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - wait_timeout(260); - -#ifdef SUPPORT_OCP - if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { - dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - return STATUS_FAIL; - } -#endif - } - - retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, - SD_OUTPUT_EN); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int sd_dummy_clock(struct rtsx_chip *chip) -{ - int retval; - - retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0x01); - if (retval) - return retval; - wait_timeout(5); - retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int sd_read_lba0(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 cmd[5], bus_width; - - cmd[0] = 0x40 | READ_SINGLE_BLOCK; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - if (CHK_SD(sd_card)) { - bus_width = SD_BUS_WIDTH_4; - } else { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 512, 1, - bus_width, NULL, 0, 100); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sd_check_wp_state(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u32 val; - u16 sd_card_type; - u8 cmd[5], buf[64]; - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - cmd[0] = 0x40 | SD_STATUS; - cmd[1] = 0; - cmd[2] = 0; - cmd[3] = 0; - cmd[4] = 0; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, - SD_BUS_WIDTH_4, buf, 64, 250); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - return STATUS_FAIL; - } - - dev_dbg(rtsx_dev(chip), "ACMD13:\n"); - dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf); - - sd_card_type = ((u16)buf[2] << 8) | buf[3]; - dev_dbg(rtsx_dev(chip), "sd_card_type = 0x%04x\n", sd_card_type); - if (sd_card_type == 0x0001 || sd_card_type == 0x0002) { - /* ROM card or OTP */ - chip->card_wp |= SD_CARD; - } - - /* Check SD Machanical Write-Protect Switch */ - val = rtsx_readl(chip, RTSX_BIPR); - if (val & SD_WRITE_PROTECT) - chip->card_wp |= SD_CARD; - - return STATUS_SUCCESS; -} - -static int reset_sd(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - bool hi_cap_flow = false; - int retval, i = 0, j = 0, k = 0; - bool sd_dont_switch = false; - bool support_1v8 = false; - bool try_sdio = true; - u8 rsp[16]; - u8 switch_bus_width; - u32 voltage = 0; - bool sd20_mode = false; - - SET_SD(sd_card); - -switch_fail: - - i = 0; - j = 0; - k = 0; - hi_cap_flow = false; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) - goto SD_UNLOCK_ENTRY; -#endif - - retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - retval = sd_dummy_clock(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) { - int rty_cnt = 0; - - for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - goto status_fail; - } - - retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, - SD_RSP_TYPE_R4, rsp, 5); - if (retval == STATUS_SUCCESS) { - int func_num = (rsp[1] >> 4) & 0x07; - - if (func_num) { - dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n", - func_num); - chip->sd_io = 1; - goto status_fail; - } - - break; - } - - sd_init_power(chip); - - sd_dummy_clock(chip); - } - - dev_dbg(rtsx_dev(chip), "Normal card!\n"); - } - - /* Start Initialization Process of SD Card */ -RTY_SD_RST: - retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, - NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - wait_timeout(20); - - retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, - SD_RSP_TYPE_R7, rsp, 5); - if (retval == STATUS_SUCCESS) { - if (rsp[4] == 0xAA && ((rsp[3] & 0x0f) == 0x01)) { - hi_cap_flow = true; - voltage = SUPPORT_VOLTAGE | 0x40000000; - } - } - - if (!hi_cap_flow) { - voltage = SUPPORT_VOLTAGE; - - retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, - SD_RSP_TYPE_R0, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - wait_timeout(20); - } - - do { - retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - goto status_fail; - } - - j++; - if (j < 3) - goto RTY_SD_RST; - else - goto status_fail; - } - - retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, - SD_RSP_TYPE_R3, rsp, 5); - if (retval != STATUS_SUCCESS) { - k++; - if (k < 3) - goto RTY_SD_RST; - else - goto status_fail; - } - - i++; - wait_timeout(20); - } while (!(rsp[1] & 0x80) && (i < 255)); - - if (i == 255) - goto status_fail; - - if (hi_cap_flow) { - if (rsp[1] & 0x40) - SET_SD_HCXC(sd_card); - else - CLR_SD_HCXC(sd_card); - - support_1v8 = false; - } else { - CLR_SD_HCXC(sd_card); - support_1v8 = false; - } - dev_dbg(rtsx_dev(chip), "support_1v8 = %d\n", support_1v8); - - if (support_1v8) { - retval = sd_voltage_switch(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - } - - retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, - NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - for (i = 0; i < 3; i++) { - retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, - SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) - goto status_fail; - - sd_card->sd_addr = (u32)rsp[1] << 24; - sd_card->sd_addr += (u32)rsp[2] << 16; - - if (sd_card->sd_addr) - break; - } - - retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) - goto status_fail; - - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - goto status_fail; - -#ifdef SUPPORT_SD_LOCK -SD_UNLOCK_ENTRY: - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - if (sd_card->sd_lock_status & SD_LOCKED) { - sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST); - return STATUS_SUCCESS; - } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) { - sd_card->sd_lock_status &= ~SD_PWD_EXIST; - } -#endif - - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - if (support_1v8) { - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - switch_bus_width = SD_BUS_WIDTH_4; - } else { - switch_bus_width = SD_BUS_WIDTH_1; - } - - retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - if (!(sd_card->raw_csd[4] & 0x40)) - sd_dont_switch = true; - - if (!sd_dont_switch) { - if (sd20_mode) { - /* Set sd_switch_fail here, because we needn't - * switch to UHS mode - */ - sd_card->sd_switch_fail = SDR104_SUPPORT_MASK | - DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK; - } - - /* Check the card whether follow SD1.1 spec or higher */ - retval = sd_check_spec(chip, switch_bus_width); - if (retval == STATUS_SUCCESS) { - retval = sd_switch_function(chip, switch_bus_width); - if (retval != STATUS_SUCCESS) { - sd_init_power(chip); - sd_dont_switch = true; - try_sdio = false; - - goto switch_fail; - } - } else { - if (support_1v8) { - sd_init_power(chip); - sd_dont_switch = true; - try_sdio = false; - - goto switch_fail; - } - } - } - - if (!support_1v8) { - retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - - retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, - SD_RSP_TYPE_R1, NULL, 0); - if (retval != STATUS_SUCCESS) - goto status_fail; - } - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - - if (!sd20_mode && CHK_SD30_SPEED(sd_card)) { - int read_lba0 = 1; - - retval = rtsx_write_register(chip, SD30_DRIVE_SEL, 0x07, - chip->sd30_drive_sel_1v8); - if (retval) - return retval; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - if (CHK_SD_DDR50(sd_card)) - retval = sd_ddr_tuning(chip); - else - retval = sd_sdr_tuning(chip); - - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - try_sdio = false; - sd20_mode = true; - goto switch_fail; - } - - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - - if (CHK_SD_DDR50(sd_card)) { - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) - read_lba0 = 0; - } - - if (read_lba0) { - retval = sd_read_lba0(chip); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - try_sdio = false; - sd20_mode = true; - goto switch_fail; - } - } - } - - retval = sd_check_wp_state(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - - chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { - retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF, - 0x02); - if (retval) - return retval; - retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF, - 0x00); - if (retval) - return retval; - } -#endif - - return STATUS_SUCCESS; - -status_fail: - return STATUS_FAIL; -} - -static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 buf[8] = {0}, bus_width, *ptr; - u16 byte_cnt; - int len; - - retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, - 0); - if (retval != STATUS_SUCCESS) - return SWITCH_FAIL; - - if (width == MMC_8BIT_BUS) { - buf[0] = 0x55; - buf[1] = 0xAA; - len = 8; - byte_cnt = 8; - bus_width = SD_BUS_WIDTH_8; - } else { - buf[0] = 0x5A; - len = 4; - byte_cnt = 4; - bus_width = SD_BUS_WIDTH_4; - } - - retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02); - if (retval != STATUS_SUCCESS) - return SWITCH_ERR; - - retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, NULL, 0, byte_cnt, 1, - bus_width, buf, len, 100); - if (retval != STATUS_SUCCESS) { - rtsx_clear_sd_error(chip); - rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); - return SWITCH_ERR; - } - - retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0); - if (retval != STATUS_SUCCESS) - return SWITCH_ERR; - - dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", BUSTEST_R); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R); - - if (width == MMC_8BIT_BUS) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, - 0xFF, 0x08); - else - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, - 0xFF, 0x04); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, SD_CALCULATE_CRC7 | - SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_NORMAL_READ | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0); - if (width == MMC_8BIT_BUS) - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval < 0) { - rtsx_clear_sd_error(chip); - return SWITCH_ERR; - } - - ptr = rtsx_get_cmd_data(chip) + 1; - - if (width == MMC_8BIT_BUS) { - dev_dbg(rtsx_dev(chip), "BUSTEST_R [8bits]: 0x%02x 0x%02x\n", - ptr[0], ptr[1]); - if (ptr[0] == 0xAA && ptr[1] == 0x55) { - u8 rsp[5]; - u32 arg; - - if (CHK_MMC_DDR52(sd_card)) - arg = 0x03B70600; - else - arg = 0x03B70200; - - retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, - SD_RSP_TYPE_R1b, rsp, 5); - if (retval == STATUS_SUCCESS && - !(rsp[4] & MMC_SWITCH_ERR)) - return SWITCH_SUCCESS; - } - } else { - dev_dbg(rtsx_dev(chip), "BUSTEST_R [4bits]: 0x%02x\n", ptr[0]); - if (ptr[0] == 0xA5) { - u8 rsp[5]; - u32 arg; - - if (CHK_MMC_DDR52(sd_card)) - arg = 0x03B70500; - else - arg = 0x03B70100; - - retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, - SD_RSP_TYPE_R1b, rsp, 5); - if (retval == STATUS_SUCCESS && - !(rsp[4] & MMC_SWITCH_ERR)) - return SWITCH_SUCCESS; - } - } - - return SWITCH_FAIL; -} - -static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - u8 *ptr, card_type, card_type_mask = 0; - - CLR_MMC_HS(sd_card); - - dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", SEND_EXT_CSD); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, - 0x40 | SEND_EXT_CSD); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | - SD_CHECK_CRC7 | SD_RSP_LEN_6); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_NORMAL_READ | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0); - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, 1000); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - rtsx_clear_sd_error(chip); - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - return STATUS_FAIL; - } - - ptr = rtsx_get_cmd_data(chip); - if (ptr[0] & SD_TRANSFER_ERR) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - return STATUS_FAIL; - } - - if (CHK_MMC_SECTOR_MODE(sd_card)) { - sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) | - ((u32)ptr[3] << 8) | ((u32)ptr[2]); - } - - card_type_mask = 0x03; - card_type = ptr[1] & card_type_mask; - if (card_type) { - u8 rsp[5]; - - if (card_type & 0x04) { - if (switch_ddr) - SET_MMC_DDR52(sd_card); - else - SET_MMC_52M(sd_card); - } else if (card_type & 0x02) { - SET_MMC_52M(sd_card); - } else { - SET_MMC_26M(sd_card); - } - - retval = sd_send_cmd_get_rsp(chip, SWITCH, 0x03B90100, - SD_RSP_TYPE_R1b, rsp, 5); - if (retval != STATUS_SUCCESS || (rsp[4] & MMC_SWITCH_ERR)) - CLR_MMC_HS(sd_card); - } - - sd_choose_proper_clock(chip); - retval = switch_clock(chip, sd_card->sd_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - /* Test Bus Procedure */ - retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS); - if (retval == SWITCH_SUCCESS) { - SET_MMC_8BIT(sd_card); - chip->card_bus_width[chip->card2lun[SD_CARD]] = 8; -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - } else if (retval == SWITCH_FAIL) { - retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS); - if (retval == SWITCH_SUCCESS) { - SET_MMC_4BIT(sd_card); - chip->card_bus_width[chip->card2lun[SD_CARD]] = 4; -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE; -#endif - } else if (retval == SWITCH_FAIL) { - CLR_MMC_8BIT(sd_card); - CLR_MMC_4BIT(sd_card); - } else { - return STATUS_FAIL; - } - } else { - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int reset_mmc(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval, i = 0, j = 0, k = 0; - bool switch_ddr = true; - u8 rsp[16]; - u8 spec_ver = 0; - u32 temp; - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) - goto MMC_UNLOCK_ENTRY; -#endif - -switch_fail: - retval = sd_prepare_reset(chip); - if (retval != STATUS_SUCCESS) - return retval; - - SET_MMC(sd_card); - -RTY_MMC_RST: - retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, - NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - do { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - return STATUS_FAIL; - } - - retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND, - (SUPPORT_VOLTAGE | 0x40000000), - SD_RSP_TYPE_R3, rsp, 5); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_BUSY) || - sd_check_err_code(chip, SD_TO_ERR)) { - k++; - if (k < 20) { - sd_clr_err_code(chip); - goto RTY_MMC_RST; - } else { - return STATUS_FAIL; - } - } else { - j++; - if (j < 100) { - sd_clr_err_code(chip); - goto RTY_MMC_RST; - } else { - return STATUS_FAIL; - } - } - } - - wait_timeout(20); - i++; - } while (!(rsp[1] & 0x80) && (i < 255)); - - if (i == 255) - return STATUS_FAIL; - - if ((rsp[1] & 0x60) == 0x40) - SET_MMC_SECTOR_MODE(sd_card); - else - CLR_MMC_SECTOR_MODE(sd_card); - - retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, - NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - sd_card->sd_addr = 0x00100000; - retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, - SD_RSP_TYPE_R6, rsp, 5); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sd_check_csd(chip, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2; - - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - -#ifdef SUPPORT_SD_LOCK -MMC_UNLOCK_ENTRY: - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; -#endif - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - chip->card_bus_width[chip->card2lun[SD_CARD]] = 1; - - if (!sd_card->mmc_dont_switch_bus) { - if (spec_ver == 4) { - /* MMC 4.x Cards */ - retval = mmc_switch_timing_bus(chip, switch_ddr); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - sd_card->mmc_dont_switch_bus = 1; - goto switch_fail; - } - } - - if (CHK_MMC_SECTOR_MODE(sd_card) && sd_card->capacity == 0) - return STATUS_FAIL; - - if (switch_ddr && CHK_MMC_DDR52(sd_card)) { - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = mmc_ddr_tuning(chip); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - switch_ddr = false; - goto switch_fail; - } - - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval == STATUS_SUCCESS) { - retval = sd_read_lba0(chip); - if (retval != STATUS_SUCCESS) { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - switch_ddr = false; - goto switch_fail; - } - } - } - } - -#ifdef SUPPORT_SD_LOCK - if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) { - retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF, - 0x02); - if (retval) - return retval; - retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF, - 0x00); - if (retval) - return retval; - } -#endif - - temp = rtsx_readl(chip, RTSX_BIPR); - if (temp & SD_WRITE_PROTECT) - chip->card_wp |= SD_CARD; - - return STATUS_SUCCESS; -} - -int reset_sd_card(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - sd_init_reg_addr(chip); - - memset(sd_card, 0, sizeof(struct sd_info)); - chip->capacity[chip->card2lun[SD_CARD]] = 0; - - retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && - !CHK_SDIO_IGNORED(chip)) { - if (chip->asic_code) { - retval = sd_pull_ctl_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | - 0x20, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - retval = card_share_mode(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - chip->sd_io = 1; - return STATUS_FAIL; - } - - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (chip->sd_ctl & RESET_MMC_FIRST) { - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) - return STATUS_FAIL; - - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - } else { - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - if (sd_check_err_code(chip, SD_NO_CARD)) - return STATUS_FAIL; - - if (chip->sd_io) - return STATUS_FAIL; - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - } - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); - if (retval) - return retval; - retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); - if (retval) - return retval; - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "sd_card->sd_type = 0x%x\n", sd_card->sd_type); - - return STATUS_SUCCESS; -} - -static int reset_mmc_only(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - sd_card->sd_type = 0; - sd_card->seq_mode = 0; - sd_card->sd_data_buf_ready = 0; - sd_card->capacity = 0; - sd_card->sd_switch_fail = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0; - - retval = enable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = reset_mmc(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0); - if (retval) - return retval; - retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2); - if (retval) - return retval; - - chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity; - - retval = sd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "In %s, sd_card->sd_type = 0x%x\n", - __func__, sd_card->sd_type); - - return STATUS_SUCCESS; -} - -#define WAIT_DATA_READY_RTY_CNT 255 - -static int wait_data_buf_ready(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int i, retval; - - for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) { - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_NO_CARD); - return STATUS_FAIL; - } - - sd_card->sd_data_buf_ready = 0; - - retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (sd_card->sd_data_buf_ready) { - return sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0); - } - } - - sd_set_err_code(chip, SD_TO_ERR); - - return STATUS_FAIL; -} - -void sd_stop_seq_mode(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - if (sd_card->seq_mode) { - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return; - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) - sd_set_err_code(chip, SD_STS_ERR); - - retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000); - if (retval != STATUS_SUCCESS) - sd_set_err_code(chip, SD_STS_ERR); - - sd_card->seq_mode = 0; - - rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - } -} - -static inline int sd_auto_tune_clock(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - if (chip->asic_code) { - if (sd_card->sd_clock > 30) - sd_card->sd_clock -= 20; - } else { - switch (sd_card->sd_clock) { - case CLK_200: - sd_card->sd_clock = CLK_150; - break; - - case CLK_150: - sd_card->sd_clock = CLK_120; - break; - - case CLK_120: - sd_card->sd_clock = CLK_100; - break; - - case CLK_100: - sd_card->sd_clock = CLK_80; - break; - - case CLK_80: - sd_card->sd_clock = CLK_60; - break; - - case CLK_60: - sd_card->sd_clock = CLK_50; - break; - - default: - break; - } - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, - u16 sector_cnt) -{ - struct sd_info *sd_card = &chip->sd_card; - u32 data_addr; - u8 cfg2; - int retval; - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - dev_dbg(rtsx_dev(chip), "%s: Read %d %s from 0x%x\n", __func__, - sector_cnt, (sector_cnt > 1) ? "sectors" : "sector", - start_sector); - } else { - dev_dbg(rtsx_dev(chip), "%s: Write %d %s to 0x%x\n", __func__, - sector_cnt, (sector_cnt > 1) ? "sectors" : "sector", - start_sector); - } - - sd_card->cleanup_counter = 0; - - if (!(chip->card_ready & SD_CARD)) { - sd_card->seq_mode = 0; - - retval = reset_sd_card(chip); - if (retval == STATUS_SUCCESS) { - chip->card_ready |= SD_CARD; - chip->card_fail &= ~SD_CARD; - } else { - chip->card_ready &= ~SD_CARD; - chip->card_fail |= SD_CARD; - chip->capacity[chip->card2lun[SD_CARD]] = 0; - chip->rw_need_retry = 1; - return STATUS_FAIL; - } - } - - if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) - data_addr = start_sector << 9; - else - data_addr = start_sector; - - sd_clr_err_code(chip); - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_IO_ERR); - goto RW_FAIL; - } - - if (sd_card->seq_mode && - (sd_card->pre_dir != srb->sc_data_direction || - ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != - start_sector))) { - if (sd_card->pre_sec_cnt < 0x80 && - sd_card->pre_dir == DMA_FROM_DEVICE && - !CHK_SD30_SPEED(sd_card) && - !CHK_SD_HS(sd_card) && - !CHK_MMC_HS(sd_card)) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) { - chip->rw_need_retry = 1; - sd_set_err_code(chip, SD_STS_ERR); - goto RW_FAIL; - } - - sd_card->seq_mode = 0; - - retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_IO_ERR); - goto RW_FAIL; - } - - if (sd_card->pre_sec_cnt < 0x80 && - !CHK_SD30_SPEED(sd_card) && - !CHK_SD_HS(sd_card) && - !CHK_MMC_HS(sd_card)) { - sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0); - } - } - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - (u8)sector_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - (u8)(sector_cnt >> 8)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - - if (CHK_MMC_8BIT(sd_card)) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, - 0x03, SD_BUS_WIDTH_8); - else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, - 0x03, SD_BUS_WIDTH_4); - else - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, - 0x03, SD_BUS_WIDTH_1); - - if (sd_card->seq_mode) { - cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | - SD_RSP_LEN_0; - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2); - - trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, - DMA_512); - - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_3 | SD_TRANSFER_START); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - } - - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - } else { - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", - READ_MULTIPLE_BLOCK); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, - 0x40 | READ_MULTIPLE_BLOCK); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, - (u8)(data_addr >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, - (u8)(data_addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, - (u8)(data_addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, - (u8)data_addr); - - cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | - SD_RSP_LEN_6; - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - cfg2); - - trans_dma_enable(srb->sc_data_direction, chip, - sector_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_READ_2 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - } else { - retval = rtsx_send_cmd(chip, SD_CARD, 50); - if (retval < 0) { - rtsx_clear_sd_error(chip); - - chip->rw_need_retry = 1; - sd_set_err_code(chip, SD_TO_ERR); - goto RW_FAIL; - } - - retval = wait_data_buf_ready(chip); - if (retval != STATUS_SUCCESS) { - chip->rw_need_retry = 1; - sd_set_err_code(chip, SD_TO_ERR); - goto RW_FAIL; - } - - retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK, - data_addr, SD_RSP_TYPE_R1, - NULL, 0); - if (retval != STATUS_SUCCESS) { - chip->rw_need_retry = 1; - goto RW_FAIL; - } - - rtsx_init_cmd(chip); - - cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | - SD_NO_WAIT_BUSY_END | - SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, - cfg2); - - trans_dma_enable(srb->sc_data_direction, chip, - sector_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - } - - sd_card->seq_mode = 1; - } - - retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), - scsi_bufflen(srb), scsi_sg_count(srb), - srb->sc_data_direction, chip->sd_timeout); - if (retval < 0) { - u8 stat = 0; - int err; - - sd_card->seq_mode = 0; - - if (retval == -ETIMEDOUT) - err = STATUS_TIMEDOUT; - else - err = STATUS_FAIL; - - rtsx_read_register(chip, REG_SD_STAT1, &stat); - rtsx_clear_sd_error(chip); - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - chip->rw_need_retry = 0; - dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n", - __func__); - return STATUS_FAIL; - } - - chip->rw_need_retry = 1; - - retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0); - if (retval != STATUS_SUCCESS) { - sd_set_err_code(chip, SD_STS_ERR); - goto RW_FAIL; - } - - if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) { - dev_dbg(rtsx_dev(chip), "SD CRC error, tune clock!\n"); - sd_set_err_code(chip, SD_CRC_ERR); - goto RW_FAIL; - } - - if (err == STATUS_TIMEDOUT) { - sd_set_err_code(chip, SD_TO_ERR); - goto RW_FAIL; - } - - return err; - } - - sd_card->pre_sec_addr = start_sector; - sd_card->pre_sec_cnt = sector_cnt; - sd_card->pre_dir = srb->sc_data_direction; - - return STATUS_SUCCESS; - -RW_FAIL: - sd_card->seq_mode = 0; - - if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) { - chip->rw_need_retry = 0; - dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n", __func__); - return STATUS_FAIL; - } - - if (sd_check_err_code(chip, SD_CRC_ERR)) { - if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) { - sd_card->mmc_dont_switch_bus = 1; - reset_mmc_only(chip); - sd_card->mmc_dont_switch_bus = 0; - } else { - sd_card->need_retune = 1; - sd_auto_tune_clock(chip); - } - } else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) { - retval = reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { - chip->card_ready &= ~SD_CARD; - chip->card_fail |= SD_CARD; - chip->capacity[chip->card2lun[SD_CARD]] = 0; - } - } - - return STATUS_FAIL; -} - -#ifdef SUPPORT_CPRM -int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, u32 arg, - u8 rsp_type, u8 *rsp, int rsp_len, - bool special_check) -{ - int retval; - int timeout = 100; - u16 reg_addr; - u8 *ptr; - int stat_idx = 0; - int rty_cnt = 0; - - dev_dbg(rtsx_dev(chip), "EXT SD/MMC CMD %d\n", cmd_idx); - - if (rsp_type == SD_RSP_TYPE_R1b) - timeout = 3000; - -RTY_SEND_CMD: - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, - SD_TRANSFER_END); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 17; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0); - - stat_idx = 6; - } - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0); - - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, timeout); - if (retval < 0) { - if (retval == -ETIMEDOUT) { - rtsx_clear_sd_error(chip); - - if (rsp_type & SD_WAIT_BUSY_END) { - retval = sd_check_data0_status(chip); - if (retval != STATUS_SUCCESS) - return retval; - } else { - sd_set_err_code(chip, SD_TO_ERR); - } - } - return STATUS_FAIL; - } - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - ptr = rtsx_get_cmd_data(chip) + 1; - - if ((ptr[0] & 0xC0) != 0) { - sd_set_err_code(chip, SD_STS_ERR); - return STATUS_FAIL; - } - - if (!(rsp_type & SD_NO_CHECK_CRC7)) { - if (ptr[stat_idx] & SD_CRC7_ERR) { - if (cmd_idx == WRITE_MULTIPLE_BLOCK) { - sd_set_err_code(chip, SD_CRC_ERR); - return STATUS_FAIL; - } - if (rty_cnt < SD_MAX_RETRY_COUNT) { - wait_timeout(20); - rty_cnt++; - goto RTY_SEND_CMD; - } else { - sd_set_err_code(chip, SD_CRC_ERR); - return STATUS_FAIL; - } - } - } - - if (cmd_idx == SELECT_CARD || cmd_idx == APP_CMD || - cmd_idx == SEND_STATUS || cmd_idx == STOP_TRANSMISSION) { - if (cmd_idx != STOP_TRANSMISSION && !special_check) { - if (ptr[1] & 0x80) - return STATUS_FAIL; - } -#ifdef SUPPORT_SD_LOCK - if (ptr[1] & 0x7D) { -#else - if (ptr[1] & 0x7F) { -#endif - return STATUS_FAIL; - } - if (ptr[2] & 0xF8) - return STATUS_FAIL; - - if (cmd_idx == SELECT_CARD) { - if (rsp_type == SD_RSP_TYPE_R2) { - if ((ptr[3] & 0x1E) != 0x04) - return STATUS_FAIL; - } - } - } - - if (rsp && rsp_len) - memcpy(rsp, ptr, rsp_len); - - return STATUS_SUCCESS; -} - -int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type) -{ - int retval, rsp_len; - u16 reg_addr; - - if (rsp_type == SD_RSP_TYPE_R0) - return STATUS_SUCCESS; - - rtsx_init_cmd(chip); - - if (rsp_type == SD_RSP_TYPE_R2) { - for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - - rsp_len = 17; - } else if (rsp_type != SD_RSP_TYPE_R0) { - for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; - reg_addr++) - rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0); - - rsp_len = 6; - } - rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0); - - retval = rtsx_send_cmd(chip, SD_CARD, 100); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (rsp) { - int min_len = (rsp_len < len) ? rsp_len : len; - - memcpy(rsp, rtsx_get_cmd_data(chip), min_len); - - dev_dbg(rtsx_dev(chip), "min_len = %d\n", min_len); - dev_dbg(rtsx_dev(chip), "Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n", - rsp[0], rsp[1], rsp[2], rsp[3]); - } - - return STATUS_SUCCESS; -} - -int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - int len; - u8 buf[18] = { - 0x00, - 0x00, - 0x00, - 0x0E, - 0x00, - 0x00, - 0x00, - 0x00, - 0x53, - 0x44, - 0x20, - 0x43, - 0x61, - 0x72, - 0x64, - 0x00, - 0x00, - 0x00, - }; - - sd_card->pre_cmd_err = 0; - - if (!(CHK_BIT(chip->lun_mc, lun))) { - SET_BIT(chip->lun_mc, lun); - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - if (srb->cmnd[2] != 0x53 || srb->cmnd[3] != 0x44 || - srb->cmnd[4] != 0x20 || srb->cmnd[5] != 0x43 || - srb->cmnd[6] != 0x61 || srb->cmnd[7] != 0x72 || - srb->cmnd[8] != 0x64) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - switch (srb->cmnd[1] & 0x0F) { - case 0: - sd_card->sd_pass_thru_en = 0; - break; - - case 1: - sd_card->sd_pass_thru_en = 1; - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - buf[5] = (CHK_SD(sd_card) == 1) ? 0x01 : 0x02; - if (chip->card_wp & SD_CARD) - buf[5] |= 0x80; - - buf[6] = (u8)(sd_card->sd_addr >> 16); - buf[7] = (u8)(sd_card->sd_addr >> 24); - - buf[15] = chip->max_lun; - - len = min_t(int, 18, scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf, len, srb); - - return TRANSPORT_GOOD; -} - -static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, - int *rsp_len) -{ - if (!rsp_type || !rsp_len) - return STATUS_FAIL; - - switch (srb->cmnd[10]) { - case 0x03: - *rsp_type = SD_RSP_TYPE_R0; - *rsp_len = 0; - break; - - case 0x04: - *rsp_type = SD_RSP_TYPE_R1; - *rsp_len = 6; - break; - - case 0x05: - *rsp_type = SD_RSP_TYPE_R1b; - *rsp_len = 6; - break; - - case 0x06: - *rsp_type = SD_RSP_TYPE_R2; - *rsp_len = 17; - break; - - case 0x07: - *rsp_type = SD_RSP_TYPE_R3; - *rsp_len = 6; - break; - - default: - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - int retval, rsp_len; - u8 cmd_idx, rsp_type; - bool standby = false, acmd = false; - u32 arg; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x02) - standby = true; - - if (srb->cmnd[1] & 0x01) - acmd = true; - - arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | - ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; - - retval = get_rsp_type(srb, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - } - } -#else - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; -#endif - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - goto sd_execute_cmd_failed; - } - - if (acmd) { - retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_cmd_failed; - } - - retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, false); - if (retval != STATUS_SUCCESS) - goto sd_execute_cmd_failed; - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - goto sd_execute_cmd_failed; - } - -#ifdef SUPPORT_SD_LOCK - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) - goto sd_execute_cmd_failed; -#endif - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - -sd_execute_cmd_failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - return TRANSPORT_FAILED; -} - -int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - int retval, rsp_len, i; - bool read_err = false, cmd13_checkbit = false; - u8 cmd_idx, rsp_type, bus_width; - bool standby = false, send_cmd12 = false, acmd = false; - u32 data_len; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) - send_cmd12 = true; - - if (srb->cmnd[1] & 0x02) - standby = true; - - if (srb->cmnd[1] & 0x01) - acmd = true; - - data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] - << 8) | srb->cmnd[9]; - - retval = get_rsp_type(srb, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) - bus_width = SD_BUS_WIDTH_8; - else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) - bus_width = SD_BUS_WIDTH_4; - else - bus_width = SD_BUS_WIDTH_1; - } else { - bus_width = SD_BUS_WIDTH_4; - } - dev_dbg(rtsx_dev(chip), "bus_width = %d\n", bus_width); -#else - bus_width = SD_BUS_WIDTH_4; -#endif - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - } - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - } - - if (acmd) { - retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - } - - if (data_len <= 512) { - int min_len; - u8 *buf; - u16 byte_cnt, blk_cnt; - u8 cmd[5]; - - byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9]; - blk_cnt = 1; - - cmd[0] = 0x40 | cmd_idx; - cmd[1] = srb->cmnd[3]; - cmd[2] = srb->cmnd[4]; - cmd[3] = srb->cmnd[5]; - cmd[4] = srb->cmnd[6]; - - buf = kmalloc(data_len, GFP_KERNEL); - if (!buf) - return TRANSPORT_ERROR; - - retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt, - blk_cnt, bus_width, buf, data_len, 2000); - if (retval != STATUS_SUCCESS) { - read_err = true; - kfree(buf); - rtsx_clear_sd_error(chip); - goto sd_execute_read_cmd_failed; - } - - min_len = min(data_len, scsi_bufflen(srb)); - rtsx_stor_set_xfer_buf(buf, min_len, srb); - - kfree(buf); - } else if (!(data_len & 0x1FF)) { - rtsx_init_cmd(chip); - - trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - 0x02); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, - 0xFF, (srb->cmnd[7] & 0xFE) >> 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, - 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, - 0x40 | cmd_idx); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, - srb->cmnd[3]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, - srb->cmnd[4]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, - srb->cmnd[5]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, - srb->cmnd[6]); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, - 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), - scsi_bufflen(srb), - scsi_sg_count(srb), - DMA_FROM_DEVICE, 10000); - if (retval < 0) { - read_err = true; - rtsx_clear_sd_error(chip); - goto sd_execute_read_cmd_failed; - } - - } else { - goto sd_execute_read_cmd_failed; - } - - retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - } - - if (send_cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - } - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - - retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - - retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - } - - if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) - cmd13_checkbit = true; - - for (i = 0; i < 3; i++) { - retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - cmd13_checkbit); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - goto sd_execute_read_cmd_failed; - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - -sd_execute_read_cmd_failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (read_err) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - return TRANSPORT_FAILED; -} - -int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - int retval, rsp_len, i; - bool write_err = false, cmd13_checkbit = false; - u8 cmd_idx, rsp_type; - bool standby = false, send_cmd12 = false, acmd = false; - u32 data_len, arg; -#ifdef SUPPORT_SD_LOCK - int lock_cmd_fail = 0; - u8 sd_lock_state = 0; - u8 lock_cmd_type = 0; -#endif - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - cmd_idx = srb->cmnd[2] & 0x3F; - if (srb->cmnd[1] & 0x04) - send_cmd12 = true; - - if (srb->cmnd[1] & 0x02) - standby = true; - - if (srb->cmnd[1] & 0x01) - acmd = true; - - data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] - << 8) | srb->cmnd[9]; - arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) | - ((u32)srb->cmnd[5] << 8) | srb->cmnd[6]; - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - sd_lock_state = sd_card->sd_lock_status; - sd_lock_state &= SD_LOCKED; - } -#endif - - retval = get_rsp_type(srb, &rsp_type, &rsp_len); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - sd_card->last_rsp_type = rsp_type; - - retval = sd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - -#ifdef SUPPORT_SD_LOCK - if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) { - if (CHK_MMC_8BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_8); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - - } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) { - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, - SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; - } - } -#else - retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4); - if (retval != STATUS_SUCCESS) - return TRANSPORT_FAILED; -#endif - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - } - - if (standby) { - retval = sd_select_card(chip, 0); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - } - - if (acmd) { - retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - } - - retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type, - sd_card->rsp, rsp_len, false); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - - if (data_len <= 512) { - u16 i; - u8 *buf; - - buf = kmalloc(data_len, GFP_KERNEL); - if (!buf) - return TRANSPORT_ERROR; - - rtsx_stor_get_xfer_buf(buf, data_len, srb); - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) - lock_cmd_type = buf[0] & 0x0F; -#endif - - if (data_len > 256) { - rtsx_init_cmd(chip); - for (i = 0; i < 256; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); - } - retval = rtsx_send_cmd(chip, 0, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - goto sd_execute_write_cmd_failed; - } - - rtsx_init_cmd(chip); - for (i = 256; i < data_len; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); - } - retval = rtsx_send_cmd(chip, 0, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - goto sd_execute_write_cmd_failed; - } - } else { - rtsx_init_cmd(chip); - for (i = 0; i < data_len; i++) { - rtsx_add_cmd(chip, WRITE_REG_CMD, - PPBUF_BASE2 + i, 0xFF, buf[i]); - } - retval = rtsx_send_cmd(chip, 0, 250); - if (retval != STATUS_SUCCESS) { - kfree(buf); - goto sd_execute_write_cmd_failed; - } - } - - kfree(buf); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - srb->cmnd[8] & 0x03); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - srb->cmnd[9]); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, - 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, - 0x01); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, SD_CARD, 250); - } else if (!(data_len & 0x1FF)) { - rtsx_init_cmd(chip); - - trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, - 0x02); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, - 0x00); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, - 0xFF, (srb->cmnd[7] & 0xFE) >> 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, - 0xFF, (u8)((data_len & 0x0001FE00) >> 9)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, - SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START); - rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, - SD_TRANSFER_END, SD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), - scsi_bufflen(srb), - scsi_sg_count(srb), - DMA_TO_DEVICE, 10000); - - } else { - goto sd_execute_write_cmd_failed; - } - - if (retval < 0) { - write_err = true; - rtsx_clear_sd_error(chip); - goto sd_execute_write_cmd_failed; - } - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - if (lock_cmd_type == SD_ERASE) { - sd_card->sd_erase_status = SD_UNDER_ERASING; - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - } - - rtsx_init_cmd(chip); - rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02); - - retval = rtsx_send_cmd(chip, SD_CARD, 250); - if (retval < 0) { - write_err = true; - rtsx_clear_sd_error(chip); - goto sd_execute_write_cmd_failed; - } - - retval = sd_update_lock_status(chip); - if (retval != STATUS_SUCCESS) { - dev_dbg(rtsx_dev(chip), "Lock command fail!\n"); - lock_cmd_fail = 1; - } - } -#endif /* SUPPORT_SD_LOCK */ - - if (standby) { - retval = sd_select_card(chip, 1); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - } - - if (send_cmd12) { - retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, - SD_RSP_TYPE_R1b, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - } - - if (data_len < 512) { - retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, - SD_RSP_TYPE_R1, NULL, 0, - false); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - - retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - - retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00); - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - } - - if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) - cmd13_checkbit = true; - - for (i = 0; i < 3; i++) { - retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, - sd_card->sd_addr, - SD_RSP_TYPE_R1, NULL, 0, - cmd13_checkbit); - if (retval == STATUS_SUCCESS) - break; - } - if (retval != STATUS_SUCCESS) - goto sd_execute_write_cmd_failed; - -#ifdef SUPPORT_SD_LOCK - if (cmd_idx == LOCK_UNLOCK) { - if (!lock_cmd_fail) { - dev_dbg(rtsx_dev(chip), "lock_cmd_type = 0x%x\n", - lock_cmd_type); - if (lock_cmd_type & SD_CLR_PWD) - sd_card->sd_lock_status &= ~SD_PWD_EXIST; - - if (lock_cmd_type & SD_SET_PWD) - sd_card->sd_lock_status |= SD_PWD_EXIST; - } - - dev_dbg(rtsx_dev(chip), "sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n", - sd_lock_state, sd_card->sd_lock_status); - if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) { - sd_card->sd_lock_notify = 1; - if (sd_lock_state && - (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE)) { - sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST); - if (CHK_SD(sd_card)) { - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - sd_card->sd_lock_status &= - ~(SD_UNLOCK_POW_ON | SD_SDR_RST); - goto sd_execute_write_cmd_failed; - } - } - - sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST); - } - } - } - - if (lock_cmd_fail) { - scsi_set_resid(srb, 0); - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - return TRANSPORT_FAILED; - } -#endif /* SUPPORT_SD_LOCK */ - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; - -sd_execute_write_cmd_failed: - sd_card->pre_cmd_err = 1; - set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE); - if (write_err) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - - release_sd_card(chip); - do_reset_sd_card(chip); - if (!(chip->card_ready & SD_CARD)) - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - - return TRANSPORT_FAILED; -} - -int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - int count; - u16 data_len; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8]; - - if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) { - count = (data_len < 17) ? data_len : 17; - } else { - count = (data_len < 6) ? data_len : 6; - } - rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb); - - dev_dbg(rtsx_dev(chip), "Response length: %d\n", data_len); - dev_dbg(rtsx_dev(chip), "Response: 0x%x 0x%x 0x%x 0x%x\n", - sd_card->rsp[0], sd_card->rsp[1], - sd_card->rsp[2], sd_card->rsp[3]); - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} - -int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - unsigned int lun = SCSI_LUN(srb); - int retval; - - if (!sd_card->sd_pass_thru_en) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - if (sd_card->pre_cmd_err) { - sd_card->pre_cmd_err = 0; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE); - return TRANSPORT_FAILED; - } - - if (srb->cmnd[2] != 0x53 || srb->cmnd[3] != 0x44 || - srb->cmnd[4] != 0x20 || srb->cmnd[5] != 0x43 || - srb->cmnd[6] != 0x61 || srb->cmnd[7] != 0x72 || - srb->cmnd[8] != 0x64) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - switch (srb->cmnd[1] & 0x0F) { - case 0: -#ifdef SUPPORT_SD_LOCK - if (srb->cmnd[9] == 0x64) - sd_card->sd_lock_status |= SD_SDR_RST; -#endif - retval = reset_sd_card(chip); - if (retval != STATUS_SUCCESS) { -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_SDR_RST; -#endif - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - sd_card->pre_cmd_err = 1; - return TRANSPORT_FAILED; - } -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status &= ~SD_SDR_RST; -#endif - break; - - case 1: - retval = reset_sd(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - sd_card->pre_cmd_err = 1; - return TRANSPORT_FAILED; - } - break; - - default: - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); - return TRANSPORT_FAILED; - } - - scsi_set_resid(srb, 0); - return TRANSPORT_GOOD; -} -#endif - -void sd_cleanup_work(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - - if (sd_card->seq_mode) { - dev_dbg(rtsx_dev(chip), "SD: stop transmission\n"); - sd_stop_seq_mode(chip); - sd_card->cleanup_counter = 0; - } -} - -int sd_power_off_card3v3(struct rtsx_chip *chip) -{ - int retval; - - retval = disable_card_clock(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0); - if (retval) - return retval; - - if (!chip->ft2_fast_mode) { - retval = card_power_off(chip, SD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - mdelay(50); - } - - if (chip->asic_code) { - retval = sd_pull_ctl_disable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, - FPGA_SD_PULL_CTL_BIT | 0x20, - FPGA_SD_PULL_CTL_BIT); - if (retval) - return retval; - } - - return STATUS_SUCCESS; -} - -int release_sd_card(struct rtsx_chip *chip) -{ - struct sd_info *sd_card = &chip->sd_card; - int retval; - - chip->card_ready &= ~SD_CARD; - chip->card_fail &= ~SD_CARD; - chip->card_wp &= ~SD_CARD; - - chip->sd_io = 0; - chip->sd_int = 0; - -#ifdef SUPPORT_SD_LOCK - sd_card->sd_lock_status = 0; - sd_card->sd_erase_status = 0; -#endif - - memset(sd_card->raw_csd, 0, 16); - memset(sd_card->raw_scr, 0, 8); - - retval = sd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} diff --git a/drivers/staging/rts5208/sd.h b/drivers/staging/rts5208/sd.h deleted file mode 100644 index f4ff62653b56c3b03e2d9fe2384bca3c4f6dbfc1..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/sd.h +++ /dev/null @@ -1,289 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_SD_H -#define __REALTEK_RTSX_SD_H - -#include "rtsx_chip.h" - -#define SUPPORT_VOLTAGE 0x003C0000 - -/* Error Code */ -#define SD_NO_ERROR 0x0 -#define SD_CRC_ERR 0x80 -#define SD_TO_ERR 0x40 -#define SD_NO_CARD 0x20 -#define SD_BUSY 0x10 -#define SD_STS_ERR 0x08 -#define SD_RSP_TIMEOUT 0x04 -#define SD_IO_ERR 0x02 - -/* Return code for MMC switch bus */ -#define SWITCH_SUCCESS 0 -#define SWITCH_ERR 1 -#define SWITCH_FAIL 2 - -/* MMC/SD Command Index */ -/* Basic command (class 0) */ -#define GO_IDLE_STATE 0 -#define SEND_OP_COND 1 -#define ALL_SEND_CID 2 -#define SET_RELATIVE_ADDR 3 -#define SEND_RELATIVE_ADDR 3 -#define SET_DSR 4 -#define IO_SEND_OP_COND 5 -#define SWITCH 6 -#define SELECT_CARD 7 -#define DESELECT_CARD 7 -/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec - * while is "SEND_IF_COND" for SD 2.0 - */ -#define SEND_EXT_CSD 8 -#define SEND_IF_COND 8 - -#define SEND_CSD 9 -#define SEND_CID 10 -#define VOLTAGE_SWITCH 11 -#define READ_DAT_UTIL_STOP 11 -#define STOP_TRANSMISSION 12 -#define SEND_STATUS 13 -#define GO_INACTIVE_STATE 15 - -#define SET_BLOCKLEN 16 -#define READ_SINGLE_BLOCK 17 -#define READ_MULTIPLE_BLOCK 18 -#define SEND_TUNING_PATTERN 19 - -#define BUSTEST_R 14 -#define BUSTEST_W 19 - -#define WRITE_BLOCK 24 -#define WRITE_MULTIPLE_BLOCK 25 -#define PROGRAM_CSD 27 - -#define ERASE_WR_BLK_START 32 -#define ERASE_WR_BLK_END 33 -#define ERASE_CMD 38 - -#define LOCK_UNLOCK 42 -#define IO_RW_DIRECT 52 - -#define APP_CMD 55 -#define GEN_CMD 56 - -#define SET_BUS_WIDTH 6 -#define SD_STATUS 13 -#define SEND_NUM_WR_BLOCKS 22 -#define SET_WR_BLK_ERASE_COUNT 23 -#define SD_APP_OP_COND 41 -#define SET_CLR_CARD_DETECT 42 -#define SEND_SCR 51 - -#define SD_READ_COMPLETE 0x00 -#define SD_READ_TO 0x01 -#define SD_READ_ADVENCE 0x02 - -#define SD_CHECK_MODE 0x00 -#define SD_SWITCH_MODE 0x80 -#define SD_FUNC_GROUP_1 0x01 -#define SD_FUNC_GROUP_2 0x02 -#define SD_FUNC_GROUP_3 0x03 -#define SD_FUNC_GROUP_4 0x04 -#define SD_CHECK_SPEC_V1_1 0xFF - -#define NO_ARGUMENT 0x00 -#define CHECK_PATTERN 0x000000AA -#define VOLTAGE_SUPPLY_RANGE 0x00000100 -#define SUPPORT_HIGH_AND_EXTENDED_CAPACITY 0x40000000 -#define SUPPORT_MAX_POWER_PERMANCE 0x10000000 -#define SUPPORT_1V8 0x01000000 - -#define SWITCH_NO_ERR 0x00 -#define CARD_NOT_EXIST 0x01 -#define SPEC_NOT_SUPPORT 0x02 -#define CHECK_MODE_ERR 0x03 -#define CHECK_NOT_READY 0x04 -#define SWITCH_CRC_ERR 0x05 -#define SWITCH_MODE_ERR 0x06 -#define SWITCH_PASS 0x07 - -#ifdef SUPPORT_SD_LOCK -#define SD_ERASE 0x08 -#define SD_LOCK 0x04 -#define SD_UNLOCK 0x00 -#define SD_CLR_PWD 0x02 -#define SD_SET_PWD 0x01 - -#define SD_PWD_LEN 0x10 - -#define SD_LOCKED 0x80 -#define SD_LOCK_1BIT_MODE 0x40 -#define SD_PWD_EXIST 0x20 -#define SD_UNLOCK_POW_ON 0x01 -#define SD_SDR_RST 0x02 - -#define SD_NOT_ERASE 0x00 -#define SD_UNDER_ERASING 0x01 -#define SD_COMPLETE_ERASE 0x02 - -#define SD_RW_FORBIDDEN 0x0F - -#endif - -#define HS_SUPPORT 0x01 -#define SDR50_SUPPORT 0x02 -#define SDR104_SUPPORT 0x03 -#define DDR50_SUPPORT 0x04 - -#define HS_SUPPORT_MASK 0x02 -#define SDR50_SUPPORT_MASK 0x04 -#define SDR104_SUPPORT_MASK 0x08 -#define DDR50_SUPPORT_MASK 0x10 - -#define HS_QUERY_SWITCH_OK 0x01 -#define SDR50_QUERY_SWITCH_OK 0x02 -#define SDR104_QUERY_SWITCH_OK 0x03 -#define DDR50_QUERY_SWITCH_OK 0x04 - -#define HS_SWITCH_BUSY 0x02 -#define SDR50_SWITCH_BUSY 0x04 -#define SDR104_SWITCH_BUSY 0x08 -#define DDR50_SWITCH_BUSY 0x10 - -#define FUNCTION_GROUP1_SUPPORT_OFFSET 0x0D -#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET 0x10 -#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET 0x1D - -#define DRIVING_TYPE_A 0x01 -#define DRIVING_TYPE_B 0x00 -#define DRIVING_TYPE_C 0x02 -#define DRIVING_TYPE_D 0x03 - -#define DRIVING_TYPE_A_MASK 0x02 -#define DRIVING_TYPE_B_MASK 0x01 -#define DRIVING_TYPE_C_MASK 0x04 -#define DRIVING_TYPE_D_MASK 0x08 - -#define TYPE_A_QUERY_SWITCH_OK 0x01 -#define TYPE_B_QUERY_SWITCH_OK 0x00 -#define TYPE_C_QUERY_SWITCH_OK 0x02 -#define TYPE_D_QUERY_SWITCH_OK 0x03 - -#define TYPE_A_SWITCH_BUSY 0x02 -#define TYPE_B_SWITCH_BUSY 0x01 -#define TYPE_C_SWITCH_BUSY 0x04 -#define TYPE_D_SWITCH_BUSY 0x08 - -#define FUNCTION_GROUP3_SUPPORT_OFFSET 0x09 -#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET 0x0F -#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET 0x19 - -#define CURRENT_LIMIT_200 0x00 -#define CURRENT_LIMIT_400 0x01 -#define CURRENT_LIMIT_600 0x02 -#define CURRENT_LIMIT_800 0x03 - -#define CURRENT_LIMIT_200_MASK 0x01 -#define CURRENT_LIMIT_400_MASK 0x02 -#define CURRENT_LIMIT_600_MASK 0x04 -#define CURRENT_LIMIT_800_MASK 0x08 - -#define CURRENT_LIMIT_200_QUERY_SWITCH_OK 0x00 -#define CURRENT_LIMIT_400_QUERY_SWITCH_OK 0x01 -#define CURRENT_LIMIT_600_QUERY_SWITCH_OK 0x02 -#define CURRENT_LIMIT_800_QUERY_SWITCH_OK 0x03 - -#define CURRENT_LIMIT_200_SWITCH_BUSY 0x01 -#define CURRENT_LIMIT_400_SWITCH_BUSY 0x02 -#define CURRENT_LIMIT_600_SWITCH_BUSY 0x04 -#define CURRENT_LIMIT_800_SWITCH_BUSY 0x08 - -#define FUNCTION_GROUP4_SUPPORT_OFFSET 0x07 -#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET 0x0F -#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET 0x17 - -#define DATA_STRUCTURE_VER_OFFSET 0x11 - -#define MAX_PHASE 31 - -#define MMC_8BIT_BUS 0x0010 -#define MMC_4BIT_BUS 0x0020 - -#define MMC_SWITCH_ERR 0x80 - -#define SD_IO_3V3 0 -#define SD_IO_1V8 1 - -#define TUNE_TX 0x00 -#define TUNE_RX 0x01 - -#define CHANGE_TX 0x00 -#define CHANGE_RX 0x01 - -#define DCM_HIGH_FREQUENCY_MODE 0x00 -#define DCM_LOW_FREQUENCY_MODE 0x01 - -#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C -#define DCM_LOW_FREQUENCY_MODE_SET 0x00 - -#define MULTIPLY_BY_1 0x00 -#define MULTIPLY_BY_2 0x01 -#define MULTIPLY_BY_3 0x02 -#define MULTIPLY_BY_4 0x03 -#define MULTIPLY_BY_5 0x04 -#define MULTIPLY_BY_6 0x05 -#define MULTIPLY_BY_7 0x06 -#define MULTIPLY_BY_8 0x07 -#define MULTIPLY_BY_9 0x08 -#define MULTIPLY_BY_10 0x09 - -#define DIVIDE_BY_2 0x01 -#define DIVIDE_BY_3 0x02 -#define DIVIDE_BY_4 0x03 -#define DIVIDE_BY_5 0x04 -#define DIVIDE_BY_6 0x05 -#define DIVIDE_BY_7 0x06 -#define DIVIDE_BY_8 0x07 -#define DIVIDE_BY_9 0x08 -#define DIVIDE_BY_10 0x09 - -struct timing_phase_path { - int start; - int end; - int mid; - int len; -}; - -int sd_select_card(struct rtsx_chip *chip, int select); -int sd_pull_ctl_enable(struct rtsx_chip *chip); -int reset_sd_card(struct rtsx_chip *chip); -int sd_switch_clock(struct rtsx_chip *chip); -void sd_stop_seq_mode(struct rtsx_chip *chip); -int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt); -void sd_cleanup_work(struct rtsx_chip *chip); -int sd_power_off_card3v3(struct rtsx_chip *chip); -int release_sd_card(struct rtsx_chip *chip); -#ifdef SUPPORT_CPRM -int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, - u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, - bool special_check); -int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type); - -int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip); -#endif - -#endif /* __REALTEK_RTSX_SD_H */ diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c deleted file mode 100644 index e88fe1a998f8126a3f5301155678875f282e8483..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/spi.c +++ /dev/null @@ -1,906 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> - -#include "rtsx.h" -#include "spi.h" - -static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct spi_info *spi = &chip->spi; - - spi->err_code = err_code; -} - -static int spi_init(struct rtsx_chip *chip) -{ - int retval; - - retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF, - CS_POLARITY_LOW | DTO_MSB_FIRST - | SPI_MASTER | SPI_MODE0 | SPI_AUTO); - if (retval) - return retval; - retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK, - SAMPLE_DELAY_HALF); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int spi_set_init_para(struct rtsx_chip *chip) -{ - struct spi_info *spi = &chip->spi; - int retval; - - retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, - (u8)(spi->clk_div >> 8)); - if (retval) - return retval; - retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, - (u8)(spi->clk_div)); - if (retval) - return retval; - - retval = switch_clock(chip, spi->spi_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = select_card(chip, SPI_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN, - SPI_CLK_EN); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN, - SPI_OUTPUT_EN); - if (retval) - return retval; - - wait_timeout(10); - - retval = spi_init(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int sf_polling_status(struct rtsx_chip *chip, int msec) -{ - int retval; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_POLLING_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, msec); - if (retval < 0) { - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_BUSY_ERR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sf_enable_write(struct rtsx_chip *chip, u8 ins) -{ - struct spi_info *spi = &chip->spi; - int retval; - - if (!spi->write_en) - return STATUS_SUCCESS; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_C_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) { - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int sf_disable_write(struct rtsx_chip *chip, u8 ins) -{ - struct spi_info *spi = &chip->spi; - int retval; - - if (!spi->write_en) - return STATUS_SUCCESS; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_C_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) { - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr, - u16 len) -{ - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8)); - if (addr_mode) { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADO_MODE0); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CDO_MODE0); - } - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); -} - -static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr) -{ - int retval; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - if (addr_mode) { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_C_MODE0); - } - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) { - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int spi_init_eeprom(struct rtsx_chip *chip) -{ - int retval; - int clk; - - if (chip->asic_code) - clk = 30; - else - clk = CLK_30; - - retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00); - if (retval) - return retval; - retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27); - if (retval) - return retval; - - retval = switch_clock(chip, clk); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = select_card(chip, SPI_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN, - SPI_CLK_EN); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN, - SPI_OUTPUT_EN); - if (retval) - return retval; - - wait_timeout(10); - - retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF, - CS_POLARITY_HIGH | SPI_EEPROM_AUTO); - if (retval) - return retval; - retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK, - SAMPLE_DELAY_HALF); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -static int spi_eeprom_program_enable(struct rtsx_chip *chip) -{ - int retval; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -int spi_erase_eeprom_chip(struct rtsx_chip *chip) -{ - int retval; - - retval = spi_init_eeprom(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = spi_eeprom_program_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr) -{ - int retval; - - retval = spi_init_eeprom(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = spi_eeprom_program_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val) -{ - int retval; - u8 data; - - retval = spi_init_eeprom(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADI_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) - return STATUS_FAIL; - - wait_timeout(5); - retval = rtsx_read_register(chip, SPI_DATA, &data); - if (retval) - return retval; - - if (val) - *val = data; - - retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val) -{ - int retval; - - retval = spi_init_eeprom(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = spi_eeprom_program_enable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CA_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01); - if (retval) - return retval; - - return STATUS_SUCCESS; -} - -int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct spi_info *spi = &chip->spi; - - dev_dbg(rtsx_dev(chip), "%s: err_code = 0x%x\n", __func__, - spi->err_code); - rtsx_stor_set_xfer_buf(&spi->err_code, - min_t(int, scsi_bufflen(srb), 1), srb); - scsi_set_resid(srb, scsi_bufflen(srb) - 1); - - return STATUS_SUCCESS; -} - -int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - struct spi_info *spi = &chip->spi; - - spi_set_err_code(chip, SPI_NO_ERR); - - if (chip->asic_code) - spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9]; - else - spi->spi_clock = srb->cmnd[3]; - - spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5]; - spi->write_en = srb->cmnd[6]; - - dev_dbg(rtsx_dev(chip), "spi_clock = %d, clk_div = %d, write_en = %d\n", - spi->spi_clock, spi->clk_div, spi->write_en); - - return STATUS_SUCCESS; -} - -int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - u16 len; - u8 *buf; - - spi_set_err_code(chip, SPI_NO_ERR); - - len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - if (len > 512) { - spi_set_err_code(chip, SPI_INVALID_COMMAND); - return STATUS_FAIL; - } - - retval = spi_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]); - - if (len == 0) { - if (srb->cmnd[9]) { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, - 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, - 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0); - } - } else { - if (srb->cmnd[9]) { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADI_MODE0); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CDI_MODE0); - } - } - - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) { - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - if (len) { - buf = kmalloc(len, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - retval = rtsx_read_ppbuf(chip, buf, len); - if (retval != STATUS_SUCCESS) { - spi_set_err_code(chip, SPI_READ_ERR); - kfree(buf); - return STATUS_FAIL; - } - - rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb); - scsi_set_resid(srb, 0); - - kfree(buf); - } - - return STATUS_SUCCESS; -} - -int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - unsigned int index = 0, offset = 0; - u8 ins, slow_read; - u32 addr; - u16 len; - u8 *buf; - - spi_set_err_code(chip, SPI_NO_ERR); - - ins = srb->cmnd[3]; - addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) - << 8) | srb->cmnd[6]; - len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - slow_read = srb->cmnd[9]; - - retval = spi_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - while (len) { - u16 pagelen = SF_PAGE_LEN - (u8)addr; - - if (pagelen > len) - pagelen = len; - - rtsx_init_cmd(chip); - - trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); - - if (slow_read) { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, - (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, - (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, - (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF, - (u8)(addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32); - } - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, - (u8)(pagelen >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, - (u8)pagelen); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CADI_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, - SPI_TRANSFER0_END, SPI_TRANSFER0_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, - DMA_FROM_DEVICE, 10000); - if (retval < 0) { - kfree(buf); - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, - TO_XFER_BUF); - - addr += pagelen; - len -= pagelen; - } - - scsi_set_resid(srb, 0); - kfree(buf); - - return STATUS_SUCCESS; -} - -int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - u8 ins, program_mode; - u32 addr; - u16 len; - u8 *buf; - unsigned int index = 0, offset = 0; - - spi_set_err_code(chip, SPI_NO_ERR); - - ins = srb->cmnd[3]; - addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) - << 8) | srb->cmnd[6]; - len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8]; - program_mode = srb->cmnd[9]; - - retval = spi_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - if (program_mode == BYTE_PROGRAM) { - buf = kmalloc(4, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - while (len) { - retval = sf_enable_write(chip, SPI_WREN); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, - FROM_XFER_BUF); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, - buf[0]); - sf_program(chip, ins, 1, addr, 1); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) { - kfree(buf); - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - retval = sf_polling_status(chip, 100); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - addr++; - len--; - } - - kfree(buf); - - } else if (program_mode == AAI_PROGRAM) { - int first_byte = 1; - - retval = sf_enable_write(chip, SPI_WREN); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - buf = kmalloc(4, GFP_KERNEL); - if (!buf) - return STATUS_ERROR; - - while (len) { - rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, - FROM_XFER_BUF); - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, - buf[0]); - if (first_byte) { - sf_program(chip, ins, 1, addr, 1); - first_byte = 0; - } else { - sf_program(chip, ins, 0, 0, 1); - } - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval < 0) { - kfree(buf); - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - retval = sf_polling_status(chip, 100); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - len--; - } - - kfree(buf); - - retval = sf_disable_write(chip, SPI_WRDI); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sf_polling_status(chip, 100); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else if (program_mode == PAGE_PROGRAM) { - buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL); - if (!buf) - return STATUS_NOMEM; - - while (len) { - u16 pagelen = SF_PAGE_LEN - (u8)addr; - - if (pagelen > len) - pagelen = len; - - retval = sf_enable_write(chip, SPI_WREN); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - rtsx_init_cmd(chip); - - trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256); - sf_program(chip, ins, 1, addr, pagelen); - - rtsx_send_cmd_no_wait(chip); - - rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, - &offset, FROM_XFER_BUF); - - retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, - DMA_TO_DEVICE, 100); - if (retval < 0) { - kfree(buf); - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - retval = sf_polling_status(chip, 100); - if (retval != STATUS_SUCCESS) { - kfree(buf); - return STATUS_FAIL; - } - - addr += pagelen; - len -= pagelen; - } - - kfree(buf); - } else { - spi_set_err_code(chip, SPI_INVALID_COMMAND); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - u8 ins, erase_mode; - u32 addr; - - spi_set_err_code(chip, SPI_NO_ERR); - - ins = srb->cmnd[3]; - addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) - << 8) | srb->cmnd[6]; - erase_mode = srb->cmnd[9]; - - retval = spi_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - if (erase_mode == PAGE_ERASE) { - retval = sf_enable_write(chip, SPI_WREN); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sf_erase(chip, ins, 1, addr); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else if (erase_mode == CHIP_ERASE) { - retval = sf_enable_write(chip, SPI_WREN); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = sf_erase(chip, ins, 0, 0); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - spi_set_err_code(chip, SPI_INVALID_COMMAND); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip) -{ - int retval; - u8 ins, status, ewsr; - - ins = srb->cmnd[3]; - status = srb->cmnd[4]; - ewsr = srb->cmnd[5]; - - retval = spi_set_init_para(chip); - if (retval != STATUS_SUCCESS) { - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - retval = sf_enable_write(chip, ewsr); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, - SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status); - rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, - SPI_TRANSFER0_START | SPI_CDO_MODE0); - rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, - SPI_TRANSFER0_END); - - retval = rtsx_send_cmd(chip, 0, 100); - if (retval != STATUS_SUCCESS) { - rtsx_clear_spi_error(chip); - spi_set_err_code(chip, SPI_HW_ERR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} diff --git a/drivers/staging/rts5208/spi.h b/drivers/staging/rts5208/spi.h deleted file mode 100644 index dcf93c80b2d50a95fa77b5151e9d8dc6bfc3f694..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/spi.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_SPI_H -#define __REALTEK_RTSX_SPI_H - -/* SPI operation error */ -#define SPI_NO_ERR 0x00 -#define SPI_HW_ERR 0x01 -#define SPI_INVALID_COMMAND 0x02 -#define SPI_READ_ERR 0x03 -#define SPI_WRITE_ERR 0x04 -#define SPI_ERASE_ERR 0x05 -#define SPI_BUSY_ERR 0x06 - -/* Serial flash instruction */ -#define SPI_READ 0x03 -#define SPI_FAST_READ 0x0B -#define SPI_WREN 0x06 -#define SPI_WRDI 0x04 -#define SPI_RDSR 0x05 - -#define SF_PAGE_LEN 256 - -#define BYTE_PROGRAM 0 -#define AAI_PROGRAM 1 -#define PAGE_PROGRAM 2 - -#define PAGE_ERASE 0 -#define CHIP_ERASE 1 - -int spi_erase_eeprom_chip(struct rtsx_chip *chip); -int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr); -int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val); -int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val); -int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip); -int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip); - -#endif /* __REALTEK_RTSX_SPI_H */ diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c deleted file mode 100644 index c0af378ada7162135956b3840f24393e52f5e424..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/xd.c +++ /dev/null @@ -1,2145 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#include <linux/blkdev.h> -#include <linux/kthread.h> -#include <linux/sched.h> -#include <linux/vmalloc.h> - -#include "rtsx.h" -#include "rtsx_transport.h" -#include "rtsx_scsi.h" -#include "rtsx_card.h" -#include "xd.h" - -static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no); -static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, - u8 start_page, u8 end_page); - -static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code) -{ - struct xd_info *xd_card = &chip->xd_card; - - xd_card->err_code = err_code; -} - -static int xd_set_init_para(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval; - - if (chip->asic_code) - xd_card->xd_clock = 47; - else - xd_card->xd_clock = CLK_50; - - retval = switch_clock(chip, xd_card->xd_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int xd_switch_clock(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval; - - retval = select_card(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = switch_clock(chip, xd_card->xd_clock); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len) -{ - int retval, i; - u8 *ptr; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_ID); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - for (i = 0; i < 4; i++) - rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0); - - retval = rtsx_send_cmd(chip, XD_CARD, 20); - if (retval < 0) - return STATUS_FAIL; - - ptr = rtsx_get_cmd_data(chip) + 1; - if (id_buf && buf_len) { - if (buf_len > 4) - buf_len = 4; - memcpy(id_buf, ptr, buf_len); - } - - return STATUS_SUCCESS; -} - -static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode) -{ - struct xd_info *xd_card = &chip->xd_card; - - switch (mode) { - case XD_RW_ADDR: - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, - 0xFF, (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, - 0xFF, (u8)(addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, - xd_card->addr_cycle | - XD_CALC_ECC | - XD_BA_NO_TRANSFORM); - break; - - case XD_ERASE_ADDR: - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, - 0xFF, (u8)(addr >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, - 0xFF, (u8)(addr >> 16)); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF, - (xd_card->addr_cycle - 1) | XD_CALC_ECC | - XD_BA_NO_TRANSFORM); - break; - - default: - break; - } -} - -static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, - u8 *buf, int buf_len) -{ - int retval, i; - - rtsx_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - for (i = 0; i < 6; i++) - rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i), - 0, 0); - for (i = 0; i < 4; i++) - rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i), - 0, 0); - rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0); - - retval = rtsx_send_cmd(chip, XD_CARD, 500); - if (retval < 0) - return STATUS_FAIL; - - if (buf && buf_len) { - u8 *ptr = rtsx_get_cmd_data(chip) + 1; - - if (buf_len > 11) - buf_len = 11; - memcpy(buf, ptr, buf_len); - } - - return STATUS_SUCCESS; -} - -static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, - u8 *buf, int buf_len) -{ - int retval, i; - - if (!buf || buf_len < 0) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - for (i = 0; i < buf_len; i++) - rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, - 0, 0); - - retval = rtsx_send_cmd(chip, 0, 250); - if (retval < 0) { - rtsx_clear_xd_error(chip); - return STATUS_FAIL; - } - - memcpy(buf, rtsx_get_cmd_data(chip), buf_len); - - return STATUS_SUCCESS; -} - -static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf, - int buf_len) -{ - int retval; - u8 reg; - - if (!buf || buf_len < 10) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, - 0x01, PINGPONG_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, - XD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, XD_CARD, 250); - if (retval == -ETIMEDOUT) { - rtsx_clear_xd_error(chip); - return STATUS_FAIL; - } - - retval = rtsx_read_register(chip, XD_PAGE_STATUS, ®); - if (retval) - return retval; - if (reg != XD_GPG) { - rtsx_clear_xd_error(chip); - return STATUS_FAIL; - } - - retval = rtsx_read_register(chip, XD_CTL, ®); - if (retval) - return retval; - if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) { - retval = xd_read_data_from_ppb(chip, 0, buf, buf_len); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - if (reg & XD_ECC1_ERROR) { - u8 ecc_bit, ecc_byte; - - retval = rtsx_read_register(chip, XD_ECC_BIT1, - &ecc_bit); - if (retval) - return retval; - retval = rtsx_read_register(chip, XD_ECC_BYTE1, - &ecc_byte); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n", - ecc_bit, ecc_byte); - if (ecc_byte < buf_len) { - dev_dbg(rtsx_dev(chip), "Before correct: 0x%x\n", - buf[ecc_byte]); - buf[ecc_byte] ^= (1 << ecc_bit); - dev_dbg(rtsx_dev(chip), "After correct: 0x%x\n", - buf[ecc_byte]); - } - } - } else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) { - rtsx_clear_xd_error(chip); - - retval = xd_read_data_from_ppb(chip, 256, buf, buf_len); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - if (reg & XD_ECC2_ERROR) { - u8 ecc_bit, ecc_byte; - - retval = rtsx_read_register(chip, XD_ECC_BIT2, - &ecc_bit); - if (retval) - return retval; - retval = rtsx_read_register(chip, XD_ECC_BYTE2, - &ecc_byte); - if (retval) - return retval; - - dev_dbg(rtsx_dev(chip), "ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n", - ecc_bit, ecc_byte); - if (ecc_byte < buf_len) { - dev_dbg(rtsx_dev(chip), "Before correct: 0x%x\n", - buf[ecc_byte]); - buf[ecc_byte] ^= (1 << ecc_bit); - dev_dbg(rtsx_dev(chip), "After correct: 0x%x\n", - buf[ecc_byte]); - } - } - } else { - rtsx_clear_xd_error(chip); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip) -{ - if (CHECK_PID(chip, 0x5208)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, - 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, - 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, - 0xFF, 0x4B); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, - 0xFF, 0x69); - } - } -} - -static void xd_fill_pull_ctl_stage1_barossa(struct rtsx_chip *chip) -{ - if (CHECK_BARO_PKG(chip, QFN)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55); - } -} - -static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip) -{ - if (CHECK_PID(chip, 0x5208)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, - XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, - XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, - XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, - 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, - 0xFF, 0x55); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, - 0xFF, 0x53); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, - 0xFF, 0xA9); - } - } -} - -static int xd_pull_ctl_disable(struct rtsx_chip *chip) -{ - int retval; - - if (CHECK_PID(chip, 0x5208)) { - retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF, - XD_D3_PD | - XD_D2_PD | - XD_D1_PD | - XD_D0_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, - XD_D7_PD | - XD_D6_PD | - XD_D5_PD | - XD_D4_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF, - XD_WP_PD | - XD_CE_PD | - XD_CLE_PD | - XD_CD_PU); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF, - XD_RDY_PD | - XD_WE_PD | - XD_RE_PD | - XD_ALE_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF, - MS_INS_PU | - SD_WP_PD | - SD_CD_PU | - SD_CMD_PD); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF, - MS_D5_PD | MS_D4_PD); - if (retval) - return retval; - } else if (CHECK_PID(chip, 0x5288)) { - if (CHECK_BARO_PKG(chip, QFN)) { - retval = rtsx_write_register(chip, CARD_PULL_CTL1, - 0xFF, 0x55); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL2, - 0xFF, 0x55); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL3, - 0xFF, 0x4B); - if (retval) - return retval; - retval = rtsx_write_register(chip, CARD_PULL_CTL4, - 0xFF, 0x69); - if (retval) - return retval; - } - } - - return STATUS_SUCCESS; -} - -static int reset_xd(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval, i, j; - u8 *ptr, id_buf[4], redunt[11]; - - retval = select_card(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, - XD_PGSTS_NOT_FF); - if (chip->asic_code) { - if (!CHECK_PID(chip, 0x5288)) - xd_fill_pull_ctl_disable(chip); - else - xd_fill_pull_ctl_stage1_barossa(chip); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) | - 0x20); - } - - if (!chip->ft2_fast_mode) - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT, - XD_NO_AUTO_PWR_OFF, 0); - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0); - - retval = rtsx_send_cmd(chip, XD_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - if (!chip->ft2_fast_mode) { - retval = card_power_off(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - wait_timeout(250); - - rtsx_init_cmd(chip); - - if (chip->asic_code) { - xd_fill_pull_ctl_enable(chip); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & - FPGA_XD_PULL_CTL_EN2) | - 0x20); - } - - retval = rtsx_send_cmd(chip, XD_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - retval = card_power_on(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - -#ifdef SUPPORT_OCP - wait_timeout(50); - if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { - dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n", - chip->ocp_stat); - return STATUS_FAIL; - } -#endif - } - - rtsx_init_cmd(chip); - - if (chip->ft2_fast_mode) { - if (chip->asic_code) { - xd_fill_pull_ctl_enable(chip); - } else { - rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF, - (FPGA_XD_PULL_CTL_EN1 & - FPGA_XD_PULL_CTL_EN2) | - 0x20); - } - } - - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, XD_OUTPUT_EN); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN); - - retval = rtsx_send_cmd(chip, XD_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - if (!chip->ft2_fast_mode) - wait_timeout(200); - - retval = xd_set_init_para(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - /* Read ID to check if the timing setting is right */ - for (i = 0; i < 4; i++) { - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF, - XD_TIME_SETUP_STEP * 3 + - XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF, - XD_TIME_SETUP_STEP * 3 + - XD_TIME_RW_STEP * (4 + i) + - XD_TIME_RWN_STEP * (3 + i)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_RESET); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); - rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); - - retval = rtsx_send_cmd(chip, XD_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - ptr = rtsx_get_cmd_data(chip) + 1; - - dev_dbg(rtsx_dev(chip), "XD_DAT: 0x%x, XD_CTL: 0x%x\n", - ptr[0], ptr[1]); - - if (((ptr[0] & READY_FLAG) != READY_STATE) || - !(ptr[1] & XD_RDY)) - continue; - - retval = xd_read_id(chip, READ_ID, id_buf, 4); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - dev_dbg(rtsx_dev(chip), "READ_ID: 0x%x 0x%x 0x%x 0x%x\n", - id_buf[0], id_buf[1], id_buf[2], id_buf[3]); - - xd_card->device_code = id_buf[1]; - - /* Check if the xD card is supported */ - switch (xd_card->device_code) { - case XD_4M_X8_512_1: - case XD_4M_X8_512_2: - xd_card->block_shift = 4; - xd_card->page_off = 0x0F; - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 1; - xd_card->capacity = 8000; - XD_SET_4MB(xd_card); - break; - case XD_8M_X8_512: - xd_card->block_shift = 4; - xd_card->page_off = 0x0F; - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 1; - xd_card->capacity = 16000; - break; - case XD_16M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 1; - xd_card->capacity = 32000; - break; - case XD_32M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 3; - xd_card->zone_cnt = 2; - xd_card->capacity = 64000; - break; - case XD_64M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 4; - xd_card->capacity = 128000; - break; - case XD_128M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 8; - xd_card->capacity = 256000; - break; - case XD_256M_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 16; - xd_card->capacity = 512000; - break; - case XD_512M_X8: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 32; - xd_card->capacity = 1024000; - break; - case XD_1G_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 64; - xd_card->capacity = 2048000; - break; - case XD_2G_X8_512: - XD_PAGE_512(xd_card); - xd_card->addr_cycle = 4; - xd_card->zone_cnt = 128; - xd_card->capacity = 4096000; - break; - default: - continue; - } - - /* Confirm timing setting */ - for (j = 0; j < 10; j++) { - retval = xd_read_id(chip, READ_ID, id_buf, 4); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (id_buf[1] != xd_card->device_code) - break; - } - - if (j == 10) - break; - } - - if (i == 4) { - xd_card->block_shift = 0; - xd_card->page_off = 0; - xd_card->addr_cycle = 0; - xd_card->capacity = 0; - - return STATUS_FAIL; - } - - retval = xd_read_id(chip, READ_XD_ID, id_buf, 4); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - dev_dbg(rtsx_dev(chip), "READ_XD_ID: 0x%x 0x%x 0x%x 0x%x\n", - id_buf[0], id_buf[1], id_buf[2], id_buf[3]); - if (id_buf[2] != XD_ID_CODE) - return STATUS_FAIL; - - /* Search CIS block */ - for (i = 0; i < 24; i++) { - u32 page_addr; - - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) - return STATUS_FAIL; - - page_addr = (u32)i << xd_card->block_shift; - - for (j = 0; j < 3; j++) { - retval = xd_read_redundant(chip, page_addr, redunt, 11); - if (retval == STATUS_SUCCESS) - break; - } - if (j == 3) - continue; - - if (redunt[BLOCK_STATUS] != XD_GBLK) - continue; - - j = 0; - if (redunt[PAGE_STATUS] != XD_GPG) { - for (j = 1; j <= 8; j++) { - retval = xd_read_redundant(chip, page_addr + j, - redunt, 11); - if (retval == STATUS_SUCCESS) { - if (redunt[PAGE_STATUS] == XD_GPG) - break; - } - } - - if (j == 9) - break; - } - - /* Check CIS data */ - if (redunt[BLOCK_STATUS] == XD_GBLK && - (redunt[PARITY] & XD_BA1_ALL0)) { - u8 buf[10]; - - page_addr += j; - - retval = xd_read_cis(chip, page_addr, buf, 10); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (buf[0] == 0x01 && buf[1] == 0x03 && - buf[2] == 0xD9 && - buf[3] == 0x01 && buf[4] == 0xFF && - buf[5] == 0x18 && buf[6] == 0x02 && - buf[7] == 0xDF && buf[8] == 0x01 && - buf[9] == 0x20) { - xd_card->cis_block = (u16)i; - } - } - - break; - } - - dev_dbg(rtsx_dev(chip), "CIS block: 0x%x\n", xd_card->cis_block); - if (xd_card->cis_block == 0xFFFF) - return STATUS_FAIL; - - chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity; - - return STATUS_SUCCESS; -} - -static int xd_check_data_blank(u8 *redunt) -{ - int i; - - for (i = 0; i < 6; i++) { - if (redunt[PAGE_STATUS + i] != 0xFF) - return 0; - } - - if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) - != (XD_ECC1_ALL1 | XD_ECC2_ALL1)) - return 0; - - for (i = 0; i < 4; i++) { - if (redunt[RESERVED0 + i] != 0xFF) - return 0; - } - - return 1; -} - -static u16 xd_load_log_block_addr(u8 *redunt) -{ - u16 addr = 0xFFFF; - - if (redunt[PARITY] & XD_BA1_BA2_EQL) - addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | - redunt[BLOCK_ADDR1_L]; - else if (redunt[PARITY] & XD_BA1_VALID) - addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | - redunt[BLOCK_ADDR1_L]; - else if (redunt[PARITY] & XD_BA2_VALID) - addr = ((u16)redunt[BLOCK_ADDR2_H] << 8) | - redunt[BLOCK_ADDR2_L]; - - return addr; -} - -static int xd_init_l2p_tbl(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int size, i; - - dev_dbg(rtsx_dev(chip), "%s: zone_cnt = %d\n", __func__, - xd_card->zone_cnt); - - if (xd_card->zone_cnt < 1) - return STATUS_FAIL; - - size = xd_card->zone_cnt * sizeof(struct zone_entry); - dev_dbg(rtsx_dev(chip), "Buffer size for l2p table is %d\n", size); - - xd_card->zone = vmalloc(size); - if (!xd_card->zone) - return STATUS_ERROR; - - for (i = 0; i < xd_card->zone_cnt; i++) { - xd_card->zone[i].build_flag = 0; - xd_card->zone[i].l2p_table = NULL; - xd_card->zone[i].free_table = NULL; - xd_card->zone[i].get_index = 0; - xd_card->zone[i].set_index = 0; - xd_card->zone[i].unused_blk_cnt = 0; - } - - return STATUS_SUCCESS; -} - -static inline void free_zone(struct zone_entry *zone) -{ - if (!zone) - return; - - zone->build_flag = 0; - zone->set_index = 0; - zone->get_index = 0; - zone->unused_blk_cnt = 0; - vfree(zone->l2p_table); - zone->l2p_table = NULL; - vfree(zone->free_table); - zone->free_table = NULL; -} - -static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk) -{ - struct xd_info *xd_card = &chip->xd_card; - struct zone_entry *zone; - int zone_no; - - zone_no = (int)phy_blk >> 10; - if (zone_no >= xd_card->zone_cnt) { - dev_dbg(rtsx_dev(chip), "Set unused block to invalid zone (zone_no = %d, zone_cnt = %d)\n", - zone_no, xd_card->zone_cnt); - return; - } - zone = &xd_card->zone[zone_no]; - - if (!zone->free_table) { - if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS) - return; - } - - if (zone->set_index >= XD_FREE_TABLE_CNT || - zone->set_index < 0) { - free_zone(zone); - dev_dbg(rtsx_dev(chip), "Set unused block fail, invalid set_index\n"); - return; - } - - dev_dbg(rtsx_dev(chip), "Set unused block to index %d\n", - zone->set_index); - - zone->free_table[zone->set_index++] = (u16)(phy_blk & 0x3ff); - if (zone->set_index >= XD_FREE_TABLE_CNT) - zone->set_index = 0; - zone->unused_blk_cnt++; -} - -static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no) -{ - struct xd_info *xd_card = &chip->xd_card; - struct zone_entry *zone; - u32 phy_blk; - - if (zone_no >= xd_card->zone_cnt) { - dev_dbg(rtsx_dev(chip), "Get unused block from invalid zone (zone_no = %d, zone_cnt = %d)\n", - zone_no, xd_card->zone_cnt); - return BLK_NOT_FOUND; - } - zone = &xd_card->zone[zone_no]; - - if (zone->unused_blk_cnt == 0 || - zone->set_index == zone->get_index) { - free_zone(zone); - dev_dbg(rtsx_dev(chip), "Get unused block fail, no unused block available\n"); - return BLK_NOT_FOUND; - } - if (zone->get_index >= XD_FREE_TABLE_CNT || zone->get_index < 0) { - free_zone(zone); - dev_dbg(rtsx_dev(chip), "Get unused block fail, invalid get_index\n"); - return BLK_NOT_FOUND; - } - - dev_dbg(rtsx_dev(chip), "Get unused block from index %d\n", - zone->get_index); - - phy_blk = zone->free_table[zone->get_index]; - zone->free_table[zone->get_index++] = 0xFFFF; - if (zone->get_index >= XD_FREE_TABLE_CNT) - zone->get_index = 0; - zone->unused_blk_cnt--; - - phy_blk += ((u32)(zone_no) << 10); - return phy_blk; -} - -static void xd_set_l2p_tbl(struct rtsx_chip *chip, - int zone_no, u16 log_off, u16 phy_off) -{ - struct xd_info *xd_card = &chip->xd_card; - struct zone_entry *zone; - - zone = &xd_card->zone[zone_no]; - zone->l2p_table[log_off] = phy_off; -} - -static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off) -{ - struct xd_info *xd_card = &chip->xd_card; - struct zone_entry *zone; - int retval; - - zone = &xd_card->zone[zone_no]; - if (zone->l2p_table[log_off] == 0xFFFF) { - u32 phy_blk = 0; - int i; - -#ifdef XD_DELAY_WRITE - retval = xd_delay_write(chip); - if (retval != STATUS_SUCCESS) { - dev_dbg(rtsx_dev(chip), "In %s, delay write fail!\n", - __func__); - return BLK_NOT_FOUND; - } -#endif - - if (zone->unused_blk_cnt <= 0) { - dev_dbg(rtsx_dev(chip), "No unused block!\n"); - return BLK_NOT_FOUND; - } - - for (i = 0; i < zone->unused_blk_cnt; i++) { - phy_blk = xd_get_unused_block(chip, zone_no); - if (phy_blk == BLK_NOT_FOUND) { - dev_dbg(rtsx_dev(chip), "No unused block available!\n"); - return BLK_NOT_FOUND; - } - - retval = xd_init_page(chip, phy_blk, log_off, - 0, xd_card->page_off + 1); - if (retval == STATUS_SUCCESS) - break; - } - if (i >= zone->unused_blk_cnt) { - dev_dbg(rtsx_dev(chip), "No good unused block available!\n"); - return BLK_NOT_FOUND; - } - - xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(phy_blk & 0x3FF)); - return phy_blk; - } - - return (u32)zone->l2p_table[log_off] + ((u32)(zone_no) << 10); -} - -int reset_xd_card(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval; - - memset(xd_card, 0, sizeof(struct xd_info)); - - xd_card->block_shift = 0; - xd_card->page_off = 0; - xd_card->addr_cycle = 0; - xd_card->capacity = 0; - xd_card->zone_cnt = 0; - xd_card->cis_block = 0xFFFF; - xd_card->delay_write.delay_write_flag = 0; - - retval = enable_card_clock(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = reset_xd(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = xd_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval; - u32 page_addr; - u8 reg = 0; - - dev_dbg(rtsx_dev(chip), "mark block 0x%x as bad block\n", phy_blk); - - if (phy_blk == BLK_NOT_FOUND) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_LATER_BBLK); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF); - - page_addr = phy_blk << xd_card->block_shift; - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, - xd_card->page_off + 1); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_REDUNDANT); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, XD_CARD, 500); - if (retval < 0) { - rtsx_clear_xd_error(chip); - rtsx_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) - xd_set_err_code(chip, XD_PRG_ERROR); - else - xd_set_err_code(chip, XD_TO_ERROR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, - u16 logoff, u8 start_page, u8 end_page) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval; - u32 page_addr; - u8 reg = 0; - - dev_dbg(rtsx_dev(chip), "Init block 0x%x\n", phy_blk); - - if (start_page > end_page) - return STATUS_FAIL; - if (phy_blk == BLK_NOT_FOUND) - return STATUS_FAIL; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, - 0xFF, (u8)(logoff >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff); - - page_addr = (phy_blk << xd_card->block_shift) + start_page; - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, - XD_BA_TRANSFORM, XD_BA_TRANSFORM); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, - 0xFF, (end_page - start_page)); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, XD_CARD, 500); - if (retval < 0) { - rtsx_clear_xd_error(chip); - rtsx_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) { - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - } else { - xd_set_err_code(chip, XD_TO_ERROR); - } - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, - u8 start_page, u8 end_page) -{ - struct xd_info *xd_card = &chip->xd_card; - u32 old_page, new_page; - u8 i, reg = 0; - int retval; - - dev_dbg(rtsx_dev(chip), "Copy page from block 0x%x to block 0x%x\n", - old_blk, new_blk); - - if (start_page > end_page) - return STATUS_FAIL; - - if (old_blk == BLK_NOT_FOUND || new_blk == BLK_NOT_FOUND) - return STATUS_FAIL; - - old_page = (old_blk << xd_card->block_shift) + start_page; - new_page = (new_blk << xd_card->block_shift) + start_page; - - XD_CLR_BAD_NEWBLK(xd_card); - - retval = rtsx_write_register(chip, CARD_DATA_SOURCE, 0x01, - PINGPONG_BUFFER); - if (retval) - return retval; - - for (i = start_page; i < end_page; i++) { - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - rtsx_clear_xd_error(chip); - xd_set_err_code(chip, XD_NO_CARD); - return STATUS_FAIL; - } - - rtsx_init_cmd(chip); - - xd_assign_phy_addr(chip, old_page, XD_RW_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, 0); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, XD_CARD, 500); - if (retval < 0) { - rtsx_clear_xd_error(chip); - reg = 0; - rtsx_read_register(chip, XD_CTL, ®); - if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) { - mdelay(100); - - if (detect_card_cd(chip, - XD_CARD) != STATUS_SUCCESS) { - xd_set_err_code(chip, XD_NO_CARD); - return STATUS_FAIL; - } - - if (((reg & XD_ECC1_ERROR) && - (reg & XD_ECC1_UNCORRECTABLE)) || - ((reg & XD_ECC2_ERROR) && - (reg & XD_ECC2_UNCORRECTABLE))) { - rtsx_write_register(chip, - XD_PAGE_STATUS, - 0xFF, - XD_BPG); - rtsx_write_register(chip, - XD_BLOCK_STATUS, - 0xFF, - XD_GBLK); - XD_SET_BAD_OLDBLK(xd_card); - dev_dbg(rtsx_dev(chip), "old block 0x%x ecc error\n", - old_blk); - } - } else { - xd_set_err_code(chip, XD_TO_ERROR); - return STATUS_FAIL; - } - } - - if (XD_CHK_BAD_OLDBLK(xd_card)) - rtsx_clear_xd_error(chip); - - rtsx_init_cmd(chip); - - xd_assign_phy_addr(chip, new_page, XD_RW_ADDR); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_WRITE_PAGES); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, XD_CARD, 300); - if (retval < 0) { - rtsx_clear_xd_error(chip); - reg = 0; - rtsx_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) { - xd_mark_bad_block(chip, new_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - XD_SET_BAD_NEWBLK(xd_card); - } else { - xd_set_err_code(chip, XD_TO_ERROR); - } - return STATUS_FAIL; - } - - old_page++; - new_page++; - } - - return STATUS_SUCCESS; -} - -static int xd_reset_cmd(struct rtsx_chip *chip) -{ - int retval; - u8 *ptr; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_RESET); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); - rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0); - - retval = rtsx_send_cmd(chip, XD_CARD, 100); - if (retval < 0) - return STATUS_FAIL; - - ptr = rtsx_get_cmd_data(chip) + 1; - if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY)) - return STATUS_SUCCESS; - - return STATUS_FAIL; -} - -static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk) -{ - struct xd_info *xd_card = &chip->xd_card; - u32 page_addr; - u8 reg = 0, *ptr; - int i, retval; - - if (phy_blk == BLK_NOT_FOUND) - return STATUS_FAIL; - - page_addr = phy_blk << xd_card->block_shift; - - for (i = 0; i < 3; i++) { - rtsx_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_ERASE); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0); - - retval = rtsx_send_cmd(chip, XD_CARD, 250); - if (retval < 0) { - rtsx_clear_xd_error(chip); - rtsx_read_register(chip, XD_DAT, ®); - if (reg & PROGRAM_ERROR) { - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - return STATUS_FAIL; - } - xd_set_err_code(chip, XD_ERASE_FAIL); - retval = xd_reset_cmd(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - continue; - } - - ptr = rtsx_get_cmd_data(chip) + 1; - if (*ptr & PROGRAM_ERROR) { - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_PRG_ERROR); - return STATUS_FAIL; - } - - return STATUS_SUCCESS; - } - - xd_mark_bad_block(chip, phy_blk); - xd_set_err_code(chip, XD_ERASE_FAIL); - return STATUS_FAIL; -} - -static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no) -{ - struct xd_info *xd_card = &chip->xd_card; - struct zone_entry *zone; - int retval; - u32 start, end, i; - u16 max_logoff, cur_fst_page_logoff; - u16 cur_lst_page_logoff, ent_lst_page_logoff; - u8 redunt[11]; - - dev_dbg(rtsx_dev(chip), "%s: %d\n", __func__, zone_no); - - if (!xd_card->zone) { - retval = xd_init_l2p_tbl(chip); - if (retval != STATUS_SUCCESS) - return retval; - } - - if (xd_card->zone[zone_no].build_flag) { - dev_dbg(rtsx_dev(chip), "l2p table of zone %d has been built\n", - zone_no); - return STATUS_SUCCESS; - } - - zone = &xd_card->zone[zone_no]; - - if (!zone->l2p_table) { - zone->l2p_table = vmalloc(2000); - if (!zone->l2p_table) - goto build_fail; - } - memset((u8 *)(zone->l2p_table), 0xff, 2000); - - if (!zone->free_table) { - zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2); - if (!zone->free_table) - goto build_fail; - } - memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2); - - if (zone_no == 0) { - if (xd_card->cis_block == 0xFFFF) - start = 0; - else - start = xd_card->cis_block + 1; - if (XD_CHK_4MB(xd_card)) { - end = 0x200; - max_logoff = 499; - } else { - end = 0x400; - max_logoff = 999; - } - } else { - start = (u32)(zone_no) << 10; - end = (u32)(zone_no + 1) << 10; - max_logoff = 999; - } - - dev_dbg(rtsx_dev(chip), "start block 0x%x, end block 0x%x\n", - start, end); - - zone->set_index = 0; - zone->get_index = 0; - zone->unused_blk_cnt = 0; - - for (i = start; i < end; i++) { - u32 page_addr = i << xd_card->block_shift; - u32 phy_block; - - retval = xd_read_redundant(chip, page_addr, redunt, 11); - if (retval != STATUS_SUCCESS) - continue; - - if (redunt[BLOCK_STATUS] != 0xFF) { - dev_dbg(rtsx_dev(chip), "bad block\n"); - continue; - } - - if (xd_check_data_blank(redunt)) { - dev_dbg(rtsx_dev(chip), "blank block\n"); - xd_set_unused_block(chip, i); - continue; - } - - cur_fst_page_logoff = xd_load_log_block_addr(redunt); - if (cur_fst_page_logoff == 0xFFFF || - cur_fst_page_logoff > max_logoff) { - retval = xd_erase_block(chip, i); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, i); - continue; - } - - if (zone_no == 0 && cur_fst_page_logoff == 0 && - redunt[PAGE_STATUS] != XD_GPG) - XD_SET_MBR_FAIL(xd_card); - - if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) { - zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF); - continue; - } - - phy_block = zone->l2p_table[cur_fst_page_logoff] + - ((u32)((zone_no) << 10)); - - page_addr = ((i + 1) << xd_card->block_shift) - 1; - - retval = xd_read_redundant(chip, page_addr, redunt, 11); - if (retval != STATUS_SUCCESS) - continue; - - cur_lst_page_logoff = xd_load_log_block_addr(redunt); - if (cur_lst_page_logoff == cur_fst_page_logoff) { - int m; - - page_addr = ((phy_block + 1) << - xd_card->block_shift) - 1; - - for (m = 0; m < 3; m++) { - retval = xd_read_redundant(chip, page_addr, - redunt, 11); - if (retval == STATUS_SUCCESS) - break; - } - - if (m == 3) { - zone->l2p_table[cur_fst_page_logoff] = - (u16)(i & 0x3FF); - retval = xd_erase_block(chip, phy_block); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, phy_block); - continue; - } - - ent_lst_page_logoff = xd_load_log_block_addr(redunt); - if (ent_lst_page_logoff != cur_fst_page_logoff) { - zone->l2p_table[cur_fst_page_logoff] = - (u16)(i & 0x3FF); - retval = xd_erase_block(chip, phy_block); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, phy_block); - continue; - } else { - retval = xd_erase_block(chip, i); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, i); - } - } else { - retval = xd_erase_block(chip, i); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, i); - } - } - - if (XD_CHK_4MB(xd_card)) - end = 500; - else - end = 1000; - - i = 0; - for (start = 0; start < end; start++) { - if (zone->l2p_table[start] == 0xFFFF) - i++; - } - - dev_dbg(rtsx_dev(chip), "Block count %d, invalid L2P entry %d\n", - end, i); - dev_dbg(rtsx_dev(chip), "Total unused block: %d\n", - zone->unused_blk_cnt); - - if ((zone->unused_blk_cnt - i) < 1) - chip->card_wp |= XD_CARD; - - zone->build_flag = 1; - - return STATUS_SUCCESS; - -build_fail: - vfree(zone->l2p_table); - zone->l2p_table = NULL; - vfree(zone->free_table); - zone->free_table = NULL; - - return STATUS_FAIL; -} - -static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd) -{ - int retval; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_SET_CMD); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - retval = rtsx_send_cmd(chip, XD_CARD, 200); - if (retval < 0) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} - -static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, - u32 log_blk, u8 start_page, u8 end_page, - u8 *buf, unsigned int *index, - unsigned int *offset) -{ - struct xd_info *xd_card = &chip->xd_card; - u32 page_addr, new_blk; - u16 log_off; - u8 reg_val, page_cnt; - int zone_no, retval, i; - - if (start_page > end_page) - goto status_fail; - - page_cnt = end_page - start_page; - zone_no = (int)(log_blk / 1000); - log_off = (u16)(log_blk % 1000); - - if ((phy_blk & 0x3FF) == 0x3FF) { - for (i = 0; i < 256; i++) { - page_addr = ((u32)i) << xd_card->block_shift; - - retval = xd_read_redundant(chip, page_addr, NULL, 0); - if (retval == STATUS_SUCCESS) - break; - - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - xd_set_err_code(chip, XD_NO_CARD); - goto status_fail; - } - } - } - - page_addr = (phy_blk << xd_card->block_shift) + start_page; - - rtsx_init_cmd(chip); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, XD_PPB_TO_SIE); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, - XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS); - - trans_dma_enable(chip->srb->sc_data_direction, chip, - page_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, - XD_TRANSFER_START | XD_READ_PAGES); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END | XD_PPB_EMPTY, - XD_TRANSFER_END | XD_PPB_EMPTY); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, - scsi_sg_count(chip->srb), - index, offset, DMA_FROM_DEVICE, - chip->xd_timeout); - if (retval < 0) { - rtsx_clear_xd_error(chip); - - if (retval == -ETIMEDOUT) { - xd_set_err_code(chip, XD_TO_ERROR); - goto status_fail; - } else { - goto fail; - } - } - - return STATUS_SUCCESS; - -fail: - retval = rtsx_read_register(chip, XD_PAGE_STATUS, ®_val); - if (retval) - return retval; - - if (reg_val != XD_GPG) - xd_set_err_code(chip, XD_PRG_ERROR); - - retval = rtsx_read_register(chip, XD_CTL, ®_val); - if (retval) - return retval; - - if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) == - (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) || - ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) == - (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) { - wait_timeout(100); - - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - xd_set_err_code(chip, XD_NO_CARD); - goto status_fail; - } - - xd_set_err_code(chip, XD_ECC_ERROR); - - new_blk = xd_get_unused_block(chip, zone_no); - if (new_blk == NO_NEW_BLK) { - XD_CLR_BAD_OLDBLK(xd_card); - goto status_fail; - } - - retval = xd_copy_page(chip, phy_blk, new_blk, 0, - xd_card->page_off + 1); - if (retval != STATUS_SUCCESS) { - if (!XD_CHK_BAD_NEWBLK(xd_card)) { - retval = xd_erase_block(chip, new_blk); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, new_blk); - } else { - XD_CLR_BAD_NEWBLK(xd_card); - } - XD_CLR_BAD_OLDBLK(xd_card); - goto status_fail; - } - xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); - xd_erase_block(chip, phy_blk); - xd_mark_bad_block(chip, phy_blk); - XD_CLR_BAD_OLDBLK(xd_card); - } - -status_fail: - return STATUS_FAIL; -} - -static int xd_finish_write(struct rtsx_chip *chip, - u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval, zone_no; - u16 log_off; - - dev_dbg(rtsx_dev(chip), "old_blk = 0x%x, ", old_blk); - dev_dbg(rtsx_dev(chip), "new_blk = 0x%x, ", new_blk); - dev_dbg(rtsx_dev(chip), "log_blk = 0x%x\n", log_blk); - - if (page_off > xd_card->page_off) - return STATUS_FAIL; - - zone_no = (int)(log_blk / 1000); - log_off = (u16)(log_blk % 1000); - - if (old_blk == BLK_NOT_FOUND) { - retval = xd_init_page(chip, new_blk, log_off, - page_off, xd_card->page_off + 1); - if (retval != STATUS_SUCCESS) { - retval = xd_erase_block(chip, new_blk); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, new_blk); - return STATUS_FAIL; - } - } else { - retval = xd_copy_page(chip, old_blk, new_blk, - page_off, xd_card->page_off + 1); - if (retval != STATUS_SUCCESS) { - if (!XD_CHK_BAD_NEWBLK(xd_card)) { - retval = xd_erase_block(chip, new_blk); - if (retval == STATUS_SUCCESS) - xd_set_unused_block(chip, new_blk); - } - XD_CLR_BAD_NEWBLK(xd_card); - return STATUS_FAIL; - } - - retval = xd_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) { - if (XD_CHK_BAD_OLDBLK(xd_card)) { - xd_mark_bad_block(chip, old_blk); - XD_CLR_BAD_OLDBLK(xd_card); - } else { - xd_set_unused_block(chip, old_blk); - } - } else { - xd_set_err_code(chip, XD_NO_ERROR); - XD_CLR_BAD_OLDBLK(xd_card); - } - } - - xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); - - return STATUS_SUCCESS; -} - -static int xd_prepare_write(struct rtsx_chip *chip, - u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off) -{ - int retval; - - dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x, page_off = %d\n", - __func__, old_blk, new_blk, log_blk, (int)page_off); - - if (page_off) { - retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} - -static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, - u32 new_blk, u32 log_blk, u8 start_page, - u8 end_page, u8 *buf, unsigned int *index, - unsigned int *offset) -{ - struct xd_info *xd_card = &chip->xd_card; - u32 page_addr; - int zone_no, retval; - u16 log_off; - u8 page_cnt, reg_val; - - dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n", - __func__, old_blk, new_blk, log_blk); - - if (start_page > end_page) - goto status_fail; - - page_cnt = end_page - start_page; - zone_no = (int)(log_blk / 1000); - log_off = (u16)(log_blk % 1000); - - page_addr = (new_blk << xd_card->block_shift) + start_page; - - retval = xd_send_cmd(chip, READ1_1); - if (retval != STATUS_SUCCESS) - goto status_fail; - - rtsx_init_cmd(chip); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, - 0xFF, (u8)(log_off >> 8)); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG); - - xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, - XD_BA_TRANSFORM); - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt); - rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); - - trans_dma_enable(chip->srb->sc_data_direction, chip, - page_cnt * 512, DMA_512); - - rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, - 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES); - rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, - XD_TRANSFER_END, XD_TRANSFER_END); - - rtsx_send_cmd_no_wait(chip); - - retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, - scsi_sg_count(chip->srb), - index, offset, DMA_TO_DEVICE, chip->xd_timeout); - if (retval < 0) { - rtsx_clear_xd_error(chip); - - if (retval == -ETIMEDOUT) { - xd_set_err_code(chip, XD_TO_ERROR); - goto status_fail; - } else { - goto fail; - } - } - - if (end_page == (xd_card->page_off + 1)) { - xd_card->delay_write.delay_write_flag = 0; - - if (old_blk != BLK_NOT_FOUND) { - retval = xd_erase_block(chip, old_blk); - if (retval == STATUS_SUCCESS) { - if (XD_CHK_BAD_OLDBLK(xd_card)) { - xd_mark_bad_block(chip, old_blk); - XD_CLR_BAD_OLDBLK(xd_card); - } else { - xd_set_unused_block(chip, old_blk); - } - } else { - xd_set_err_code(chip, XD_NO_ERROR); - XD_CLR_BAD_OLDBLK(xd_card); - } - } - xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF)); - } - - return STATUS_SUCCESS; - -fail: - retval = rtsx_read_register(chip, XD_DAT, ®_val); - if (retval) - return retval; - if (reg_val & PROGRAM_ERROR) { - xd_set_err_code(chip, XD_PRG_ERROR); - xd_mark_bad_block(chip, new_blk); - } - -status_fail: - return STATUS_FAIL; -} - -#ifdef XD_DELAY_WRITE -int xd_delay_write(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - struct xd_delay_write_tag *delay_write = &xd_card->delay_write; - int retval; - - if (delay_write->delay_write_flag) { - retval = xd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - delay_write->delay_write_flag = 0; - retval = xd_finish_write(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->logblock, - delay_write->pageoff); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } - - return STATUS_SUCCESS; -} -#endif - -int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt) -{ - struct xd_info *xd_card = &chip->xd_card; - unsigned int lun = SCSI_LUN(srb); -#ifdef XD_DELAY_WRITE - struct xd_delay_write_tag *delay_write = &xd_card->delay_write; -#endif - int retval, zone_no; - unsigned int index = 0, offset = 0; - u32 log_blk, old_blk = 0, new_blk = 0; - u16 log_off, total_sec_cnt = sector_cnt; - u8 start_page, end_page = 0, page_cnt; - u8 *ptr; - - xd_set_err_code(chip, XD_NO_ERROR); - - xd_card->cleanup_counter = 0; - - dev_dbg(rtsx_dev(chip), "%s: scsi_sg_count = %d\n", __func__, - scsi_sg_count(srb)); - - ptr = (u8 *)scsi_sglist(srb); - - retval = xd_switch_clock(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - - log_blk = start_sector >> xd_card->block_shift; - start_page = (u8)start_sector & xd_card->page_off; - zone_no = (int)(log_blk / 1000); - log_off = (u16)(log_blk % 1000); - - if (xd_card->zone[zone_no].build_flag == 0) { - retval = xd_build_l2p_tbl(chip, zone_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { -#ifdef XD_DELAY_WRITE - if (delay_write->delay_write_flag && - delay_write->logblock == log_blk && - start_page > delay_write->pageoff) { - delay_write->delay_write_flag = 0; - if (delay_write->old_phyblock != BLK_NOT_FOUND) { - retval = xd_copy_page(chip, - delay_write->old_phyblock, - delay_write->new_phyblock, - delay_write->pageoff, - start_page); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } - } - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else if (delay_write->delay_write_flag && - (delay_write->logblock == log_blk) && - (start_page == delay_write->pageoff)) { - delay_write->delay_write_flag = 0; - old_blk = delay_write->old_phyblock; - new_blk = delay_write->new_phyblock; - } else { - retval = xd_delay_write(chip); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } -#endif - old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); - new_blk = xd_get_unused_block(chip, zone_no); - if (old_blk == BLK_NOT_FOUND || - new_blk == BLK_NOT_FOUND) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } - - retval = xd_prepare_write(chip, old_blk, new_blk, - log_blk, start_page); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, XD_CARD) != - STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } -#ifdef XD_DELAY_WRITE - } -#endif - } else { -#ifdef XD_DELAY_WRITE - retval = xd_delay_write(chip); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return STATUS_FAIL; - } -#endif - - old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); - if (old_blk == BLK_NOT_FOUND) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return STATUS_FAIL; - } - } - - dev_dbg(rtsx_dev(chip), "old_blk = 0x%x\n", old_blk); - - while (total_sec_cnt) { - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - - if ((start_page + total_sec_cnt) > (xd_card->page_off + 1)) - end_page = xd_card->page_off + 1; - else - end_page = start_page + (u8)total_sec_cnt; - - page_cnt = end_page - start_page; - if (srb->sc_data_direction == DMA_FROM_DEVICE) { - retval = xd_read_multiple_pages(chip, old_blk, log_blk, - start_page, end_page, - ptr, &index, &offset); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - return STATUS_FAIL; - } - } else { - retval = xd_write_multiple_pages(chip, old_blk, - new_blk, log_blk, - start_page, end_page, - ptr, &index, &offset); - if (retval != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } - } - - total_sec_cnt -= page_cnt; - if (scsi_sg_count(srb) == 0) - ptr += page_cnt * 512; - - if (total_sec_cnt == 0) - break; - - log_blk++; - zone_no = (int)(log_blk / 1000); - log_off = (u16)(log_blk % 1000); - - if (xd_card->zone[zone_no].build_flag == 0) { - retval = xd_build_l2p_tbl(chip, zone_no); - if (retval != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - } - - old_blk = xd_get_l2p_tbl(chip, zone_no, log_off); - if (old_blk == BLK_NOT_FOUND) { - if (srb->sc_data_direction == DMA_FROM_DEVICE) - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR); - else - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - - return STATUS_FAIL; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE) { - new_blk = xd_get_unused_block(chip, zone_no); - if (new_blk == BLK_NOT_FOUND) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } - } - - start_page = 0; - } - - if (srb->sc_data_direction == DMA_TO_DEVICE && - (end_page != (xd_card->page_off + 1))) { -#ifdef XD_DELAY_WRITE - delay_write->delay_write_flag = 1; - delay_write->old_phyblock = old_blk; - delay_write->new_phyblock = new_blk; - delay_write->logblock = log_blk; - delay_write->pageoff = end_page; -#else - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - chip->card_fail |= XD_CARD; - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - - retval = xd_finish_write(chip, old_blk, new_blk, - log_blk, end_page); - if (retval != STATUS_SUCCESS) { - if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) { - set_sense_type(chip, lun, - SENSE_TYPE_MEDIA_NOT_PRESENT); - return STATUS_FAIL; - } - set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR); - return STATUS_FAIL; - } -#endif - } - - scsi_set_resid(srb, 0); - - return STATUS_SUCCESS; -} - -void xd_free_l2p_tbl(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int i = 0; - - if (xd_card->zone) { - for (i = 0; i < xd_card->zone_cnt; i++) { - vfree(xd_card->zone[i].l2p_table); - xd_card->zone[i].l2p_table = NULL; - vfree(xd_card->zone[i].free_table); - xd_card->zone[i].free_table = NULL; - } - vfree(xd_card->zone); - xd_card->zone = NULL; - } -} - -void xd_cleanup_work(struct rtsx_chip *chip) -{ -#ifdef XD_DELAY_WRITE - struct xd_info *xd_card = &chip->xd_card; - - if (xd_card->delay_write.delay_write_flag) { - dev_dbg(rtsx_dev(chip), "xD: delay write\n"); - xd_delay_write(chip); - xd_card->cleanup_counter = 0; - } -#endif -} - -int xd_power_off_card3v3(struct rtsx_chip *chip) -{ - int retval; - - retval = disable_card_clock(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - retval = rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0); - if (retval) - return retval; - - if (!chip->ft2_fast_mode) { - retval = card_power_off(chip, XD_CARD); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - wait_timeout(50); - } - - if (chip->asic_code) { - retval = xd_pull_ctl_disable(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - } else { - retval = rtsx_write_register(chip, FPGA_PULL_CTL, 0xFF, 0xDF); - if (retval) - return retval; - } - - return STATUS_SUCCESS; -} - -int release_xd_card(struct rtsx_chip *chip) -{ - struct xd_info *xd_card = &chip->xd_card; - int retval; - - chip->card_ready &= ~XD_CARD; - chip->card_fail &= ~XD_CARD; - chip->card_wp &= ~XD_CARD; - - xd_card->delay_write.delay_write_flag = 0; - - xd_free_l2p_tbl(chip); - - retval = xd_power_off_card3v3(chip); - if (retval != STATUS_SUCCESS) - return STATUS_FAIL; - - return STATUS_SUCCESS; -} diff --git a/drivers/staging/rts5208/xd.h b/drivers/staging/rts5208/xd.h deleted file mode 100644 index 98c00f268e56127dc2d5e4bbf8de3f3178cea056..0000000000000000000000000000000000000000 --- a/drivers/staging/rts5208/xd.h +++ /dev/null @@ -1,176 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Driver for Realtek PCI-Express card reader - * - * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. - * - * Author: - * Wei WANG (wei_wang@realsil.com.cn) - * Micky Ching (micky_ching@realsil.com.cn) - */ - -#ifndef __REALTEK_RTSX_XD_H -#define __REALTEK_RTSX_XD_H - -#define XD_DELAY_WRITE - -/* Error Codes */ -#define XD_NO_ERROR 0x00 -#define XD_NO_MEMORY 0x80 -#define XD_PRG_ERROR 0x40 -#define XD_NO_CARD 0x20 -#define XD_READ_FAIL 0x10 -#define XD_ERASE_FAIL 0x08 -#define XD_WRITE_FAIL 0x04 -#define XD_ECC_ERROR 0x02 -#define XD_TO_ERROR 0x01 - -/* XD Commands */ -#define READ1_1 0x00 -#define READ1_2 0x01 -#define READ2 0x50 -#define READ_ID 0x90 -#define RESET 0xff -#define PAGE_PRG_1 0x80 -#define PAGE_PRG_2 0x10 -#define BLK_ERASE_1 0x60 -#define BLK_ERASE_2 0xD0 -#define READ_STS 0x70 -#define READ_XD_ID 0x9A -#define COPY_BACK_512 0x8A -#define COPY_BACK_2K 0x85 -#define READ1_1_2 0x30 -#define READ1_1_3 0x35 -#define CHG_DAT_OUT_1 0x05 -#define RDM_DAT_OUT_1 0x05 -#define CHG_DAT_OUT_2 0xE0 -#define RDM_DAT_OUT_2 0xE0 -#define CHG_DAT_OUT_2 0xE0 -#define CHG_DAT_IN_1 0x85 -#define CACHE_PRG 0x15 - -/* Redundant Area Related */ -#define XD_EXTRA_SIZE 0x10 -#define XD_2K_EXTRA_SIZE 0x40 - -#define NOT_WRITE_PROTECTED 0x80 -#define READY_STATE 0x40 -#define PROGRAM_ERROR 0x01 -#define PROGRAM_ERROR_N_1 0x02 -#define INTERNAL_READY 0x20 -#define READY_FLAG 0x5F - -#define XD_8M_X8_512 0xE6 -#define XD_16M_X8_512 0x73 -#define XD_32M_X8_512 0x75 -#define XD_64M_X8_512 0x76 -#define XD_128M_X8_512 0x79 -#define XD_256M_X8_512 0x71 -#define XD_128M_X8_2048 0xF1 -#define XD_256M_X8_2048 0xDA -#define XD_512M_X8 0xDC -#define XD_128M_X16_2048 0xC1 -#define XD_4M_X8_512_1 0xE3 -#define XD_4M_X8_512_2 0xE5 -#define XD_1G_X8_512 0xD3 -#define XD_2G_X8_512 0xD5 - -#define XD_ID_CODE 0xB5 - -#define VENDOR_BLOCK 0xEFFF -#define CIS_BLOCK 0xDFFF - -#define BLK_NOT_FOUND 0xFFFFFFFF - -#define NO_NEW_BLK 0xFFFFFFFF - -#define PAGE_CORRECTABLE 0x0 -#define PAGE_NOTCORRECTABLE 0x1 - -#define NO_OFFSET 0x0 -#define WITH_OFFSET 0x1 - -#define SECT_PER_PAGE 4 -#define XD_ADDR_MODE_2C XD_ADDR_MODE_2A - -#define ZONE0_BAD_BLOCK 23 -#define NOT_ZONE0_BAD_BLOCK 24 - -#define XD_RW_ADDR 0x01 -#define XD_ERASE_ADDR 0x02 - -#define XD_PAGE_512(xd_card) \ -do { \ - (xd_card)->block_shift = 5; \ - (xd_card)->page_off = 0x1F; \ -} while (0) - -#define XD_SET_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag |= 0x01) -#define XD_CLR_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag &= ~0x01) -#define XD_CHK_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag & 0x01) - -#define XD_SET_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag |= 0x02) -#define XD_CLR_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag &= ~0x02) -#define XD_CHK_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag & 0x02) - -#define XD_SET_MBR_FAIL(xd_card) ((xd_card)->multi_flag |= 0x04) -#define XD_CLR_MBR_FAIL(xd_card) ((xd_card)->multi_flag &= ~0x04) -#define XD_CHK_MBR_FAIL(xd_card) ((xd_card)->multi_flag & 0x04) - -#define XD_SET_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag |= 0x08) -#define XD_CLR_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag &= ~0x08) -#define XD_CHK_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag & 0x08) - -#define XD_SET_4MB(xd_card) ((xd_card)->multi_flag |= 0x10) -#define XD_CLR_4MB(xd_card) ((xd_card)->multi_flag &= ~0x10) -#define XD_CHK_4MB(xd_card) ((xd_card)->multi_flag & 0x10) - -#define XD_SET_ECC_ERR(xd_card) ((xd_card)->multi_flag |= 0x40) -#define XD_CLR_ECC_ERR(xd_card) ((xd_card)->multi_flag &= ~0x40) -#define XD_CHK_ECC_ERR(xd_card) ((xd_card)->multi_flag & 0x40) - -#define PAGE_STATUS 0 -#define BLOCK_STATUS 1 -#define BLOCK_ADDR1_L 2 -#define BLOCK_ADDR1_H 3 -#define BLOCK_ADDR2_L 4 -#define BLOCK_ADDR2_H 5 -#define RESERVED0 6 -#define RESERVED1 7 -#define RESERVED2 8 -#define RESERVED3 9 -#define PARITY 10 - -#define CIS0_0 0 -#define CIS0_1 1 -#define CIS0_2 2 -#define CIS0_3 3 -#define CIS0_4 4 -#define CIS0_5 5 -#define CIS0_6 6 -#define CIS0_7 7 -#define CIS0_8 8 -#define CIS0_9 9 -#define CIS1_0 256 -#define CIS1_1 (256 + 1) -#define CIS1_2 (256 + 2) -#define CIS1_3 (256 + 3) -#define CIS1_4 (256 + 4) -#define CIS1_5 (256 + 5) -#define CIS1_6 (256 + 6) -#define CIS1_7 (256 + 7) -#define CIS1_8 (256 + 8) -#define CIS1_9 (256 + 9) - -int reset_xd_card(struct rtsx_chip *chip); -#ifdef XD_DELAY_WRITE -int xd_delay_write(struct rtsx_chip *chip); -#endif -int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, - u32 start_sector, u16 sector_cnt); -void xd_free_l2p_tbl(struct rtsx_chip *chip); -void xd_cleanup_work(struct rtsx_chip *chip); -int xd_power_off_card3v3(struct rtsx_chip *chip); -int release_xd_card(struct rtsx_chip *chip); - -#endif /* __REALTEK_RTSX_XD_H */ diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO index 481409eb3fb384f71a9fb91262b0e9010e5200bb..9dd57c56625704f2b9f377706620e995c63c1aae 100644 --- a/drivers/staging/sm750fb/TODO +++ b/drivers/staging/sm750fb/TODO @@ -12,8 +12,3 @@ TODO: Note: - This driver will be removed from staging after the drm driver is ready - The drm driver is getting ready at https://gitlab.com/sudipm/sm750/tree/sm750 - -Please send any patches to - Greg Kroah-Hartman <greg@kroah.com> - Sudip Mukherjee <sudipm.mukherjee@gmail.com> - Teddy Wang <teddy.wang@siliconmotion.com> diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 133ed15f3dbcc07dc353c22d8522e11a08ee6f46..dc0d715ed97078ad0f0a41db78428db4f4135a76 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -96,7 +96,8 @@ static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance, static int audio_vchi_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason, struct vchiq_header *header, - unsigned int handle, void *userdata) + unsigned int handle, + void *cb_data, void __user *cb_userdata) { struct bcm2835_audio_instance *instance = vchiq_get_service_userdata(vchiq_instance, handle); diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h index 6c40d8c1dde60723ddeb451733648b811d39be16..ee4469f4fc510e540fe5e11d793e50655ee068a1 100644 --- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h +++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h @@ -56,7 +56,7 @@ struct vchiq_service_base { enum vchiq_reason reason, struct vchiq_header *header, unsigned int handle, - void *bulk_userdata); + void *cb_data, void __user *cb_userdata); void *userdata; }; @@ -64,7 +64,8 @@ struct vchiq_completion_data_kernel { enum vchiq_reason reason; struct vchiq_header *header; void *service_userdata; - void *bulk_userdata; + void *cb_data; + void __user *cb_userdata; }; struct vchiq_service_params_kernel { @@ -73,7 +74,7 @@ struct vchiq_service_params_kernel { enum vchiq_reason reason, struct vchiq_header *header, unsigned int handle, - void *bulk_userdata); + void *cb_data, void __user *cb_userdata); void *userdata; short version; /* Increment for non-trivial changes */ short version_min; /* Update for incompatible changes */ diff --git a/drivers/staging/vc04_services/interface/TESTING b/drivers/staging/vc04_services/interface/TESTING index 273952dc9d85964266814f265c205e465d4ded5f..c98f688b07e0fe788c61619bf1acddc0ec32aeaa 100644 --- a/drivers/staging/vc04_services/interface/TESTING +++ b/drivers/staging/vc04_services/interface/TESTING @@ -52,10 +52,10 @@ Here are the most common kernel configurations: * Ping test - Command: vchiq_test -p 1 + Command: vchiq_test -p Expected output: - Ping test - service:echo, iters:1, version 3 + Ping test - service:echo, iters:1000, version 3 vchi ping (size 0) -> 57.000000us vchi ping (size 0, 0 async, 0 oneway) -> 122.000000us vchi bulk (size 0, 0 async, 0 oneway) -> 546.000000us diff --git a/drivers/staging/vc04_services/interface/TODO b/drivers/staging/vc04_services/interface/TODO index dfb1ee49633fe294bee2ca5f11b5add88d0200cc..f6f24600aa86240fba77169f62f3e657e42727c3 100644 --- a/drivers/staging/vc04_services/interface/TODO +++ b/drivers/staging/vc04_services/interface/TODO @@ -26,16 +26,3 @@ kthreads, userspace, limitations) could be very helpful for reviewers. The code follows the 80 characters limitation yet tends to go 3 or 4 levels of indentation deep making it very unpleasant to read. This is specially relevant in the character driver ioctl code and in the core thread functions. - -* Clean up Sparse warnings from __user annotations. See -vchiq_irq_queue_bulk_tx_rx(). Ensure that the address of "&waiter->bulk_waiter" -is never disclosed to userspace. - -* Fix behavior of message handling - -The polling behavior of vchiq_bulk_transmit(), vchiq_bulk_receive() and -vchiq_queue_kernel_message() looks broken. A possible signal should be -propagated back to user space to let the calling task handle it before -retrying. Hopefully these msleep(1) shouldn't be necessary anymore. - -https://lore.kernel.org/linux-staging/CAK8P3a3HGm1cPo4sW9fOY4E8AN8yAq3tevXxU5m8bmtmsU8WKw@mail.gmail.com/ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 6c488b1e2624850d51fbc507965b66333521c86a..a4e83e5d619bc95f1d4ba311a201bba8c05cd030 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -14,7 +14,6 @@ #include <linux/device.h> #include <linux/device/bus.h> #include <linux/mm.h> -#include <linux/highmem.h> #include <linux/pagemap.h> #include <linux/bug.h> #include <linux/completion.h> @@ -36,7 +35,6 @@ #include "vchiq_arm.h" #include "vchiq_bus.h" #include "vchiq_debugfs.h" -#include "vchiq_pagelist.h" #define DEVICE_NAME "vchiq" @@ -48,7 +46,6 @@ #define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 #define BELL0 0x00 -#define BELL2 0x08 #define ARM_DS_ACTIVE BIT(2) @@ -109,21 +106,9 @@ struct vchiq_arm_state { int first_connect; }; -struct vchiq_pagelist_info { - struct pagelist *pagelist; - size_t pagelist_buffer_size; - dma_addr_t dma_addr; - enum dma_data_direction dma_dir; - unsigned int num_pages; - unsigned int pages_need_release; - struct page **pages; - struct scatterlist *scatterlist; - unsigned int scatterlist_mapped; -}; - static int -vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data, - unsigned int size, enum vchiq_bulk_dir dir); +vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk_params); static irqreturn_t vchiq_doorbell_irq(int irq, void *dev_id) @@ -146,35 +131,6 @@ vchiq_doorbell_irq(int irq, void *dev_id) return ret; } -static void -cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo) -{ - if (pagelistinfo->scatterlist_mapped) { - dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist, - pagelistinfo->num_pages, pagelistinfo->dma_dir); - } - - if (pagelistinfo->pages_need_release) - unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages); - - dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size, - pagelistinfo->pagelist, pagelistinfo->dma_addr); -} - -static inline bool -is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k) -{ - u32 tmp; - - if (!k) - return false; - - tmp = (addrs[k - 1] & PAGE_MASK) + - (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT); - - return tmp == (addr & PAGE_MASK); -} - /* * This function is called by the vchiq stack once it has been connected to * the videocore and clients can start to use the stack. @@ -225,270 +181,6 @@ void vchiq_add_connected_callback(struct vchiq_device *device, void (*callback)( } EXPORT_SYMBOL(vchiq_add_connected_callback); -/* There is a potential problem with partial cache lines (pages?) - * at the ends of the block when reading. If the CPU accessed anything in - * the same line (page?) then it may have pulled old data into the cache, - * obscuring the new data underneath. We can solve this by transferring the - * partial cache lines separately, and allowing the ARM to copy into the - * cached area. - */ - -static struct vchiq_pagelist_info * -create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf, - size_t count, unsigned short type) -{ - struct vchiq_drv_mgmt *drv_mgmt; - struct pagelist *pagelist; - struct vchiq_pagelist_info *pagelistinfo; - struct page **pages; - u32 *addrs; - unsigned int num_pages, offset, i, k; - int actual_pages; - size_t pagelist_size; - struct scatterlist *scatterlist, *sg; - int dma_buffers; - dma_addr_t dma_addr; - - if (count >= INT_MAX - PAGE_SIZE) - return NULL; - - drv_mgmt = dev_get_drvdata(instance->state->dev); - - if (buf) - offset = (uintptr_t)buf & (PAGE_SIZE - 1); - else - offset = (uintptr_t)ubuf & (PAGE_SIZE - 1); - num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE); - - if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) - - sizeof(struct vchiq_pagelist_info)) / - (sizeof(u32) + sizeof(pages[0]) + - sizeof(struct scatterlist))) - return NULL; - - pagelist_size = sizeof(struct pagelist) + - (num_pages * sizeof(u32)) + - (num_pages * sizeof(pages[0]) + - (num_pages * sizeof(struct scatterlist))) + - sizeof(struct vchiq_pagelist_info); - - /* Allocate enough storage to hold the page pointers and the page - * list - */ - pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr, - GFP_KERNEL); - - dev_dbg(instance->state->dev, "arm: %pK\n", pagelist); - - if (!pagelist) - return NULL; - - addrs = pagelist->addrs; - pages = (struct page **)(addrs + num_pages); - scatterlist = (struct scatterlist *)(pages + num_pages); - pagelistinfo = (struct vchiq_pagelist_info *) - (scatterlist + num_pages); - - pagelist->length = count; - pagelist->type = type; - pagelist->offset = offset; - - /* Populate the fields of the pagelistinfo structure */ - pagelistinfo->pagelist = pagelist; - pagelistinfo->pagelist_buffer_size = pagelist_size; - pagelistinfo->dma_addr = dma_addr; - pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE; - pagelistinfo->num_pages = num_pages; - pagelistinfo->pages_need_release = 0; - pagelistinfo->pages = pages; - pagelistinfo->scatterlist = scatterlist; - pagelistinfo->scatterlist_mapped = 0; - - if (buf) { - unsigned long length = count; - unsigned int off = offset; - - for (actual_pages = 0; actual_pages < num_pages; - actual_pages++) { - struct page *pg = - vmalloc_to_page((buf + - (actual_pages * PAGE_SIZE))); - size_t bytes = PAGE_SIZE - off; - - if (!pg) { - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - - if (bytes > length) - bytes = length; - pages[actual_pages] = pg; - length -= bytes; - off = 0; - } - /* do not try and release vmalloc pages */ - } else { - actual_pages = pin_user_pages_fast((unsigned long)ubuf & PAGE_MASK, num_pages, - type == PAGELIST_READ, pages); - - if (actual_pages != num_pages) { - dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n", - actual_pages, num_pages); - - /* This is probably due to the process being killed */ - if (actual_pages > 0) - unpin_user_pages(pages, actual_pages); - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - /* release user pages */ - pagelistinfo->pages_need_release = 1; - } - - /* - * Initialize the scatterlist so that the magic cookie - * is filled if debugging is enabled - */ - sg_init_table(scatterlist, num_pages); - /* Now set the pages for each scatterlist */ - for (i = 0; i < num_pages; i++) { - unsigned int len = PAGE_SIZE - offset; - - if (len > count) - len = count; - sg_set_page(scatterlist + i, pages[i], len, offset); - offset = 0; - count -= len; - } - - dma_buffers = dma_map_sg(instance->state->dev, - scatterlist, - num_pages, - pagelistinfo->dma_dir); - - if (dma_buffers == 0) { - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - - pagelistinfo->scatterlist_mapped = 1; - - /* Combine adjacent blocks for performance */ - k = 0; - for_each_sg(scatterlist, sg, dma_buffers, i) { - unsigned int len = sg_dma_len(sg); - dma_addr_t addr = sg_dma_address(sg); - - /* Note: addrs is the address + page_count - 1 - * The firmware expects blocks after the first to be page- - * aligned and a multiple of the page size - */ - WARN_ON(len == 0); - WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK)); - WARN_ON(i && (addr & ~PAGE_MASK)); - if (is_adjacent_block(addrs, addr, k)) - addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT); - else - addrs[k++] = (addr & PAGE_MASK) | - (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1); - } - - /* Partial cache lines (fragments) require special measures */ - if ((type == PAGELIST_READ) && - ((pagelist->offset & (drv_mgmt->info->cache_line_size - 1)) || - ((pagelist->offset + pagelist->length) & - (drv_mgmt->info->cache_line_size - 1)))) { - char *fragments; - - if (down_interruptible(&drv_mgmt->free_fragments_sema)) { - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - - WARN_ON(!drv_mgmt->free_fragments); - - down(&drv_mgmt->free_fragments_mutex); - fragments = drv_mgmt->free_fragments; - WARN_ON(!fragments); - drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments; - up(&drv_mgmt->free_fragments_mutex); - pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + - (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size; - } - - return pagelistinfo; -} - -static void -free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo, - int actual) -{ - struct vchiq_drv_mgmt *drv_mgmt; - struct pagelist *pagelist = pagelistinfo->pagelist; - struct page **pages = pagelistinfo->pages; - unsigned int num_pages = pagelistinfo->num_pages; - - dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual); - - drv_mgmt = dev_get_drvdata(instance->state->dev); - - /* - * NOTE: dma_unmap_sg must be called before the - * cpu can touch any of the data/pages. - */ - dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist, - pagelistinfo->num_pages, pagelistinfo->dma_dir); - pagelistinfo->scatterlist_mapped = 0; - - /* Deal with any partial cache lines (fragments) */ - if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) { - char *fragments = drv_mgmt->fragments_base + - (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * - drv_mgmt->fragments_size; - int head_bytes, tail_bytes; - - head_bytes = (drv_mgmt->info->cache_line_size - pagelist->offset) & - (drv_mgmt->info->cache_line_size - 1); - tail_bytes = (pagelist->offset + actual) & - (drv_mgmt->info->cache_line_size - 1); - - if ((actual >= 0) && (head_bytes != 0)) { - if (head_bytes > actual) - head_bytes = actual; - - memcpy_to_page(pages[0], - pagelist->offset, - fragments, - head_bytes); - } - if ((actual >= 0) && (head_bytes < actual) && - (tail_bytes != 0)) - memcpy_to_page(pages[num_pages - 1], - (pagelist->offset + actual) & - (PAGE_SIZE - 1) & ~(drv_mgmt->info->cache_line_size - 1), - fragments + drv_mgmt->info->cache_line_size, - tail_bytes); - - down(&drv_mgmt->free_fragments_mutex); - *(char **)fragments = drv_mgmt->free_fragments; - drv_mgmt->free_fragments = fragments; - up(&drv_mgmt->free_fragments_mutex); - up(&drv_mgmt->free_fragments_sema); - } - - /* Need to mark all the pages dirty. */ - if (pagelist->type != PAGELIST_WRITE && - pagelistinfo->pages_need_release) { - unsigned int i; - - for (i = 0; i < num_pages; i++) - set_page_dirty(pages[i]); - } - - cleanup_pagelistinfo(instance, pagelistinfo); -} - static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) { struct device *dev = &pdev->dev; @@ -616,58 +308,6 @@ static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state * return (struct vchiq_arm_state *)state->platform_state; } -void -remote_event_signal(struct vchiq_state *state, struct remote_event *event) -{ - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev); - - /* - * Ensure that all writes to shared data structures have completed - * before signalling the peer. - */ - wmb(); - - event->fired = 1; - - dsb(sy); /* data barrier operation */ - - if (event->armed) - writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */ -} - -int -vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk, void *offset, - void __user *uoffset, int size, int dir) -{ - struct vchiq_pagelist_info *pagelistinfo; - - pagelistinfo = create_pagelist(instance, offset, uoffset, size, - (dir == VCHIQ_BULK_RECEIVE) - ? PAGELIST_READ - : PAGELIST_WRITE); - - if (!pagelistinfo) - return -ENOMEM; - - bulk->data = pagelistinfo->dma_addr; - - /* - * Store the pagelistinfo address in remote_data, - * which isn't used by the slave. - */ - bulk->remote_data = pagelistinfo; - - return 0; -} - -void -vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk) -{ - if (bulk && bulk->remote_data && bulk->actual) - free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data, - bulk->actual); -} - void vchiq_dump_platform_state(struct seq_file *f) { seq_puts(f, " Platform: 2835 (VC master)\n"); @@ -851,34 +491,31 @@ int vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int handle, const void *data, unsigned int size, void *userdata, enum vchiq_bulk_mode mode) { + struct vchiq_bulk bulk_params = {}; int ret; - while (1) { - switch (mode) { - case VCHIQ_BULK_MODE_NOCALLBACK: - case VCHIQ_BULK_MODE_CALLBACK: - ret = vchiq_bulk_xfer_callback_interruptible(instance, handle, - (void *)data, NULL, - size, mode, userdata, - VCHIQ_BULK_TRANSMIT); - break; - case VCHIQ_BULK_MODE_BLOCKING: - ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size, - VCHIQ_BULK_TRANSMIT); - break; - default: - return -EINVAL; - } - - /* - * vchiq_*_bulk_transfer() may return -EAGAIN, so we need - * to implement a retry mechanism since this function is - * supposed to block until queued - */ - if (ret != -EAGAIN) - break; - - msleep(1); + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + + bulk_params.offset = (void *)data; + bulk_params.mode = mode; + bulk_params.size = size; + bulk_params.cb_data = userdata; + bulk_params.dir = VCHIQ_BULK_TRANSMIT; + + ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params); + break; + case VCHIQ_BULK_MODE_BLOCKING: + bulk_params.offset = (void *)data; + bulk_params.mode = mode; + bulk_params.size = size; + bulk_params.dir = VCHIQ_BULK_TRANSMIT; + + ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params); + break; + default: + return -EINVAL; } return ret; @@ -889,34 +526,31 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle, void *data, unsigned int size, void *userdata, enum vchiq_bulk_mode mode) { + struct vchiq_bulk bulk_params = {}; int ret; - while (1) { - switch (mode) { - case VCHIQ_BULK_MODE_NOCALLBACK: - case VCHIQ_BULK_MODE_CALLBACK: - ret = vchiq_bulk_xfer_callback_interruptible(instance, handle, - (void *)data, NULL, - size, mode, userdata, - VCHIQ_BULK_RECEIVE); - break; - case VCHIQ_BULK_MODE_BLOCKING: - ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size, - VCHIQ_BULK_RECEIVE); - break; - default: - return -EINVAL; - } - - /* - * vchiq_*_bulk_transfer() may return -EAGAIN, so we need - * to implement a retry mechanism since this function is - * supposed to block until queued - */ - if (ret != -EAGAIN) - break; - - msleep(1); + switch (mode) { + case VCHIQ_BULK_MODE_NOCALLBACK: + case VCHIQ_BULK_MODE_CALLBACK: + + bulk_params.offset = (void *)data; + bulk_params.mode = mode; + bulk_params.size = size; + bulk_params.cb_data = userdata; + bulk_params.dir = VCHIQ_BULK_RECEIVE; + + ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params); + break; + case VCHIQ_BULK_MODE_BLOCKING: + bulk_params.offset = (void *)data; + bulk_params.mode = mode; + bulk_params.size = size; + bulk_params.dir = VCHIQ_BULK_RECEIVE; + + ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params); + break; + default: + return -EINVAL; } return ret; @@ -924,8 +558,8 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle, EXPORT_SYMBOL(vchiq_bulk_receive); static int -vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data, - unsigned int size, enum vchiq_bulk_dir dir) +vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk_params) { struct vchiq_service *service; struct bulk_waiter_node *waiter = NULL, *iter; @@ -953,13 +587,14 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl if (bulk) { /* This thread has an outstanding bulk transfer. */ /* FIXME: why compare a dma address to a pointer? */ - if ((bulk->data != (dma_addr_t)(uintptr_t)data) || (bulk->size != size)) { + if ((bulk->dma_addr != (dma_addr_t)(uintptr_t)bulk_params->dma_addr) || + (bulk->size != bulk_params->size)) { /* * This is not a retry of the previous one. * Cancel the signal when the transfer completes. */ spin_lock(&service->state->bulk_waiter_spinlock); - bulk->userdata = NULL; + bulk->waiter = NULL; spin_unlock(&service->state->bulk_waiter_spinlock); } } @@ -969,15 +604,16 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl return -ENOMEM; } - ret = vchiq_bulk_xfer_blocking_interruptible(instance, handle, data, NULL, size, - &waiter->bulk_waiter, dir); + bulk_params->waiter = &waiter->bulk_waiter; + + ret = vchiq_bulk_xfer_blocking(instance, handle, bulk_params); if ((ret != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; if (bulk) { /* Cancel the signal when the transfer completes. */ spin_lock(&service->state->bulk_waiter_spinlock); - bulk->userdata = NULL; + bulk->waiter = NULL; spin_unlock(&service->state->bulk_waiter_spinlock); } kfree(waiter); @@ -996,7 +632,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl static int add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, struct vchiq_header *header, struct user_service *user_service, - void *bulk_userdata) + void *cb_data, void __user *cb_userdata) { struct vchiq_completion_data_kernel *completion; struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev); @@ -1026,7 +662,8 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, completion->reason = reason; /* N.B. service_userdata is updated while processing AWAIT_COMPLETION */ completion->service_userdata = user_service->service; - completion->bulk_userdata = bulk_userdata; + completion->cb_data = cb_data; + completion->cb_userdata = cb_userdata; if (reason == VCHIQ_SERVICE_CLOSED) { /* @@ -1057,8 +694,8 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, static int service_single_message(struct vchiq_instance *instance, - enum vchiq_reason reason, - struct vchiq_service *service, void *bulk_userdata) + enum vchiq_reason reason, struct vchiq_service *service, + void *cb_data, void __user *cb_userdata) { struct user_service *user_service; @@ -1076,7 +713,7 @@ service_single_message(struct vchiq_instance *instance, dev_dbg(instance->state->dev, "arm: Inserting extra MESSAGE_AVAILABLE\n"); ret = add_completion(instance, reason, NULL, user_service, - bulk_userdata); + cb_data, cb_userdata); if (ret) return ret; } @@ -1094,7 +731,8 @@ service_single_message(struct vchiq_instance *instance, int service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, - struct vchiq_header *header, unsigned int handle, void *bulk_userdata) + struct vchiq_header *header, unsigned int handle, + void *cb_data, void __user *cb_userdata) { /* * How do we ensure the callback goes to the right client? @@ -1133,9 +771,9 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, rcu_read_unlock(); dev_dbg(service->state->dev, - "arm: service %p(%d,%p), reason %d, header %p, instance %p, bulk_userdata %p\n", + "arm: service %p(%d,%p), reason %d, header %p, instance %p, cb_data %p, cb_userdata %p\n", user_service, service->localport, user_service->userdata, - reason, header, instance, bulk_userdata); + reason, header, instance, cb_data, cb_userdata); if (header && user_service->is_vchi) { spin_lock(&service->state->msg_queue_spinlock); @@ -1147,8 +785,8 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, DEBUG_TRACE(SERVICE_CALLBACK_LINE); DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); - ret = service_single_message(instance, reason, - service, bulk_userdata); + ret = service_single_message(instance, reason, service, + cb_data, cb_userdata); if (ret) { DEBUG_TRACE(SERVICE_CALLBACK_LINE); vchiq_service_put(service); @@ -1186,7 +824,7 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, return 0; return add_completion(instance, reason, header, user_service, - bulk_userdata); + cb_data, cb_userdata); } void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f) @@ -1273,7 +911,8 @@ static int vchiq_keepalive_vchiq_callback(struct vchiq_instance *instance, enum vchiq_reason reason, struct vchiq_header *header, - unsigned int service_user, void *bulk_user) + unsigned int service_user, + void *cb_data, void __user *cb_userdata) { dev_err(instance->state->dev, "suspend: %s: callback reason %d\n", __func__, reason); @@ -1715,7 +1354,6 @@ MODULE_DEVICE_TABLE(of, vchiq_of_match); static int vchiq_probe(struct platform_device *pdev) { - struct device_node *fw_node; const struct vchiq_platform_info *info; struct vchiq_drv_mgmt *mgmt; int ret; @@ -1724,8 +1362,8 @@ static int vchiq_probe(struct platform_device *pdev) if (!info) return -EINVAL; - fw_node = of_find_compatible_node(NULL, NULL, - "raspberrypi,bcm2835-firmware"); + struct device_node *fw_node __free(device_node) = + of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware"); if (!fw_node) { dev_err(&pdev->dev, "Missing firmware node\n"); return -ENOENT; @@ -1736,7 +1374,6 @@ static int vchiq_probe(struct platform_device *pdev) return -ENOMEM; mgmt->fw = devm_rpi_firmware_get(&pdev->dev, fw_node); - of_node_put(fw_node); if (!mgmt->fw) return -EPROBE_DEFER; @@ -1744,8 +1381,10 @@ static int vchiq_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mgmt); ret = vchiq_platform_init(pdev, &mgmt->state); - if (ret) - goto failed_platform_init; + if (ret) { + dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n"); + return ret; + } vchiq_debugfs_init(&mgmt->state); @@ -1759,18 +1398,13 @@ static int vchiq_probe(struct platform_device *pdev) ret = vchiq_register_chrdev(&pdev->dev); if (ret) { dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n"); - goto error_exit; + return ret; } bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio"); bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera"); return 0; - -failed_platform_init: - dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n"); -error_exit: - return ret; } static void vchiq_remove(struct platform_device *pdev) @@ -1797,7 +1431,7 @@ static struct platform_driver vchiq_driver = { .of_match_table = vchiq_of_match, }, .probe = vchiq_probe, - .remove_new = vchiq_remove, + .remove = vchiq_remove, }; static int __init vchiq_driver_init(void) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h index b402aac333d9b9c7babfbecc2faeac20bc397fc6..e32b02f990244b46ab97c463dab6a973fdd97033 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -155,7 +155,8 @@ static inline int vchiq_register_chrdev(struct device *parent) { return 0; } extern int service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason, - struct vchiq_header *header, unsigned int handle, void *bulk_userdata); + struct vchiq_header *header, unsigned int handle, + void *cb_data, void __user *cb_userdata); extern void free_bulk_waiter(struct vchiq_instance *instance); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 1f94db6e0cd984847207a2b3668af1326ac77820..8d5795db4f39f8003310a54ba369367c95e6c079 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -5,6 +5,8 @@ #include <linux/completion.h> #include <linux/mutex.h> #include <linux/bitops.h> +#include <linux/io.h> +#include <linux/highmem.h> #include <linux/kthread.h> #include <linux/wait.h> #include <linux/delay.h> @@ -61,12 +63,16 @@ #define MAKE_REMOTE_USE (VCHIQ_MSG_REMOTE_USE << TYPE_SHIFT) #define MAKE_REMOTE_USE_ACTIVE (VCHIQ_MSG_REMOTE_USE_ACTIVE << TYPE_SHIFT) +#define PAGELIST_WRITE 0 +#define PAGELIST_READ 1 +#define PAGELIST_READ_WITH_FRAGMENTS 2 + +#define BELL2 0x08 + /* Ensure the fields are wide enough */ -static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) - == 0); +static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) == 0); static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); -static_assert((unsigned int)VCHIQ_PORT_MAX < - (unsigned int)VCHIQ_PORT_FREE); +static_assert((unsigned int)VCHIQ_PORT_MAX < (unsigned int)VCHIQ_PORT_FREE); #define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) #define VCHIQ_MSGID_CLAIMED 0x40000000 @@ -449,15 +455,26 @@ mark_service_closing(struct vchiq_service *service) static inline int make_service_callback(struct vchiq_service *service, enum vchiq_reason reason, - struct vchiq_header *header, void *bulk_userdata) + struct vchiq_header *header, struct vchiq_bulk *bulk) { + void *cb_data = NULL; + void __user *cb_userdata = NULL; int status; - dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK)\n", + /* + * If a bulk transfer is in progress, pass bulk->cb_*data to the + * callback function. + */ + if (bulk) { + cb_data = bulk->cb_data; + cb_userdata = bulk->cb_userdata; + } + + dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK %pK)\n", service->state->id, service->localport, reason_names[reason], - header, bulk_userdata); + header, cb_data, cb_userdata); status = service->base.callback(service->instance, reason, header, service->handle, - bulk_userdata); + cb_data, cb_userdata); if (status && (status != -EAGAIN)) { dev_warn(service->state->dev, "core: %d: ignoring ERROR from callback to service %x\n", @@ -526,6 +543,25 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) return ret; } +static void +remote_event_signal(struct vchiq_state *state, struct remote_event *event) +{ + struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev); + + /* + * Ensure that all writes to shared data structures have completed + * before signalling the peer. + */ + wmb(); + + event->fired = 1; + + dsb(sy); /* data barrier operation */ + + if (event->armed) + writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */ +} + /* * Acknowledge that the event has been signalled, and wake any waiters. Usually * called as a result of the doorbell being rung. @@ -911,6 +947,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, struct vchiq_service_quota *quota = NULL; struct vchiq_header *header; int type = VCHIQ_MSG_TYPE(msgid); + int svc_fourcc; size_t stride; @@ -922,7 +959,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && mutex_lock_killable(&state->slot_mutex)) - return -EAGAIN; + return -EINTR; if (type == VCHIQ_MSG_DATA) { int tx_end_index; @@ -962,8 +999,8 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, spin_unlock(&state->quota_spinlock); mutex_unlock(&state->slot_mutex); - if (wait_for_completion_interruptible(&state->data_quota_event)) - return -EAGAIN; + if (wait_for_completion_killable(&state->data_quota_event)) + return -EINTR; mutex_lock(&state->slot_mutex); spin_lock(&state->quota_spinlock); @@ -986,12 +1023,12 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, quota->message_use_count, quota->slot_use_count); VCHIQ_SERVICE_STATS_INC(service, quota_stalls); mutex_unlock(&state->slot_mutex); - if (wait_for_completion_interruptible("a->quota_event)) - return -EAGAIN; + if (wait_for_completion_killable("a->quota_event)) + return -EINTR; if (service->closing) return -EHOSTDOWN; if (mutex_lock_killable(&state->slot_mutex)) - return -EAGAIN; + return -EINTR; if (service->srvstate != VCHIQ_SRVSTATE_OPEN) { /* The service has been closed */ mutex_unlock(&state->slot_mutex); @@ -1103,17 +1140,13 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service, header->msgid = msgid; header->size = size; - { - int svc_fourcc; - - svc_fourcc = service - ? service->base.fourcc - : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); + svc_fourcc = service ? service->base.fourcc + : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); - dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n", - msg_type_str(VCHIQ_MSG_TYPE(msgid)), VCHIQ_MSG_TYPE(msgid), - &svc_fourcc, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size); - } + dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n", + msg_type_str(VCHIQ_MSG_TYPE(msgid)), + VCHIQ_MSG_TYPE(msgid), &svc_fourcc, + VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size); /* Make sure the new header is visible to the peer. */ wmb(); @@ -1175,9 +1208,8 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service, state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); - callback_result = - copy_message_data(copy_callback, context, - header->data, size); + callback_result = copy_message_data(copy_callback, context, + header->data, size); if (callback_result < 0) { mutex_unlock(&state->slot_mutex); @@ -1288,6 +1320,42 @@ get_bulk_reason(struct vchiq_bulk *bulk) return VCHIQ_BULK_RECEIVE_DONE; } +static int service_notify_bulk(struct vchiq_service *service, + struct vchiq_bulk *bulk) +{ + if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { + if (bulk->dir == VCHIQ_BULK_TRANSMIT) { + VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count); + VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes, + bulk->actual); + } else { + VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count); + VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes, + bulk->actual); + } + } else { + VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count); + } + + if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { + struct bulk_waiter *waiter; + + spin_lock(&service->state->bulk_waiter_spinlock); + waiter = bulk->waiter; + if (waiter) { + waiter->actual = bulk->actual; + complete(&waiter->event); + } + spin_unlock(&service->state->bulk_waiter_spinlock); + } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) { + enum vchiq_reason reason = get_bulk_reason(bulk); + + return make_service_callback(service, reason, NULL, bulk); + } + + return 0; +} + /* Called by the slot handler - don't hold the bulk mutex */ static int notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, @@ -1311,38 +1379,10 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, * Only generate callbacks for non-dummy bulk * requests, and non-terminated services */ - if (bulk->data && service->instance) { - if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { - if (bulk->dir == VCHIQ_BULK_TRANSMIT) { - VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes, - bulk->actual); - } else { - VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count); - VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes, - bulk->actual); - } - } else { - VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count); - } - if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { - struct bulk_waiter *waiter; - - spin_lock(&service->state->bulk_waiter_spinlock); - waiter = bulk->userdata; - if (waiter) { - waiter->actual = bulk->actual; - complete(&waiter->event); - } - spin_unlock(&service->state->bulk_waiter_spinlock); - } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) { - enum vchiq_reason reason = - get_bulk_reason(bulk); - status = make_service_callback(service, reason, NULL, - bulk->userdata); - if (status == -EAGAIN) - break; - } + if (bulk->dma_addr && service->instance) { + status = service_notify_bulk(service, bulk); + if (status == -EAGAIN) + break; } queue->remove++; @@ -1415,6 +1455,331 @@ poll_services(struct vchiq_state *state) poll_services_of_group(state, group); } +static void +cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo) +{ + if (pagelistinfo->scatterlist_mapped) { + dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist, + pagelistinfo->num_pages, pagelistinfo->dma_dir); + } + + if (pagelistinfo->pages_need_release) + unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages); + + dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size, + pagelistinfo->pagelist, pagelistinfo->dma_addr); +} + +static inline bool +is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k) +{ + u32 tmp; + + if (!k) + return false; + + tmp = (addrs[k - 1] & PAGE_MASK) + + (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT); + + return tmp == (addr & PAGE_MASK); +} + +/* There is a potential problem with partial cache lines (pages?) + * at the ends of the block when reading. If the CPU accessed anything in + * the same line (page?) then it may have pulled old data into the cache, + * obscuring the new data underneath. We can solve this by transferring the + * partial cache lines separately, and allowing the ARM to copy into the + * cached area. + */ +static struct vchiq_pagelist_info * +create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk) +{ + struct vchiq_drv_mgmt *drv_mgmt; + struct pagelist *pagelist; + struct vchiq_pagelist_info *pagelistinfo; + struct page **pages; + u32 *addrs; + unsigned int num_pages, offset, i, k; + int actual_pages; + size_t pagelist_size; + struct scatterlist *scatterlist, *sg; + int dma_buffers; + unsigned int cache_line_size; + dma_addr_t dma_addr; + size_t count = bulk->size; + unsigned short type = (bulk->dir == VCHIQ_BULK_RECEIVE) + ? PAGELIST_READ : PAGELIST_WRITE; + + if (count >= INT_MAX - PAGE_SIZE) + return NULL; + + drv_mgmt = dev_get_drvdata(instance->state->dev); + + if (bulk->offset) + offset = (uintptr_t)bulk->offset & (PAGE_SIZE - 1); + else + offset = (uintptr_t)bulk->uoffset & (PAGE_SIZE - 1); + num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE); + + if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) - + sizeof(struct vchiq_pagelist_info)) / + (sizeof(u32) + sizeof(pages[0]) + + sizeof(struct scatterlist))) + return NULL; + + pagelist_size = sizeof(struct pagelist) + + (num_pages * sizeof(u32)) + + (num_pages * sizeof(pages[0]) + + (num_pages * sizeof(struct scatterlist))) + + sizeof(struct vchiq_pagelist_info); + + /* Allocate enough storage to hold the page pointers and the page + * list + */ + pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr, + GFP_KERNEL); + + dev_dbg(instance->state->dev, "arm: %pK\n", pagelist); + + if (!pagelist) + return NULL; + + addrs = pagelist->addrs; + pages = (struct page **)(addrs + num_pages); + scatterlist = (struct scatterlist *)(pages + num_pages); + pagelistinfo = (struct vchiq_pagelist_info *) + (scatterlist + num_pages); + + pagelist->length = count; + pagelist->type = type; + pagelist->offset = offset; + + /* Populate the fields of the pagelistinfo structure */ + pagelistinfo->pagelist = pagelist; + pagelistinfo->pagelist_buffer_size = pagelist_size; + pagelistinfo->dma_addr = dma_addr; + pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE; + pagelistinfo->num_pages = num_pages; + pagelistinfo->pages_need_release = 0; + pagelistinfo->pages = pages; + pagelistinfo->scatterlist = scatterlist; + pagelistinfo->scatterlist_mapped = 0; + + if (bulk->offset) { + unsigned long length = count; + unsigned int off = offset; + + for (actual_pages = 0; actual_pages < num_pages; + actual_pages++) { + struct page *pg = + vmalloc_to_page(((unsigned int *)bulk->offset + + (actual_pages * PAGE_SIZE))); + size_t bytes = PAGE_SIZE - off; + + if (!pg) { + cleanup_pagelistinfo(instance, pagelistinfo); + return NULL; + } + + if (bytes > length) + bytes = length; + pages[actual_pages] = pg; + length -= bytes; + off = 0; + } + /* do not try and release vmalloc pages */ + } else { + actual_pages = + pin_user_pages_fast((unsigned long)bulk->uoffset & PAGE_MASK, num_pages, + type == PAGELIST_READ, pages); + + if (actual_pages != num_pages) { + dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n", + actual_pages, num_pages); + + /* This is probably due to the process being killed */ + if (actual_pages > 0) + unpin_user_pages(pages, actual_pages); + cleanup_pagelistinfo(instance, pagelistinfo); + return NULL; + } + /* release user pages */ + pagelistinfo->pages_need_release = 1; + } + + /* + * Initialize the scatterlist so that the magic cookie + * is filled if debugging is enabled + */ + sg_init_table(scatterlist, num_pages); + /* Now set the pages for each scatterlist */ + for (i = 0; i < num_pages; i++) { + unsigned int len = PAGE_SIZE - offset; + + if (len > count) + len = count; + sg_set_page(scatterlist + i, pages[i], len, offset); + offset = 0; + count -= len; + } + + dma_buffers = dma_map_sg(instance->state->dev, + scatterlist, + num_pages, + pagelistinfo->dma_dir); + + if (dma_buffers == 0) { + cleanup_pagelistinfo(instance, pagelistinfo); + return NULL; + } + + pagelistinfo->scatterlist_mapped = 1; + + /* Combine adjacent blocks for performance */ + k = 0; + for_each_sg(scatterlist, sg, dma_buffers, i) { + unsigned int len = sg_dma_len(sg); + dma_addr_t addr = sg_dma_address(sg); + + /* Note: addrs is the address + page_count - 1 + * The firmware expects blocks after the first to be page- + * aligned and a multiple of the page size + */ + WARN_ON(len == 0); + WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK)); + WARN_ON(i && (addr & ~PAGE_MASK)); + if (is_adjacent_block(addrs, addr, k)) + addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT); + else + addrs[k++] = (addr & PAGE_MASK) | + (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1); + } + + /* Partial cache lines (fragments) require special measures */ + cache_line_size = drv_mgmt->info->cache_line_size; + if ((type == PAGELIST_READ) && + ((pagelist->offset & (cache_line_size - 1)) || + ((pagelist->offset + pagelist->length) & (cache_line_size - 1)))) { + char *fragments; + + if (down_interruptible(&drv_mgmt->free_fragments_sema)) { + cleanup_pagelistinfo(instance, pagelistinfo); + return NULL; + } + + WARN_ON(!drv_mgmt->free_fragments); + + down(&drv_mgmt->free_fragments_mutex); + fragments = drv_mgmt->free_fragments; + WARN_ON(!fragments); + drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments; + up(&drv_mgmt->free_fragments_mutex); + pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + + (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size; + } + + return pagelistinfo; +} + +static void +free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo, + int actual) +{ + struct vchiq_drv_mgmt *drv_mgmt; + struct pagelist *pagelist = pagelistinfo->pagelist; + struct page **pages = pagelistinfo->pages; + unsigned int num_pages = pagelistinfo->num_pages; + unsigned int cache_line_size; + + dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual); + + drv_mgmt = dev_get_drvdata(instance->state->dev); + + /* + * NOTE: dma_unmap_sg must be called before the + * cpu can touch any of the data/pages. + */ + dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist, + pagelistinfo->num_pages, pagelistinfo->dma_dir); + pagelistinfo->scatterlist_mapped = 0; + + /* Deal with any partial cache lines (fragments) */ + cache_line_size = drv_mgmt->info->cache_line_size; + if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) { + char *fragments = drv_mgmt->fragments_base + + (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * + drv_mgmt->fragments_size; + int head_bytes, tail_bytes; + + head_bytes = (cache_line_size - pagelist->offset) & + (cache_line_size - 1); + tail_bytes = (pagelist->offset + actual) & + (cache_line_size - 1); + + if ((actual >= 0) && (head_bytes != 0)) { + if (head_bytes > actual) + head_bytes = actual; + + memcpy_to_page(pages[0], pagelist->offset, + fragments, head_bytes); + } + if ((actual >= 0) && (head_bytes < actual) && + (tail_bytes != 0)) + memcpy_to_page(pages[num_pages - 1], + (pagelist->offset + actual) & + (PAGE_SIZE - 1) & ~(cache_line_size - 1), + fragments + cache_line_size, + tail_bytes); + + down(&drv_mgmt->free_fragments_mutex); + *(char **)fragments = drv_mgmt->free_fragments; + drv_mgmt->free_fragments = fragments; + up(&drv_mgmt->free_fragments_mutex); + up(&drv_mgmt->free_fragments_sema); + } + + /* Need to mark all the pages dirty. */ + if (pagelist->type != PAGELIST_WRITE && + pagelistinfo->pages_need_release) { + unsigned int i; + + for (i = 0; i < num_pages; i++) + set_page_dirty(pages[i]); + } + + cleanup_pagelistinfo(instance, pagelistinfo); +} + +static int +vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk) +{ + struct vchiq_pagelist_info *pagelistinfo; + + pagelistinfo = create_pagelist(instance, bulk); + + if (!pagelistinfo) + return -ENOMEM; + + bulk->dma_addr = pagelistinfo->dma_addr; + + /* + * Store the pagelistinfo address in remote_data, + * which isn't used by the slave. + */ + bulk->remote_data = pagelistinfo; + + return 0; +} + +static void +vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk) +{ + if (bulk && bulk->remote_data && bulk->actual) + free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data, + bulk->actual); +} + /* Called with the bulk_mutex held */ static void abort_outstanding_bulks(struct vchiq_service *service, @@ -1452,7 +1817,7 @@ abort_outstanding_bulks(struct vchiq_service *service, service->remoteport, bulk->size, bulk->remote_size); } else { /* fabricate a matching dummy bulk */ - bulk->data = 0; + bulk->dma_addr = 0; bulk->size = 0; bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : @@ -1468,8 +1833,10 @@ static int parse_open(struct vchiq_state *state, struct vchiq_header *header) { const struct vchiq_open_payload *payload; + struct vchiq_openack_payload ack_payload; struct vchiq_service *service = NULL; int msgid, size; + int openack_id; unsigned int localport, remoteport, fourcc; short version, version_min; @@ -1504,34 +1871,36 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header) } service->peer_version = version; - if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { - struct vchiq_openack_payload ack_payload = { - service->version - }; - int openack_id = MAKE_OPENACK(service->localport, remoteport); + if (service->srvstate != VCHIQ_SRVSTATE_LISTENING) + goto done; - if (state->version_common < - VCHIQ_VERSION_SYNCHRONOUS_MODE) - service->sync = 0; + ack_payload.version = service->version; + openack_id = MAKE_OPENACK(service->localport, remoteport); - /* Acknowledge the OPEN */ - if (service->sync) { - if (queue_message_sync(state, NULL, openack_id, memcpy_copy_callback, - &ack_payload, sizeof(ack_payload)) == -EAGAIN) - goto bail_not_ready; + if (state->version_common < VCHIQ_VERSION_SYNCHRONOUS_MODE) + service->sync = 0; - /* The service is now open */ - set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC); - } else { - if (queue_message(state, NULL, openack_id, memcpy_copy_callback, - &ack_payload, sizeof(ack_payload), 0) == -EAGAIN) - goto bail_not_ready; + /* Acknowledge the OPEN */ + if (service->sync) { + if (queue_message_sync(state, NULL, openack_id, + memcpy_copy_callback, + &ack_payload, + sizeof(ack_payload)) == -EAGAIN) + goto bail_not_ready; - /* The service is now open */ - set_service_state(service, VCHIQ_SRVSTATE_OPEN); - } + /* The service is now open */ + set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC); + } else { + if (queue_message(state, NULL, openack_id, + memcpy_copy_callback, &ack_payload, + sizeof(ack_payload), 0) == -EINTR) + goto bail_not_ready; + + /* The service is now open */ + set_service_state(service, VCHIQ_SRVSTATE_OPEN); } +done: /* Success - the message has been dealt with */ vchiq_service_put(service); return 1; @@ -1539,7 +1908,7 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header) fail_open: /* No available service, or an invalid request - send a CLOSE */ if (queue_message(state, NULL, MAKE_CLOSE(0, VCHIQ_MSG_SRCPORT(msgid)), - NULL, NULL, 0, 0) == -EAGAIN) + NULL, NULL, 0, 0) == -EINTR) goto bail_not_ready; return 1; @@ -1753,7 +2122,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) dev_dbg(state->dev, "core: %d: prs %s@%pK (%d->%d) %x@%pad\n", state->id, msg_type_str(type), header, remoteport, - localport, bulk->actual, &bulk->data); + localport, bulk->actual, &bulk->dma_addr); dev_dbg(state->dev, "core: %d: prs:%d %cx li=%x ri=%x p=%x\n", state->id, localport, @@ -1786,7 +2155,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header) if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { /* Send a PAUSE in response */ if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0, - QMFLAGS_NO_MUTEX_UNLOCK) == -EAGAIN) + QMFLAGS_NO_MUTEX_UNLOCK) == -EINTR) goto bail_not_ready; } /* At this point slot_mutex is held */ @@ -1903,7 +2272,7 @@ handle_poll(struct vchiq_state *state) case VCHIQ_CONNSTATE_PAUSING: if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0, - QMFLAGS_NO_MUTEX_UNLOCK) != -EAGAIN) { + QMFLAGS_NO_MUTEX_UNLOCK) != -EINTR) { vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT); } else { /* Retry later */ @@ -1913,7 +2282,7 @@ handle_poll(struct vchiq_state *state) case VCHIQ_CONNSTATE_RESUMING: if (queue_message(state, NULL, MAKE_RESUME, NULL, NULL, 0, - QMFLAGS_NO_MUTEX_LOCK) != -EAGAIN) { + QMFLAGS_NO_MUTEX_LOCK) != -EINTR) { vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); } else { /* @@ -2662,56 +3031,58 @@ close_service_complete(struct vchiq_service *service, int failstate) * returned to user context. */ static int -vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service, - void *offset, void __user *uoffset, - int size, void *userdata, - enum vchiq_bulk_mode mode, - enum vchiq_bulk_dir dir) +vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service, + struct vchiq_bulk *bulk_params) { struct vchiq_bulk_queue *queue; struct bulk_waiter *bulk_waiter = NULL; struct vchiq_bulk *bulk; struct vchiq_state *state = service->state; - const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; - const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? + const char dir_char = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; + const int dir_msgtype = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; int status = -EINVAL; int payload[2]; - if (mode == VCHIQ_BULK_MODE_BLOCKING) { - bulk_waiter = userdata; + if (bulk_params->mode == VCHIQ_BULK_MODE_BLOCKING) { + bulk_waiter = bulk_params->waiter; init_completion(&bulk_waiter->event); bulk_waiter->actual = 0; bulk_waiter->bulk = NULL; } - queue = (dir == VCHIQ_BULK_TRANSMIT) ? + queue = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? &service->bulk_tx : &service->bulk_rx; if (mutex_lock_killable(&service->bulk_mutex)) - return -EAGAIN; + return -EINTR; if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) { VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); do { mutex_unlock(&service->bulk_mutex); - if (wait_for_completion_interruptible(&service->bulk_remove_event)) - return -EAGAIN; + if (wait_for_completion_killable(&service->bulk_remove_event)) + return -EINTR; if (mutex_lock_killable(&service->bulk_mutex)) - return -EAGAIN; + return -EINTR; } while (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS); } bulk = &queue->bulks[BULK_INDEX(queue->local_insert)]; - bulk->mode = mode; - bulk->dir = dir; - bulk->userdata = userdata; - bulk->size = size; + /* Initiliaze the 'bulk' slot with bulk parameters passed in. */ + bulk->mode = bulk_params->mode; + bulk->dir = bulk_params->dir; + bulk->waiter = bulk_params->waiter; + bulk->cb_data = bulk_params->cb_data; + bulk->cb_userdata = bulk_params->cb_userdata; + bulk->size = bulk_params->size; + bulk->offset = bulk_params->offset; + bulk->uoffset = bulk_params->uoffset; bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; - if (vchiq_prepare_bulk_data(service->instance, bulk, offset, uoffset, size, dir)) + if (vchiq_prepare_bulk_data(service->instance, bulk)) goto unlock_error_exit; /* @@ -2722,21 +3093,21 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service, dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %pK\n", state->id, service->localport, service->remoteport, - dir_char, size, &bulk->data, userdata); + dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data); /* * The slot mutex must be held when the service is being closed, so * claim it here to ensure that isn't happening */ if (mutex_lock_killable(&state->slot_mutex)) { - status = -EAGAIN; + status = -EINTR; goto cancel_bulk_error_exit; } if (service->srvstate != VCHIQ_SRVSTATE_OPEN) goto unlock_both_error_exit; - payload[0] = lower_32_bits(bulk->data); + payload[0] = lower_32_bits(bulk->dma_addr); payload[1] = bulk->size; status = queue_message(state, NULL, @@ -2761,13 +3132,13 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service, state->id, service->localport, dir_char, queue->local_insert, queue->remote_insert, queue->process); - if (bulk_waiter) { - bulk_waiter->bulk = bulk; - if (wait_for_completion_interruptible(&bulk_waiter->event)) - status = -EAGAIN; - else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) - status = -EINVAL; - } + if (bulk_waiter) { + bulk_waiter->bulk = bulk; + if (wait_for_completion_killable(&bulk_waiter->event)) + status = -EINTR; + else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) + status = -EINVAL; + } return status; @@ -2803,19 +3174,21 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) if (close_recvd) { dev_err(state->dev, "core: (1) called in state %s\n", srvstate_names[service->srvstate]); - } else if (is_server) { - if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { - status = -EINVAL; - } else { - service->client_id = 0; - service->remoteport = VCHIQ_PORT_FREE; - if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT) - set_service_state(service, VCHIQ_SRVSTATE_LISTENING); - } - complete(&service->remove_event); - } else { + break; + } else if (!is_server) { vchiq_free_service_internal(service); + break; + } + + if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { + status = -EINVAL; + } else { + service->client_id = 0; + service->remoteport = VCHIQ_PORT_FREE; + if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT) + set_service_state(service, VCHIQ_SRVSTATE_LISTENING); } + complete(&service->remove_event); break; case VCHIQ_SRVSTATE_OPENING: if (close_recvd) { @@ -2945,6 +3318,7 @@ int vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance) { struct vchiq_service *service; + int status = 0; int i; /* Find all services registered to this client and enable them. */ @@ -2956,9 +3330,10 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc } if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { - if (queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0, - QMFLAGS_IS_BLOCKING) == -EAGAIN) - return -EAGAIN; + status = queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0, + QMFLAGS_IS_BLOCKING); + if (status) + return status; vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING); } @@ -2971,7 +3346,7 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc complete(&state->connect); } - return 0; + return status; } void @@ -3105,12 +3480,10 @@ vchiq_remove_service(struct vchiq_instance *instance, unsigned int handle) } int -vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle, - void *offset, void __user *uoffset, int size, - void __user *userdata, enum vchiq_bulk_dir dir) +vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk_params) { struct vchiq_service *service = find_service_by_handle(instance, handle); - enum vchiq_bulk_mode mode = VCHIQ_BULK_MODE_BLOCKING; int status = -EINVAL; if (!service) @@ -3119,15 +3492,13 @@ vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned if (service->srvstate != VCHIQ_SRVSTATE_OPEN) goto error_exit; - if (!offset && !uoffset) + if (!bulk_params->offset && !bulk_params->uoffset) goto error_exit; if (vchiq_check_service(service)) goto error_exit; - - status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset, size, - userdata, mode, dir); + status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params); error_exit: vchiq_service_put(service); @@ -3136,10 +3507,8 @@ error_exit: } int -vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned int handle, - void *offset, void __user *uoffset, int size, - enum vchiq_bulk_mode mode, void *userdata, - enum vchiq_bulk_dir dir) +vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk_params) { struct vchiq_service *service = find_service_by_handle(instance, handle); int status = -EINVAL; @@ -3147,21 +3516,20 @@ vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned if (!service) return -EINVAL; - if (mode != VCHIQ_BULK_MODE_CALLBACK && - mode != VCHIQ_BULK_MODE_NOCALLBACK) + if (bulk_params->mode != VCHIQ_BULK_MODE_CALLBACK && + bulk_params->mode != VCHIQ_BULK_MODE_NOCALLBACK) goto error_exit; if (service->srvstate != VCHIQ_SRVSTATE_OPEN) goto error_exit; - if (!offset && !uoffset) + if (!bulk_params->offset && !bulk_params->uoffset) goto error_exit; if (vchiq_check_service(service)) goto error_exit; - status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset, - size, userdata, mode, dir); + status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params); error_exit: vchiq_service_put(service); @@ -3175,8 +3543,8 @@ error_exit: * and the call should be retried after being returned to user context. */ int -vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance, - unsigned int handle, struct bulk_waiter *userdata) +vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, + unsigned int handle, struct bulk_waiter *waiter) { struct vchiq_service *service = find_service_by_handle(instance, handle); struct bulk_waiter *bulk_waiter; @@ -3185,7 +3553,7 @@ vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance, if (!service) return -EINVAL; - if (!userdata) + if (!waiter) goto error_exit; if (service->srvstate != VCHIQ_SRVSTATE_OPEN) @@ -3194,14 +3562,14 @@ vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance, if (vchiq_check_service(service)) goto error_exit; - bulk_waiter = userdata; + bulk_waiter = waiter; vchiq_service_put(service); status = 0; - if (wait_for_completion_interruptible(&bulk_waiter->event)) - return -EAGAIN; + if (wait_for_completion_killable(&bulk_waiter->event)) + return -EINTR; else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) return -EINVAL; @@ -3267,24 +3635,8 @@ error_exit: int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, void *data, unsigned int size) { - int status; - - while (1) { - status = vchiq_queue_message(instance, handle, memcpy_copy_callback, - data, size); - - /* - * vchiq_queue_message() may return -EAGAIN, so we need to - * implement a retry mechanism since this function is supposed - * to block until queued - */ - if (status != -EAGAIN) - break; - - msleep(1); - } - - return status; + return vchiq_queue_message(instance, handle, memcpy_copy_callback, + data, size); } EXPORT_SYMBOL(vchiq_queue_kernel_message); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 468463f318018ca4ecb6cf6121098ba67934c1aa..9b4e766990a493d6e9d4e0604f2c84f4e7b77804 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -6,11 +6,12 @@ #include <linux/mutex.h> #include <linux/completion.h> -#include <linux/debugfs.h> +#include <linux/dma-mapping.h> #include <linux/dev_printk.h> #include <linux/kthread.h> #include <linux/kref.h> #include <linux/rcupdate.h> +#include <linux/seq_file.h> #include <linux/spinlock_types.h> #include <linux/wait.h> @@ -113,12 +114,16 @@ enum vchiq_bulk_dir { struct vchiq_bulk { short mode; short dir; - void *userdata; - dma_addr_t data; + void *cb_data; + void __user *cb_userdata; + struct bulk_waiter *waiter; + dma_addr_t dma_addr; int size; void *remote_data; int remote_size; int actual; + void *offset; + void __user *uoffset; }; struct vchiq_bulk_queue { @@ -409,6 +414,28 @@ struct vchiq_state { struct opaque_platform_state *platform_state; }; +struct pagelist { + u32 length; + u16 type; + u16 offset; + u32 addrs[1]; /* N.B. 12 LSBs hold the number + * of following pages at consecutive + * addresses. + */ +}; + +struct vchiq_pagelist_info { + struct pagelist *pagelist; + size_t pagelist_buffer_size; + dma_addr_t dma_addr; + enum dma_data_direction dma_dir; + unsigned int num_pages; + unsigned int pages_need_release; + struct page **pages; + struct scatterlist *scatterlist; + unsigned int scatterlist_mapped; +}; + static inline bool vchiq_remote_initialised(const struct vchiq_state *state) { return state->remote && state->remote->initialised; @@ -471,19 +498,16 @@ extern void remote_event_pollall(struct vchiq_state *state); extern int -vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance, - unsigned int handle, struct bulk_waiter *userdata); +vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, unsigned int handle, + struct bulk_waiter *userdata); extern int -vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle, - void *offset, void __user *uoffset, int size, - void __user *userdata, enum vchiq_bulk_dir dir); +vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk); extern int -vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned int handle, - void *offset, void __user *uoffset, int size, - enum vchiq_bulk_mode mode, void *userdata, - enum vchiq_bulk_dir dir); +vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle, + struct vchiq_bulk *bulk); extern void vchiq_dump_state(struct seq_file *f, struct vchiq_state *state); @@ -529,13 +553,6 @@ vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle, void *context, size_t size); -int vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk, void *offset, - void __user *uoffset, int size, int dir); - -void vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk); - -void remote_event_signal(struct vchiq_state *state, struct remote_event *event); - void vchiq_dump_platform_state(struct seq_file *f); void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h index fabffd81b1ec9a1d5e522496f26ee9262216aa47..b29e6693c949937e7b161c047634f0e8d69c27dc 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h @@ -4,7 +4,8 @@ #ifndef VCHIQ_DEBUGFS_H #define VCHIQ_DEBUGFS_H -#include "vchiq_core.h" +struct vchiq_state; +struct vchiq_instance; struct vchiq_debugfs_node { struct dentry *dentry; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c index d41a4624cc92c39eafa1bfdb229b15c3c21ff6aa..454f4341650306654d1365653ab3b570795f3331 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c @@ -288,7 +288,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, { struct vchiq_service *service; struct bulk_waiter_node *waiter = NULL, *iter; - void *userdata; + struct vchiq_bulk bulk_params = {}; int status = 0; int ret; @@ -303,12 +303,14 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, goto out; } - userdata = &waiter->bulk_waiter; - - status = vchiq_bulk_xfer_blocking_interruptible(instance, args->handle, - NULL, args->data, args->size, - userdata, dir); + bulk_params.uoffset = args->data; + bulk_params.mode = args->mode; + bulk_params.size = args->size; + bulk_params.dir = dir; + bulk_params.waiter = &waiter->bulk_waiter; + status = vchiq_bulk_xfer_blocking(instance, args->handle, + &bulk_params); } else if (args->mode == VCHIQ_BULK_MODE_WAITING) { mutex_lock(&instance->bulk_waiter_list_mutex); list_for_each_entry(iter, &instance->bulk_waiter_list, @@ -328,16 +330,18 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, } dev_dbg(service->state->dev, "arm: found bulk_waiter %pK for pid %d\n", waiter, current->pid); - userdata = &waiter->bulk_waiter; - status = vchiq_bulk_xfer_waiting_interruptible(instance, args->handle, userdata); + status = vchiq_bulk_xfer_waiting(instance, args->handle, + &waiter->bulk_waiter); } else { - userdata = args->userdata; - - status = vchiq_bulk_xfer_callback_interruptible(instance, args->handle, NULL, - args->data, args->size, - args->mode, userdata, dir); - + bulk_params.uoffset = args->data; + bulk_params.mode = args->mode; + bulk_params.size = args->size; + bulk_params.dir = dir; + bulk_params.cb_userdata = args->userdata; + + status = vchiq_bulk_xfer_callback(instance, args->handle, + &bulk_params); } if (!waiter) { @@ -350,7 +354,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, if (waiter->bulk_waiter.bulk) { /* Cancel the signal when the transfer completes. */ spin_lock(&service->state->bulk_waiter_spinlock); - waiter->bulk_waiter.bulk->userdata = NULL; + waiter->bulk_waiter.bulk->waiter = NULL; spin_unlock(&service->state->bulk_waiter_spinlock); } kfree(waiter); @@ -410,7 +414,7 @@ struct vchiq_completion_data32 { enum vchiq_reason reason; compat_uptr_t header; compat_uptr_t service_userdata; - compat_uptr_t bulk_userdata; + compat_uptr_t cb_data; }; static int vchiq_put_completion(struct vchiq_completion_data __user *buf, @@ -424,7 +428,7 @@ static int vchiq_put_completion(struct vchiq_completion_data __user *buf, .reason = completion->reason, .header = ptr_to_compat(completion->header), .service_userdata = ptr_to_compat(completion->service_userdata), - .bulk_userdata = ptr_to_compat(completion->bulk_userdata), + .cb_data = ptr_to_compat(completion->cb_userdata), }; if (copy_to_user(&buf32[index], &tmp, sizeof(tmp))) return -EFAULT; @@ -545,11 +549,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance, !instance->use_close_delivered) vchiq_service_put(service); - /* - * FIXME: address space mismatch, does bulk_userdata - * actually point to user or kernel memory? - */ - user_completion.bulk_userdata = completion->bulk_userdata; + user_completion.cb_userdata = completion->cb_userdata; if (vchiq_put_completion(args->buf, &user_completion, ret)) { if (ret == 0) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h index 17550831f86cb9b1fdd7231875593aa2bcd47833..afb71a83cfe7035e5dd61003fa99fd514ca18047 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -47,7 +47,7 @@ struct vchiq_completion_data { enum vchiq_reason reason; struct vchiq_header __user *header; void __user *service_userdata; - void __user *bulk_userdata; + void __user *cb_userdata; }; struct vchiq_await_completion { diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h deleted file mode 100644 index ebd12bfabb63753ac55bd6deb873170948f7b231..0000000000000000000000000000000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_PAGELIST_H -#define VCHIQ_PAGELIST_H - -#define PAGELIST_WRITE 0 -#define PAGELIST_READ 1 -#define PAGELIST_READ_WITH_FRAGMENTS 2 - -struct pagelist { - u32 length; - u16 type; - u16 offset; - u32 addrs[1]; /* N.B. 12 LSBs hold the number - * of following pages at consecutive - * addresses. - */ -}; - -#endif /* VCHIQ_PAGELIST_H */ diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c index 67489c334f7b2dc0d55027659de76ad2bbd37983..3fe482bd279390a7586c49bde00f38c61558ca8e 100644 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c @@ -551,7 +551,8 @@ static void bulk_abort_cb(struct vchiq_mmal_instance *instance, /* incoming event service callback */ static int mmal_service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason, struct vchiq_header *header, - unsigned int handle, void *bulk_ctx) + unsigned int handle, void *cb_data, + void __user *cb_userdata) { struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(vchiq_instance, handle); u32 msg_len; @@ -626,11 +627,11 @@ static int mmal_service_callback(struct vchiq_instance *vchiq_instance, break; case VCHIQ_BULK_RECEIVE_DONE: - bulk_receive_cb(instance, bulk_ctx); + bulk_receive_cb(instance, cb_data); break; case VCHIQ_BULK_RECEIVE_ABORTED: - bulk_abort_cb(instance, bulk_ctx); + bulk_abort_cb(instance, cb_data); break; case VCHIQ_SERVICE_CLOSED: diff --git a/drivers/staging/vme_user/vme_bridge.h b/drivers/staging/vme_user/vme_bridge.h index 9bdc41bb6602102048f8c619fee37b345b3e735c..abf880d68b124cb8cd3603d86efcc7b7bd49709c 100644 --- a/drivers/staging/vme_user/vme_bridge.h +++ b/drivers/staging/vme_user/vme_bridge.h @@ -128,39 +128,49 @@ struct vme_bridge { struct mutex irq_mtx; /* Slave Functions */ - int (*slave_get)(struct vme_slave_resource *, int *, unsigned long long *, - unsigned long long *, dma_addr_t *, u32 *, u32 *); - int (*slave_set)(struct vme_slave_resource *, int, unsigned long long, - unsigned long long, dma_addr_t, u32, u32); + int (*slave_get)(struct vme_slave_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + dma_addr_t *buf_base, u32 *aspace, u32 *cycle); + int (*slave_set)(struct vme_slave_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, + dma_addr_t buf_base, u32 aspace, u32 cycle); /* Master Functions */ - int (*master_get)(struct vme_master_resource *, int *, unsigned long long *, - unsigned long long *, u32 *, u32 *, u32 *); - int (*master_set)(struct vme_master_resource *, int, unsigned long long, - unsigned long long, u32, u32, u32); - ssize_t (*master_read)(struct vme_master_resource *, void *, size_t, loff_t); - ssize_t (*master_write)(struct vme_master_resource *, void *, size_t, loff_t); - unsigned int (*master_rmw)(struct vme_master_resource *, unsigned int, - unsigned int, unsigned int, loff_t); + int (*master_get)(struct vme_master_resource *image, int *enabled, + unsigned long long *vme_base, unsigned long long *size, + u32 *aspace, u32 *cycle, u32 *dwidth); + int (*master_set)(struct vme_master_resource *image, int enabled, + unsigned long long vme_base, unsigned long long size, + u32 aspace, u32 cycle, u32 dwidth); + ssize_t (*master_read)(struct vme_master_resource *image, void *buf, + size_t count, loff_t offset); + ssize_t (*master_write)(struct vme_master_resource *image, void *buf, + size_t count, loff_t offset); + unsigned int (*master_rmw)(struct vme_master_resource *image, + unsigned int mask, unsigned int compare, + unsigned int swap, loff_t offset); /* DMA Functions */ - int (*dma_list_add)(struct vme_dma_list *, struct vme_dma_attr *, - struct vme_dma_attr *, size_t); - int (*dma_list_exec)(struct vme_dma_list *); - int (*dma_list_empty)(struct vme_dma_list *); + int (*dma_list_add)(struct vme_dma_list *list, struct vme_dma_attr *src, + struct vme_dma_attr *dest, size_t count); + int (*dma_list_exec)(struct vme_dma_list *list); + int (*dma_list_empty)(struct vme_dma_list *list); /* Interrupt Functions */ - void (*irq_set)(struct vme_bridge *, int, int, int); - int (*irq_generate)(struct vme_bridge *, int, int); + void (*irq_set)(struct vme_bridge *bridge, int level, int state, int sync); + int (*irq_generate)(struct vme_bridge *bridge, int level, int statid); /* Location monitor functions */ - int (*lm_set)(struct vme_lm_resource *, unsigned long long, u32, u32); - int (*lm_get)(struct vme_lm_resource *, unsigned long long *, u32 *, u32 *); - int (*lm_attach)(struct vme_lm_resource *, int, void (*callback)(void *), void *); - int (*lm_detach)(struct vme_lm_resource *, int); + int (*lm_set)(struct vme_lm_resource *lm, unsigned long long lm_base, + u32 aspace, u32 cycle); + int (*lm_get)(struct vme_lm_resource *lm, unsigned long long *lm_base, + u32 *aspace, u32 *cycle); + int (*lm_attach)(struct vme_lm_resource *lm, int monitor, + void (*callback)(void *), void *data); + int (*lm_detach)(struct vme_lm_resource *lm, int monitor); /* CR/CSR space functions */ - int (*slot_get)(struct vme_bridge *); + int (*slot_get)(struct vme_bridge *bridge); /* Bridge parent interface */ void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *dma); diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig deleted file mode 100644 index 077f62ebe80cddb6b269d98ee1c4767185913c9c..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config VT6655 - tristate "VIA Technologies VT6655 support" - depends on PCI && HAS_IOPORT && MAC80211 && m - help - This is a vendor-written driver for VIA VT6655. diff --git a/drivers/staging/vt6655/Makefile b/drivers/staging/vt6655/Makefile deleted file mode 100644 index e70357ec0af8a1e229b9e3fa9259a0b0e6cef52b..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -vt6655_stage-y += device_main.o \ - card.o \ - channel.o \ - mac.o \ - baseband.o \ - rxtx.o \ - dpc.o \ - power.o \ - srom.o \ - key.o \ - rf.o - -obj-$(CONFIG_VT6655) += vt6655_stage.o diff --git a/drivers/staging/vt6655/TODO b/drivers/staging/vt6655/TODO deleted file mode 100644 index 27654bd0ff5d76125d9c18b746b8ae35018926b3..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/TODO +++ /dev/null @@ -1,20 +0,0 @@ -TODO: -- remove __cplusplus ifdefs -- done -- prepare for merge with vt6656 driver: - - rename DEVICE_PRT() to DBG_PRT() -- done - - share 80211*.h includes - - split rf.c - - remove dead code - - abstract VT3253 chipset specific code -- add common vt665x infrastructure -- kill ttype.h -- switch to use MAC80211 -- verify unsigned long usage for x86-64 arch -- reduce .data footprint -- use kernel coding style -- checkpatch.pl fixes -- sparse fixes -- integrate with drivers/net/wireless - -Please send any patches to Greg Kroah-Hartman <greg@kroah.com> -and Philipp Hortmann <philipp.g.hortmann@gmail.com>. diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c deleted file mode 100644 index f7824396c5ff7009226858aeee573dd685c866c5..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/baseband.c +++ /dev/null @@ -1,2257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions to access baseband - * - * Author: Kyle Hsu - * - * Date: Aug.22, 2002 - * - * Functions: - * bb_get_frame_time - Calculate data frame transmitting time - * bb_read_embedded - Embedded read baseband register via MAC - * bb_write_embedded - Embedded write baseband register via MAC - * bb_vt3253_init - VIA VT3253 baseband chip init code - * - * Revision History: - * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support. - * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and - * BBvCalculateParameter(). - * cancel the setting of MAC_REG_SOFTPWRCTL on - * BBbVT3253Init(). - * Add the comments. - * 09-01-2003 Bryan YC Fan: RF & BB tables updated. - * Modified BBvLoopbackOn & BBvLoopbackOff(). - * - * - */ - -#include "mac.h" -#include "baseband.h" -#include "srom.h" -#include "rf.h" - -/*--------------------- Static Classes ----------------------------*/ - -/*--------------------- Static Variables --------------------------*/ - -/*--------------------- Static Functions --------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Static Definitions -------------------------*/ - -/*--------------------- Static Classes ----------------------------*/ - -/*--------------------- Static Variables --------------------------*/ - -#define CB_VT3253_INIT_FOR_RFMD 446 -static const unsigned char by_vt3253_init_tab_rfmd[CB_VT3253_INIT_FOR_RFMD][2] = { - {0x00, 0x30}, - {0x01, 0x00}, - {0x02, 0x00}, - {0x03, 0x00}, - {0x04, 0x00}, - {0x05, 0x00}, - {0x06, 0x00}, - {0x07, 0x00}, - {0x08, 0x70}, - {0x09, 0x45}, - {0x0a, 0x2a}, - {0x0b, 0x76}, - {0x0c, 0x00}, - {0x0d, 0x01}, - {0x0e, 0x80}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x9d}, - {0x1c, 0x05}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x4a}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0xa8}, - {0x2e, 0x1a}, - {0x2f, 0x0c}, - {0x30, 0x26}, - {0x31, 0x5b}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0xaa}, - {0x37, 0xaa}, - {0x38, 0xff}, - {0x39, 0xff}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x0d}, - {0x3e, 0x51}, - {0x3f, 0x04}, - {0x40, 0x00}, - {0x41, 0x08}, - {0x42, 0x00}, - {0x43, 0x08}, - {0x44, 0x06}, - {0x45, 0x14}, - {0x46, 0x05}, - {0x47, 0x08}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x09}, - {0x4d, 0x80}, - {0x4e, 0x00}, - {0x4f, 0xc5}, - {0x50, 0x14}, - {0x51, 0x19}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0xb0}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x44}, - {0x61, 0x04}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x04}, - {0x67, 0xb7}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x03}, - {0x6e, 0x01}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x80, 0x0b}, - {0x81, 0x00}, - {0x82, 0x3c}, - {0x83, 0x00}, - {0x84, 0x00}, - {0x85, 0x00}, - {0x86, 0x00}, - {0x87, 0x00}, - {0x88, 0x08}, - {0x89, 0x00}, - {0x8a, 0x08}, - {0x8b, 0xa6}, - {0x8c, 0x84}, - {0x8d, 0x47}, - {0x8e, 0xbb}, - {0x8f, 0x02}, - {0x90, 0x21}, - {0x91, 0x0c}, - {0x92, 0x04}, - {0x93, 0x22}, - {0x94, 0x00}, - {0x95, 0x00}, - {0x96, 0x00}, - {0x97, 0xeb}, - {0x98, 0x00}, - {0x99, 0x00}, - {0x9a, 0x00}, - {0x9b, 0x00}, - {0x9c, 0x00}, - {0x9d, 0x00}, - {0x9e, 0x00}, - {0x9f, 0x00}, - {0xa0, 0x00}, - {0xa1, 0x00}, - {0xa2, 0x00}, - {0xa3, 0x00}, - {0xa4, 0x00}, - {0xa5, 0x00}, - {0xa6, 0x10}, - {0xa7, 0x04}, - {0xa8, 0x10}, - {0xa9, 0x00}, - {0xaa, 0x8f}, - {0xab, 0x00}, - {0xac, 0x00}, - {0xad, 0x00}, - {0xae, 0x00}, - {0xaf, 0x80}, - {0xb0, 0x38}, - {0xb1, 0x00}, - {0xb2, 0x00}, - {0xb3, 0x00}, - {0xb4, 0xee}, - {0xb5, 0xff}, - {0xb6, 0x10}, - {0xb7, 0x00}, - {0xb8, 0x00}, - {0xb9, 0x00}, - {0xba, 0x00}, - {0xbb, 0x03}, - {0xbc, 0x00}, - {0xbd, 0x00}, - {0xbe, 0x00}, - {0xbf, 0x00}, - {0xc0, 0x10}, - {0xc1, 0x10}, - {0xc2, 0x18}, - {0xc3, 0x20}, - {0xc4, 0x10}, - {0xc5, 0x00}, - {0xc6, 0x22}, - {0xc7, 0x14}, - {0xc8, 0x0f}, - {0xc9, 0x08}, - {0xca, 0xa4}, - {0xcb, 0xa7}, - {0xcc, 0x3c}, - {0xcd, 0x10}, - {0xce, 0x20}, - {0xcf, 0x00}, - {0xd0, 0x00}, - {0xd1, 0x10}, - {0xd2, 0x00}, - {0xd3, 0x00}, - {0xd4, 0x10}, - {0xd5, 0x33}, - {0xd6, 0x70}, - {0xd7, 0x01}, - {0xd8, 0x00}, - {0xd9, 0x00}, - {0xda, 0x00}, - {0xdb, 0x00}, - {0xdc, 0x00}, - {0xdd, 0x00}, - {0xde, 0x00}, - {0xdf, 0x00}, - {0xe0, 0x00}, - {0xe1, 0x00}, - {0xe2, 0xcc}, - {0xe3, 0x04}, - {0xe4, 0x08}, - {0xe5, 0x10}, - {0xe6, 0x00}, - {0xe7, 0x0e}, - {0xe8, 0x88}, - {0xe9, 0xd4}, - {0xea, 0x05}, - {0xeb, 0xf0}, - {0xec, 0x79}, - {0xed, 0x0f}, - {0xee, 0x04}, - {0xef, 0x04}, - {0xf0, 0x00}, - {0xf1, 0x00}, - {0xf2, 0x00}, - {0xf3, 0x00}, - {0xf4, 0x00}, - {0xf5, 0x00}, - {0xf6, 0x00}, - {0xf7, 0x00}, - {0xf8, 0x00}, - {0xf9, 0x00}, - {0xF0, 0x00}, - {0xF1, 0xF8}, - {0xF0, 0x80}, - {0xF0, 0x00}, - {0xF1, 0xF4}, - {0xF0, 0x81}, - {0xF0, 0x01}, - {0xF1, 0xF0}, - {0xF0, 0x82}, - {0xF0, 0x02}, - {0xF1, 0xEC}, - {0xF0, 0x83}, - {0xF0, 0x03}, - {0xF1, 0xE8}, - {0xF0, 0x84}, - {0xF0, 0x04}, - {0xF1, 0xE4}, - {0xF0, 0x85}, - {0xF0, 0x05}, - {0xF1, 0xE0}, - {0xF0, 0x86}, - {0xF0, 0x06}, - {0xF1, 0xDC}, - {0xF0, 0x87}, - {0xF0, 0x07}, - {0xF1, 0xD8}, - {0xF0, 0x88}, - {0xF0, 0x08}, - {0xF1, 0xD4}, - {0xF0, 0x89}, - {0xF0, 0x09}, - {0xF1, 0xD0}, - {0xF0, 0x8A}, - {0xF0, 0x0A}, - {0xF1, 0xCC}, - {0xF0, 0x8B}, - {0xF0, 0x0B}, - {0xF1, 0xC8}, - {0xF0, 0x8C}, - {0xF0, 0x0C}, - {0xF1, 0xC4}, - {0xF0, 0x8D}, - {0xF0, 0x0D}, - {0xF1, 0xC0}, - {0xF0, 0x8E}, - {0xF0, 0x0E}, - {0xF1, 0xBC}, - {0xF0, 0x8F}, - {0xF0, 0x0F}, - {0xF1, 0xB8}, - {0xF0, 0x90}, - {0xF0, 0x10}, - {0xF1, 0xB4}, - {0xF0, 0x91}, - {0xF0, 0x11}, - {0xF1, 0xB0}, - {0xF0, 0x92}, - {0xF0, 0x12}, - {0xF1, 0xAC}, - {0xF0, 0x93}, - {0xF0, 0x13}, - {0xF1, 0xA8}, - {0xF0, 0x94}, - {0xF0, 0x14}, - {0xF1, 0xA4}, - {0xF0, 0x95}, - {0xF0, 0x15}, - {0xF1, 0xA0}, - {0xF0, 0x96}, - {0xF0, 0x16}, - {0xF1, 0x9C}, - {0xF0, 0x97}, - {0xF0, 0x17}, - {0xF1, 0x98}, - {0xF0, 0x98}, - {0xF0, 0x18}, - {0xF1, 0x94}, - {0xF0, 0x99}, - {0xF0, 0x19}, - {0xF1, 0x90}, - {0xF0, 0x9A}, - {0xF0, 0x1A}, - {0xF1, 0x8C}, - {0xF0, 0x9B}, - {0xF0, 0x1B}, - {0xF1, 0x88}, - {0xF0, 0x9C}, - {0xF0, 0x1C}, - {0xF1, 0x84}, - {0xF0, 0x9D}, - {0xF0, 0x1D}, - {0xF1, 0x80}, - {0xF0, 0x9E}, - {0xF0, 0x1E}, - {0xF1, 0x7C}, - {0xF0, 0x9F}, - {0xF0, 0x1F}, - {0xF1, 0x78}, - {0xF0, 0xA0}, - {0xF0, 0x20}, - {0xF1, 0x74}, - {0xF0, 0xA1}, - {0xF0, 0x21}, - {0xF1, 0x70}, - {0xF0, 0xA2}, - {0xF0, 0x22}, - {0xF1, 0x6C}, - {0xF0, 0xA3}, - {0xF0, 0x23}, - {0xF1, 0x68}, - {0xF0, 0xA4}, - {0xF0, 0x24}, - {0xF1, 0x64}, - {0xF0, 0xA5}, - {0xF0, 0x25}, - {0xF1, 0x60}, - {0xF0, 0xA6}, - {0xF0, 0x26}, - {0xF1, 0x5C}, - {0xF0, 0xA7}, - {0xF0, 0x27}, - {0xF1, 0x58}, - {0xF0, 0xA8}, - {0xF0, 0x28}, - {0xF1, 0x54}, - {0xF0, 0xA9}, - {0xF0, 0x29}, - {0xF1, 0x50}, - {0xF0, 0xAA}, - {0xF0, 0x2A}, - {0xF1, 0x4C}, - {0xF0, 0xAB}, - {0xF0, 0x2B}, - {0xF1, 0x48}, - {0xF0, 0xAC}, - {0xF0, 0x2C}, - {0xF1, 0x44}, - {0xF0, 0xAD}, - {0xF0, 0x2D}, - {0xF1, 0x40}, - {0xF0, 0xAE}, - {0xF0, 0x2E}, - {0xF1, 0x3C}, - {0xF0, 0xAF}, - {0xF0, 0x2F}, - {0xF1, 0x38}, - {0xF0, 0xB0}, - {0xF0, 0x30}, - {0xF1, 0x34}, - {0xF0, 0xB1}, - {0xF0, 0x31}, - {0xF1, 0x30}, - {0xF0, 0xB2}, - {0xF0, 0x32}, - {0xF1, 0x2C}, - {0xF0, 0xB3}, - {0xF0, 0x33}, - {0xF1, 0x28}, - {0xF0, 0xB4}, - {0xF0, 0x34}, - {0xF1, 0x24}, - {0xF0, 0xB5}, - {0xF0, 0x35}, - {0xF1, 0x20}, - {0xF0, 0xB6}, - {0xF0, 0x36}, - {0xF1, 0x1C}, - {0xF0, 0xB7}, - {0xF0, 0x37}, - {0xF1, 0x18}, - {0xF0, 0xB8}, - {0xF0, 0x38}, - {0xF1, 0x14}, - {0xF0, 0xB9}, - {0xF0, 0x39}, - {0xF1, 0x10}, - {0xF0, 0xBA}, - {0xF0, 0x3A}, - {0xF1, 0x0C}, - {0xF0, 0xBB}, - {0xF0, 0x3B}, - {0xF1, 0x08}, - {0xF0, 0x00}, - {0xF0, 0x3C}, - {0xF1, 0x04}, - {0xF0, 0xBD}, - {0xF0, 0x3D}, - {0xF1, 0x00}, - {0xF0, 0xBE}, - {0xF0, 0x3E}, - {0xF1, 0x00}, - {0xF0, 0xBF}, - {0xF0, 0x3F}, - {0xF1, 0x00}, - {0xF0, 0xC0}, - {0xF0, 0x00}, -}; - -#define CB_VT3253B0_INIT_FOR_RFMD 256 -static const unsigned char vt3253b0_rfmd[CB_VT3253B0_INIT_FOR_RFMD][2] = { - {0x00, 0x31}, - {0x01, 0x00}, - {0x02, 0x00}, - {0x03, 0x00}, - {0x04, 0x00}, - {0x05, 0x81}, - {0x06, 0x00}, - {0x07, 0x00}, - {0x08, 0x38}, - {0x09, 0x45}, - {0x0a, 0x2a}, - {0x0b, 0x76}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x80}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x8e}, - {0x1c, 0x06}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x4a}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x34}, - {0x2e, 0x18}, - {0x2f, 0x0c}, - {0x30, 0x26}, - {0x31, 0x5b}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0xaa}, - {0x37, 0xaa}, - {0x38, 0xff}, - {0x39, 0xff}, - {0x3a, 0xf8}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x09}, - {0x3e, 0x0d}, - {0x3f, 0x04}, - {0x40, 0x00}, - {0x41, 0x08}, - {0x42, 0x00}, - {0x43, 0x08}, - {0x44, 0x08}, - {0x45, 0x14}, - {0x46, 0x05}, - {0x47, 0x08}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x09}, - {0x4d, 0x80}, - {0x4e, 0x00}, - {0x4f, 0xc5}, - {0x50, 0x14}, - {0x51, 0x19}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0xb0}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0x39}, - {0x61, 0x83}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0xc0}, - {0x67, 0x49}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, - {0x6d, 0x03}, - {0x6e, 0x01}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x80, 0x89}, - {0x81, 0x00}, - {0x82, 0x0e}, - {0x83, 0x00}, - {0x84, 0x00}, - {0x85, 0x00}, - {0x86, 0x00}, - {0x87, 0x00}, - {0x88, 0x08}, - {0x89, 0x00}, - {0x8a, 0x0e}, - {0x8b, 0xa7}, - {0x8c, 0x88}, - {0x8d, 0x47}, - {0x8e, 0xaa}, - {0x8f, 0x02}, - {0x90, 0x23}, - {0x91, 0x0c}, - {0x92, 0x06}, - {0x93, 0x08}, - {0x94, 0x00}, - {0x95, 0x00}, - {0x96, 0x00}, - {0x97, 0xeb}, - {0x98, 0x00}, - {0x99, 0x00}, - {0x9a, 0x00}, - {0x9b, 0x00}, - {0x9c, 0x00}, - {0x9d, 0x00}, - {0x9e, 0x00}, - {0x9f, 0x00}, - {0xa0, 0x00}, - {0xa1, 0x00}, - {0xa2, 0x00}, - {0xa3, 0xcd}, - {0xa4, 0x07}, - {0xa5, 0x33}, - {0xa6, 0x18}, - {0xa7, 0x00}, - {0xa8, 0x18}, - {0xa9, 0x00}, - {0xaa, 0x28}, - {0xab, 0x00}, - {0xac, 0x00}, - {0xad, 0x00}, - {0xae, 0x00}, - {0xaf, 0x18}, - {0xb0, 0x38}, - {0xb1, 0x30}, - {0xb2, 0x00}, - {0xb3, 0x00}, - {0xb4, 0x00}, - {0xb5, 0x00}, - {0xb6, 0x84}, - {0xb7, 0xfd}, - {0xb8, 0x00}, - {0xb9, 0x00}, - {0xba, 0x00}, - {0xbb, 0x03}, - {0xbc, 0x00}, - {0xbd, 0x00}, - {0xbe, 0x00}, - {0xbf, 0x00}, - {0xc0, 0x10}, - {0xc1, 0x20}, - {0xc2, 0x18}, - {0xc3, 0x20}, - {0xc4, 0x10}, - {0xc5, 0x2c}, - {0xc6, 0x1e}, - {0xc7, 0x10}, - {0xc8, 0x12}, - {0xc9, 0x01}, - {0xca, 0x6f}, - {0xcb, 0xa7}, - {0xcc, 0x3c}, - {0xcd, 0x10}, - {0xce, 0x00}, - {0xcf, 0x22}, - {0xd0, 0x00}, - {0xd1, 0x10}, - {0xd2, 0x00}, - {0xd3, 0x00}, - {0xd4, 0x10}, - {0xd5, 0x33}, - {0xd6, 0x80}, - {0xd7, 0x21}, - {0xd8, 0x00}, - {0xd9, 0x00}, - {0xda, 0x00}, - {0xdb, 0x00}, - {0xdc, 0x00}, - {0xdd, 0x00}, - {0xde, 0x00}, - {0xdf, 0x00}, - {0xe0, 0x00}, - {0xe1, 0xB3}, - {0xe2, 0x00}, - {0xe3, 0x00}, - {0xe4, 0x00}, - {0xe5, 0x10}, - {0xe6, 0x00}, - {0xe7, 0x18}, - {0xe8, 0x08}, - {0xe9, 0xd4}, - {0xea, 0x00}, - {0xeb, 0xff}, - {0xec, 0x79}, - {0xed, 0x10}, - {0xee, 0x30}, - {0xef, 0x02}, - {0xf0, 0x00}, - {0xf1, 0x09}, - {0xf2, 0x00}, - {0xf3, 0x00}, - {0xf4, 0x00}, - {0xf5, 0x00}, - {0xf6, 0x00}, - {0xf7, 0x00}, - {0xf8, 0x00}, - {0xf9, 0x00}, - {0xfa, 0x00}, - {0xfb, 0x00}, - {0xfc, 0x00}, - {0xfd, 0x00}, - {0xfe, 0x00}, - {0xff, 0x00}, -}; - -#define CB_VT3253B0_AGC_FOR_RFMD2959 195 -/* For RFMD2959 */ -static -unsigned char vt3253b0_agc4_rfmd2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = { - {0xF0, 0x00}, - {0xF1, 0x3E}, - {0xF0, 0x80}, - {0xF0, 0x00}, - {0xF1, 0x3E}, - {0xF0, 0x81}, - {0xF0, 0x01}, - {0xF1, 0x3E}, - {0xF0, 0x82}, - {0xF0, 0x02}, - {0xF1, 0x3E}, - {0xF0, 0x83}, - {0xF0, 0x03}, - {0xF1, 0x3B}, - {0xF0, 0x84}, - {0xF0, 0x04}, - {0xF1, 0x39}, - {0xF0, 0x85}, - {0xF0, 0x05}, - {0xF1, 0x38}, - {0xF0, 0x86}, - {0xF0, 0x06}, - {0xF1, 0x37}, - {0xF0, 0x87}, - {0xF0, 0x07}, - {0xF1, 0x36}, - {0xF0, 0x88}, - {0xF0, 0x08}, - {0xF1, 0x35}, - {0xF0, 0x89}, - {0xF0, 0x09}, - {0xF1, 0x35}, - {0xF0, 0x8A}, - {0xF0, 0x0A}, - {0xF1, 0x34}, - {0xF0, 0x8B}, - {0xF0, 0x0B}, - {0xF1, 0x34}, - {0xF0, 0x8C}, - {0xF0, 0x0C}, - {0xF1, 0x33}, - {0xF0, 0x8D}, - {0xF0, 0x0D}, - {0xF1, 0x32}, - {0xF0, 0x8E}, - {0xF0, 0x0E}, - {0xF1, 0x31}, - {0xF0, 0x8F}, - {0xF0, 0x0F}, - {0xF1, 0x30}, - {0xF0, 0x90}, - {0xF0, 0x10}, - {0xF1, 0x2F}, - {0xF0, 0x91}, - {0xF0, 0x11}, - {0xF1, 0x2F}, - {0xF0, 0x92}, - {0xF0, 0x12}, - {0xF1, 0x2E}, - {0xF0, 0x93}, - {0xF0, 0x13}, - {0xF1, 0x2D}, - {0xF0, 0x94}, - {0xF0, 0x14}, - {0xF1, 0x2C}, - {0xF0, 0x95}, - {0xF0, 0x15}, - {0xF1, 0x2B}, - {0xF0, 0x96}, - {0xF0, 0x16}, - {0xF1, 0x2B}, - {0xF0, 0x97}, - {0xF0, 0x17}, - {0xF1, 0x2A}, - {0xF0, 0x98}, - {0xF0, 0x18}, - {0xF1, 0x29}, - {0xF0, 0x99}, - {0xF0, 0x19}, - {0xF1, 0x28}, - {0xF0, 0x9A}, - {0xF0, 0x1A}, - {0xF1, 0x27}, - {0xF0, 0x9B}, - {0xF0, 0x1B}, - {0xF1, 0x26}, - {0xF0, 0x9C}, - {0xF0, 0x1C}, - {0xF1, 0x25}, - {0xF0, 0x9D}, - {0xF0, 0x1D}, - {0xF1, 0x24}, - {0xF0, 0x9E}, - {0xF0, 0x1E}, - {0xF1, 0x24}, - {0xF0, 0x9F}, - {0xF0, 0x1F}, - {0xF1, 0x23}, - {0xF0, 0xA0}, - {0xF0, 0x20}, - {0xF1, 0x22}, - {0xF0, 0xA1}, - {0xF0, 0x21}, - {0xF1, 0x21}, - {0xF0, 0xA2}, - {0xF0, 0x22}, - {0xF1, 0x20}, - {0xF0, 0xA3}, - {0xF0, 0x23}, - {0xF1, 0x20}, - {0xF0, 0xA4}, - {0xF0, 0x24}, - {0xF1, 0x1F}, - {0xF0, 0xA5}, - {0xF0, 0x25}, - {0xF1, 0x1E}, - {0xF0, 0xA6}, - {0xF0, 0x26}, - {0xF1, 0x1D}, - {0xF0, 0xA7}, - {0xF0, 0x27}, - {0xF1, 0x1C}, - {0xF0, 0xA8}, - {0xF0, 0x28}, - {0xF1, 0x1B}, - {0xF0, 0xA9}, - {0xF0, 0x29}, - {0xF1, 0x1B}, - {0xF0, 0xAA}, - {0xF0, 0x2A}, - {0xF1, 0x1A}, - {0xF0, 0xAB}, - {0xF0, 0x2B}, - {0xF1, 0x1A}, - {0xF0, 0xAC}, - {0xF0, 0x2C}, - {0xF1, 0x19}, - {0xF0, 0xAD}, - {0xF0, 0x2D}, - {0xF1, 0x18}, - {0xF0, 0xAE}, - {0xF0, 0x2E}, - {0xF1, 0x17}, - {0xF0, 0xAF}, - {0xF0, 0x2F}, - {0xF1, 0x16}, - {0xF0, 0xB0}, - {0xF0, 0x30}, - {0xF1, 0x15}, - {0xF0, 0xB1}, - {0xF0, 0x31}, - {0xF1, 0x15}, - {0xF0, 0xB2}, - {0xF0, 0x32}, - {0xF1, 0x15}, - {0xF0, 0xB3}, - {0xF0, 0x33}, - {0xF1, 0x14}, - {0xF0, 0xB4}, - {0xF0, 0x34}, - {0xF1, 0x13}, - {0xF0, 0xB5}, - {0xF0, 0x35}, - {0xF1, 0x12}, - {0xF0, 0xB6}, - {0xF0, 0x36}, - {0xF1, 0x11}, - {0xF0, 0xB7}, - {0xF0, 0x37}, - {0xF1, 0x10}, - {0xF0, 0xB8}, - {0xF0, 0x38}, - {0xF1, 0x0F}, - {0xF0, 0xB9}, - {0xF0, 0x39}, - {0xF1, 0x0E}, - {0xF0, 0xBA}, - {0xF0, 0x3A}, - {0xF1, 0x0D}, - {0xF0, 0xBB}, - {0xF0, 0x3B}, - {0xF1, 0x0C}, - {0xF0, 0xBC}, - {0xF0, 0x3C}, - {0xF1, 0x0B}, - {0xF0, 0xBD}, - {0xF0, 0x3D}, - {0xF1, 0x0B}, - {0xF0, 0xBE}, - {0xF0, 0x3E}, - {0xF1, 0x0A}, - {0xF0, 0xBF}, - {0xF0, 0x3F}, - {0xF1, 0x09}, - {0xF0, 0x00}, -}; - -#define CB_VT3253B0_INIT_FOR_AIROHA2230 256 -/* For AIROHA */ -static -unsigned char vt3253b0_airoha2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = { - {0x00, 0x31}, - {0x01, 0x00}, - {0x02, 0x00}, - {0x03, 0x00}, - {0x04, 0x00}, - {0x05, 0x80}, - {0x06, 0x00}, - {0x07, 0x00}, - {0x08, 0x70}, - {0x09, 0x41}, - {0x0a, 0x2A}, - {0x0b, 0x76}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x80}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x8f}, - {0x1c, 0x09}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x4a}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x4a}, - {0x2e, 0x00}, - {0x2f, 0x0a}, - {0x30, 0x26}, - {0x31, 0x5b}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0xaa}, - {0x37, 0xaa}, - {0x38, 0xff}, - {0x39, 0xff}, - {0x3a, 0x79}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x0b}, - {0x3e, 0x48}, - {0x3f, 0x04}, - {0x40, 0x00}, - {0x41, 0x08}, - {0x42, 0x00}, - {0x43, 0x08}, - {0x44, 0x08}, - {0x45, 0x14}, - {0x46, 0x05}, - {0x47, 0x09}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x09}, - {0x4d, 0x73}, - {0x4e, 0x00}, - {0x4f, 0xc5}, - {0x50, 0x15}, - {0x51, 0x19}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0xb0}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0xe4}, - {0x61, 0x80}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x98}, - {0x67, 0x0a}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */ - {0x6d, 0x03}, - {0x6e, 0x01}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x80, 0x8c}, - {0x81, 0x01}, - {0x82, 0x09}, - {0x83, 0x00}, - {0x84, 0x00}, - {0x85, 0x00}, - {0x86, 0x00}, - {0x87, 0x00}, - {0x88, 0x08}, - {0x89, 0x00}, - {0x8a, 0x0f}, - {0x8b, 0xb7}, - {0x8c, 0x88}, - {0x8d, 0x47}, - {0x8e, 0xaa}, - {0x8f, 0x02}, - {0x90, 0x22}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x00}, - {0x96, 0x00}, - {0x97, 0xeb}, - {0x98, 0x00}, - {0x99, 0x00}, - {0x9a, 0x00}, - {0x9b, 0x00}, - {0x9c, 0x00}, - {0x9d, 0x00}, - {0x9e, 0x00}, - {0x9f, 0x01}, - {0xa0, 0x00}, - {0xa1, 0x00}, - {0xa2, 0x00}, - {0xa3, 0x00}, - {0xa4, 0x00}, - {0xa5, 0x00}, - {0xa6, 0x10}, - {0xa7, 0x00}, - {0xa8, 0x18}, - {0xa9, 0x00}, - {0xaa, 0x00}, - {0xab, 0x00}, - {0xac, 0x00}, - {0xad, 0x00}, - {0xae, 0x00}, - {0xaf, 0x18}, - {0xb0, 0x38}, - {0xb1, 0x30}, - {0xb2, 0x00}, - {0xb3, 0x00}, - {0xb4, 0xff}, - {0xb5, 0x0f}, - {0xb6, 0xe4}, - {0xb7, 0xe2}, - {0xb8, 0x00}, - {0xb9, 0x00}, - {0xba, 0x00}, - {0xbb, 0x03}, - {0xbc, 0x01}, - {0xbd, 0x00}, - {0xbe, 0x00}, - {0xbf, 0x00}, - {0xc0, 0x18}, - {0xc1, 0x20}, - {0xc2, 0x07}, - {0xc3, 0x18}, - {0xc4, 0xff}, - {0xc5, 0x2c}, - {0xc6, 0x0c}, - {0xc7, 0x0a}, - {0xc8, 0x0e}, - {0xc9, 0x01}, - {0xca, 0x68}, - {0xcb, 0xa7}, - {0xcc, 0x3c}, - {0xcd, 0x10}, - {0xce, 0x00}, - {0xcf, 0x25}, - {0xd0, 0x40}, - {0xd1, 0x12}, - {0xd2, 0x00}, - {0xd3, 0x00}, - {0xd4, 0x10}, - {0xd5, 0x28}, - {0xd6, 0x80}, - {0xd7, 0x2A}, - {0xd8, 0x00}, - {0xd9, 0x00}, - {0xda, 0x00}, - {0xdb, 0x00}, - {0xdc, 0x00}, - {0xdd, 0x00}, - {0xde, 0x00}, - {0xdf, 0x00}, - {0xe0, 0x00}, - {0xe1, 0xB3}, - {0xe2, 0x00}, - {0xe3, 0x00}, - {0xe4, 0x00}, - {0xe5, 0x10}, - {0xe6, 0x00}, - {0xe7, 0x1C}, - {0xe8, 0x00}, - {0xe9, 0xf4}, - {0xea, 0x00}, - {0xeb, 0xff}, - {0xec, 0x79}, - {0xed, 0x20}, - {0xee, 0x30}, - {0xef, 0x01}, - {0xf0, 0x00}, - {0xf1, 0x3e}, - {0xf2, 0x00}, - {0xf3, 0x00}, - {0xf4, 0x00}, - {0xf5, 0x00}, - {0xf6, 0x00}, - {0xf7, 0x00}, - {0xf8, 0x00}, - {0xf9, 0x00}, - {0xfa, 0x00}, - {0xfb, 0x00}, - {0xfc, 0x00}, - {0xfd, 0x00}, - {0xfe, 0x00}, - {0xff, 0x00}, -}; - -#define CB_VT3253B0_INIT_FOR_UW2451 256 -/* For UW2451 */ -static unsigned char vt3253b0_uw2451[CB_VT3253B0_INIT_FOR_UW2451][2] = { - {0x00, 0x31}, - {0x01, 0x00}, - {0x02, 0x00}, - {0x03, 0x00}, - {0x04, 0x00}, - {0x05, 0x81}, - {0x06, 0x00}, - {0x07, 0x00}, - {0x08, 0x38}, - {0x09, 0x45}, - {0x0a, 0x28}, - {0x0b, 0x76}, - {0x0c, 0x00}, - {0x0d, 0x00}, - {0x0e, 0x80}, - {0x0f, 0x00}, - {0x10, 0x00}, - {0x11, 0x00}, - {0x12, 0x00}, - {0x13, 0x00}, - {0x14, 0x00}, - {0x15, 0x00}, - {0x16, 0x00}, - {0x17, 0x00}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x8f}, - {0x1c, 0x0f}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x1f, 0x00}, - {0x20, 0x00}, - {0x21, 0x00}, - {0x22, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x4a}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x29, 0x00}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2c, 0x00}, - {0x2d, 0x18}, - {0x2e, 0x00}, - {0x2f, 0x0a}, - {0x30, 0x26}, - {0x31, 0x5b}, - {0x32, 0x00}, - {0x33, 0x00}, - {0x34, 0x00}, - {0x35, 0x00}, - {0x36, 0xaa}, - {0x37, 0xaa}, - {0x38, 0xff}, - {0x39, 0xff}, - {0x3a, 0x00}, - {0x3b, 0x00}, - {0x3c, 0x00}, - {0x3d, 0x03}, - {0x3e, 0x1d}, - {0x3f, 0x04}, - {0x40, 0x00}, - {0x41, 0x08}, - {0x42, 0x00}, - {0x43, 0x08}, - {0x44, 0x08}, - {0x45, 0x14}, - {0x46, 0x05}, - {0x47, 0x09}, - {0x48, 0x00}, - {0x49, 0x00}, - {0x4a, 0x00}, - {0x4b, 0x00}, - {0x4c, 0x09}, - {0x4d, 0x90}, - {0x4e, 0x00}, - {0x4f, 0xc5}, - {0x50, 0x15}, - {0x51, 0x19}, - {0x52, 0x00}, - {0x53, 0x00}, - {0x54, 0x00}, - {0x55, 0x00}, - {0x56, 0x00}, - {0x57, 0x00}, - {0x58, 0x00}, - {0x59, 0xb0}, - {0x5a, 0x00}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x00}, - {0x60, 0xb3}, - {0x61, 0x81}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x57}, - {0x67, 0x6c}, - {0x68, 0x00}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6b, 0x00}, - {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */ - {0x6d, 0x03}, - {0x6e, 0x01}, - {0x6f, 0x00}, - {0x70, 0x00}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0x77, 0x00}, - {0x78, 0x00}, - {0x79, 0x00}, - {0x7a, 0x00}, - {0x7b, 0x00}, - {0x7c, 0x00}, - {0x7d, 0x00}, - {0x7e, 0x00}, - {0x7f, 0x00}, - {0x80, 0x8c}, - {0x81, 0x00}, - {0x82, 0x0e}, - {0x83, 0x00}, - {0x84, 0x00}, - {0x85, 0x00}, - {0x86, 0x00}, - {0x87, 0x00}, - {0x88, 0x08}, - {0x89, 0x00}, - {0x8a, 0x0e}, - {0x8b, 0xa7}, - {0x8c, 0x88}, - {0x8d, 0x47}, - {0x8e, 0xaa}, - {0x8f, 0x02}, - {0x90, 0x00}, - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x00}, - {0x96, 0x00}, - {0x97, 0xe3}, - {0x98, 0x00}, - {0x99, 0x00}, - {0x9a, 0x00}, - {0x9b, 0x00}, - {0x9c, 0x00}, - {0x9d, 0x00}, - {0x9e, 0x00}, - {0x9f, 0x00}, - {0xa0, 0x00}, - {0xa1, 0x00}, - {0xa2, 0x00}, - {0xa3, 0x00}, - {0xa4, 0x00}, - {0xa5, 0x00}, - {0xa6, 0x10}, - {0xa7, 0x00}, - {0xa8, 0x18}, - {0xa9, 0x00}, - {0xaa, 0x00}, - {0xab, 0x00}, - {0xac, 0x00}, - {0xad, 0x00}, - {0xae, 0x00}, - {0xaf, 0x18}, - {0xb0, 0x18}, - {0xb1, 0x30}, - {0xb2, 0x00}, - {0xb3, 0x00}, - {0xb4, 0x00}, - {0xb5, 0x00}, - {0xb6, 0x00}, - {0xb7, 0x00}, - {0xb8, 0x00}, - {0xb9, 0x00}, - {0xba, 0x00}, - {0xbb, 0x03}, - {0xbc, 0x01}, - {0xbd, 0x00}, - {0xbe, 0x00}, - {0xbf, 0x00}, - {0xc0, 0x10}, - {0xc1, 0x20}, - {0xc2, 0x00}, - {0xc3, 0x20}, - {0xc4, 0x00}, - {0xc5, 0x2c}, - {0xc6, 0x1c}, - {0xc7, 0x10}, - {0xc8, 0x10}, - {0xc9, 0x01}, - {0xca, 0x68}, - {0xcb, 0xa7}, - {0xcc, 0x3c}, - {0xcd, 0x09}, - {0xce, 0x00}, - {0xcf, 0x20}, - {0xd0, 0x40}, - {0xd1, 0x10}, - {0xd2, 0x00}, - {0xd3, 0x00}, - {0xd4, 0x20}, - {0xd5, 0x28}, - {0xd6, 0xa0}, - {0xd7, 0x2a}, - {0xd8, 0x00}, - {0xd9, 0x00}, - {0xda, 0x00}, - {0xdb, 0x00}, - {0xdc, 0x00}, - {0xdd, 0x00}, - {0xde, 0x00}, - {0xdf, 0x00}, - {0xe0, 0x00}, - {0xe1, 0xd3}, - {0xe2, 0xc0}, - {0xe3, 0x00}, - {0xe4, 0x00}, - {0xe5, 0x10}, - {0xe6, 0x00}, - {0xe7, 0x12}, - {0xe8, 0x12}, - {0xe9, 0x34}, - {0xea, 0x00}, - {0xeb, 0xff}, - {0xec, 0x79}, - {0xed, 0x20}, - {0xee, 0x30}, - {0xef, 0x01}, - {0xf0, 0x00}, - {0xf1, 0x3e}, - {0xf2, 0x00}, - {0xf3, 0x00}, - {0xf4, 0x00}, - {0xf5, 0x00}, - {0xf6, 0x00}, - {0xf7, 0x00}, - {0xf8, 0x00}, - {0xf9, 0x00}, - {0xfa, 0x00}, - {0xfb, 0x00}, - {0xfc, 0x00}, - {0xfd, 0x00}, - {0xfe, 0x00}, - {0xff, 0x00}, -}; - -#define CB_VT3253B0_AGC 193 -/* For AIROHA */ -static unsigned char vt3253b0_agc[CB_VT3253B0_AGC][2] = { - {0xF0, 0x00}, - {0xF1, 0x00}, - {0xF0, 0x80}, - {0xF0, 0x01}, - {0xF1, 0x00}, - {0xF0, 0x81}, - {0xF0, 0x02}, - {0xF1, 0x02}, - {0xF0, 0x82}, - {0xF0, 0x03}, - {0xF1, 0x04}, - {0xF0, 0x83}, - {0xF0, 0x03}, - {0xF1, 0x04}, - {0xF0, 0x84}, - {0xF0, 0x04}, - {0xF1, 0x06}, - {0xF0, 0x85}, - {0xF0, 0x05}, - {0xF1, 0x06}, - {0xF0, 0x86}, - {0xF0, 0x06}, - {0xF1, 0x06}, - {0xF0, 0x87}, - {0xF0, 0x07}, - {0xF1, 0x08}, - {0xF0, 0x88}, - {0xF0, 0x08}, - {0xF1, 0x08}, - {0xF0, 0x89}, - {0xF0, 0x09}, - {0xF1, 0x0A}, - {0xF0, 0x8A}, - {0xF0, 0x0A}, - {0xF1, 0x0A}, - {0xF0, 0x8B}, - {0xF0, 0x0B}, - {0xF1, 0x0C}, - {0xF0, 0x8C}, - {0xF0, 0x0C}, - {0xF1, 0x0C}, - {0xF0, 0x8D}, - {0xF0, 0x0D}, - {0xF1, 0x0E}, - {0xF0, 0x8E}, - {0xF0, 0x0E}, - {0xF1, 0x0E}, - {0xF0, 0x8F}, - {0xF0, 0x0F}, - {0xF1, 0x10}, - {0xF0, 0x90}, - {0xF0, 0x10}, - {0xF1, 0x10}, - {0xF0, 0x91}, - {0xF0, 0x11}, - {0xF1, 0x12}, - {0xF0, 0x92}, - {0xF0, 0x12}, - {0xF1, 0x12}, - {0xF0, 0x93}, - {0xF0, 0x13}, - {0xF1, 0x14}, - {0xF0, 0x94}, - {0xF0, 0x14}, - {0xF1, 0x14}, - {0xF0, 0x95}, - {0xF0, 0x15}, - {0xF1, 0x16}, - {0xF0, 0x96}, - {0xF0, 0x16}, - {0xF1, 0x16}, - {0xF0, 0x97}, - {0xF0, 0x17}, - {0xF1, 0x18}, - {0xF0, 0x98}, - {0xF0, 0x18}, - {0xF1, 0x18}, - {0xF0, 0x99}, - {0xF0, 0x19}, - {0xF1, 0x1A}, - {0xF0, 0x9A}, - {0xF0, 0x1A}, - {0xF1, 0x1A}, - {0xF0, 0x9B}, - {0xF0, 0x1B}, - {0xF1, 0x1C}, - {0xF0, 0x9C}, - {0xF0, 0x1C}, - {0xF1, 0x1C}, - {0xF0, 0x9D}, - {0xF0, 0x1D}, - {0xF1, 0x1E}, - {0xF0, 0x9E}, - {0xF0, 0x1E}, - {0xF1, 0x1E}, - {0xF0, 0x9F}, - {0xF0, 0x1F}, - {0xF1, 0x20}, - {0xF0, 0xA0}, - {0xF0, 0x20}, - {0xF1, 0x20}, - {0xF0, 0xA1}, - {0xF0, 0x21}, - {0xF1, 0x22}, - {0xF0, 0xA2}, - {0xF0, 0x22}, - {0xF1, 0x22}, - {0xF0, 0xA3}, - {0xF0, 0x23}, - {0xF1, 0x24}, - {0xF0, 0xA4}, - {0xF0, 0x24}, - {0xF1, 0x24}, - {0xF0, 0xA5}, - {0xF0, 0x25}, - {0xF1, 0x26}, - {0xF0, 0xA6}, - {0xF0, 0x26}, - {0xF1, 0x26}, - {0xF0, 0xA7}, - {0xF0, 0x27}, - {0xF1, 0x28}, - {0xF0, 0xA8}, - {0xF0, 0x28}, - {0xF1, 0x28}, - {0xF0, 0xA9}, - {0xF0, 0x29}, - {0xF1, 0x2A}, - {0xF0, 0xAA}, - {0xF0, 0x2A}, - {0xF1, 0x2A}, - {0xF0, 0xAB}, - {0xF0, 0x2B}, - {0xF1, 0x2C}, - {0xF0, 0xAC}, - {0xF0, 0x2C}, - {0xF1, 0x2C}, - {0xF0, 0xAD}, - {0xF0, 0x2D}, - {0xF1, 0x2E}, - {0xF0, 0xAE}, - {0xF0, 0x2E}, - {0xF1, 0x2E}, - {0xF0, 0xAF}, - {0xF0, 0x2F}, - {0xF1, 0x30}, - {0xF0, 0xB0}, - {0xF0, 0x30}, - {0xF1, 0x30}, - {0xF0, 0xB1}, - {0xF0, 0x31}, - {0xF1, 0x32}, - {0xF0, 0xB2}, - {0xF0, 0x32}, - {0xF1, 0x32}, - {0xF0, 0xB3}, - {0xF0, 0x33}, - {0xF1, 0x34}, - {0xF0, 0xB4}, - {0xF0, 0x34}, - {0xF1, 0x34}, - {0xF0, 0xB5}, - {0xF0, 0x35}, - {0xF1, 0x36}, - {0xF0, 0xB6}, - {0xF0, 0x36}, - {0xF1, 0x36}, - {0xF0, 0xB7}, - {0xF0, 0x37}, - {0xF1, 0x38}, - {0xF0, 0xB8}, - {0xF0, 0x38}, - {0xF1, 0x38}, - {0xF0, 0xB9}, - {0xF0, 0x39}, - {0xF1, 0x3A}, - {0xF0, 0xBA}, - {0xF0, 0x3A}, - {0xF1, 0x3A}, - {0xF0, 0xBB}, - {0xF0, 0x3B}, - {0xF1, 0x3C}, - {0xF0, 0xBC}, - {0xF0, 0x3C}, - {0xF1, 0x3C}, - {0xF0, 0xBD}, - {0xF0, 0x3D}, - {0xF1, 0x3E}, - {0xF0, 0xBE}, - {0xF0, 0x3E}, - {0xF1, 0x3E}, - {0xF0, 0xBF}, - {0xF0, 0x00}, -}; - -static const unsigned short awc_frame_time[MAX_RATE] = { - 10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216 -}; - -/*--------------------- Export Variables --------------------------*/ -/* - * Description: Calculate data frame transmitting time - * - * Parameters: - * In: - * preamble_type - Preamble Type - * by_pkt_type - PK_TYPE_11A, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA - * cb_frame_length - Baseband Type - * tx_rate - Tx Rate - * Out: - * - * Return Value: FrameTime - * - */ -unsigned int bb_get_frame_time(unsigned char preamble_type, - unsigned char by_pkt_type, - unsigned int cb_frame_length, - unsigned short tx_rate) -{ - unsigned int frame_time; - unsigned int preamble; - unsigned int tmp; - unsigned int rate_idx = (unsigned int)tx_rate; - unsigned int rate = 0; - - if (rate_idx > RATE_54M) - return 0; - - rate = (unsigned int)awc_frame_time[rate_idx]; - - if (rate_idx <= 3) { /* CCK mode */ - if (preamble_type == PREAMBLE_SHORT) - preamble = 96; - else - preamble = 192; - frame_time = (cb_frame_length * 80) / rate; /* ????? */ - tmp = (frame_time * rate) / 80; - if (cb_frame_length != tmp) - frame_time++; - - return preamble + frame_time; - } - frame_time = (cb_frame_length * 8 + 22) / rate; /* ???????? */ - tmp = ((frame_time * rate) - 22) / 8; - if (cb_frame_length != tmp) - frame_time++; - - frame_time = frame_time * 4; /* ??????? */ - if (by_pkt_type != PK_TYPE_11A) - frame_time += 6; /* ?????? */ - - return 20 + frame_time; /* ?????? */ -} - -/* - * Description: Calculate Length, Service, and Signal fields of Phy for Tx - * - * Parameters: - * In: - * priv - Device Structure - * frame_length - Tx Frame Length - * tx_rate - Tx Rate - * Out: - * struct vnt_phy_field *phy - * - pointer to Phy Length field - * - pointer to Phy Service field - * - pointer to Phy Signal field - * - * Return Value: none - * - */ -void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, - u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy) -{ - u32 bit_count; - u32 count = 0; - u32 tmp; - int ext_bit; - u8 preamble_type = priv->preamble_type; - - bit_count = frame_length * 8; - ext_bit = false; - - switch (tx_rate) { - case RATE_1M: - count = bit_count; - - phy->signal = 0x00; - - break; - case RATE_2M: - count = bit_count / 2; - - if (preamble_type == PREAMBLE_SHORT) - phy->signal = 0x09; - else - phy->signal = 0x01; - - break; - case RATE_5M: - count = (bit_count * 10) / 55; - tmp = (count * 55) / 10; - - if (tmp != bit_count) - count++; - - if (preamble_type == PREAMBLE_SHORT) - phy->signal = 0x0a; - else - phy->signal = 0x02; - - break; - case RATE_11M: - count = bit_count / 11; - tmp = count * 11; - - if (tmp != bit_count) { - count++; - - if ((bit_count - tmp) <= 3) - ext_bit = true; - } - - if (preamble_type == PREAMBLE_SHORT) - phy->signal = 0x0b; - else - phy->signal = 0x03; - - break; - case RATE_6M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9b; - else - phy->signal = 0x8b; - - break; - case RATE_9M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9f; - else - phy->signal = 0x8f; - - break; - case RATE_12M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9a; - else - phy->signal = 0x8a; - - break; - case RATE_18M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9e; - else - phy->signal = 0x8e; - - break; - case RATE_24M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x99; - else - phy->signal = 0x89; - - break; - case RATE_36M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9d; - else - phy->signal = 0x8d; - - break; - case RATE_48M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x98; - else - phy->signal = 0x88; - - break; - case RATE_54M: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9c; - else - phy->signal = 0x8c; - break; - default: - if (pkt_type == PK_TYPE_11A) - phy->signal = 0x9c; - else - phy->signal = 0x8c; - break; - } - - if (pkt_type == PK_TYPE_11B) { - phy->service = 0x00; - if (ext_bit) - phy->service |= 0x80; - phy->len = cpu_to_le16((u16)count); - } else { - phy->service = 0x00; - phy->len = cpu_to_le16((u16)frame_length); - } -} - -/* - * Description: Read a byte from BASEBAND, by embedded programming - * - * Parameters: - * In: - * iobase - I/O base address - * by_bb_addr - address of register in Baseband - * Out: - * pby_data - data read - * - * Return Value: true if succeeded; false if failed. - * - */ -bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr, - unsigned char *pby_data) -{ - void __iomem *iobase = priv->port_offset; - unsigned short ww; - unsigned char by_value; - - /* BB reg offset */ - iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR); - - /* turn on REGR */ - vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGR); - /* W_MAX_TIMEOUT is the timeout period */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - by_value = ioread8(iobase + MAC_REG_BBREGCTL); - if (by_value & BBREGCTL_DONE) - break; - } - - /* get BB data */ - *pby_data = ioread8(iobase + MAC_REG_BBREGDATA); - - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x30)\n"); - return false; - } - return true; -} - -/* - * Description: Write a Byte to BASEBAND, by embedded programming - * - * Parameters: - * In: - * iobase - I/O base address - * by_bb_addr - address of register in Baseband - * by_data - data to write - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr, - unsigned char by_data) -{ - void __iomem *iobase = priv->port_offset; - unsigned short ww; - unsigned char by_value; - - /* BB reg offset */ - iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR); - /* set BB data */ - iowrite8(by_data, iobase + MAC_REG_BBREGDATA); - - /* turn on BBREGCTL_REGW */ - vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGW); - /* W_MAX_TIMEOUT is the timeout period */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - by_value = ioread8(iobase + MAC_REG_BBREGCTL); - if (by_value & BBREGCTL_DONE) - break; - } - - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x31)\n"); - return false; - } - return true; -} - -/* - * Description: VIA VT3253 Baseband chip init function - * - * Parameters: - * In: - * iobase - I/O base address - * byRevId - Revision ID - * rf_type - RF type - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ - -bool bb_vt3253_init(struct vnt_private *priv) -{ - bool result = true; - int ii; - void __iomem *iobase = priv->port_offset; - unsigned char rf_type = priv->rf_type; - unsigned char by_local_id = priv->local_id; - - if (rf_type == RF_RFMD2959) { - if (by_local_id <= REV_ID_VT3253_A1) { - for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++) - result &= bb_write_embedded(priv, - by_vt3253_init_tab_rfmd[ii][0], - by_vt3253_init_tab_rfmd[ii][1]); - - } else { - for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++) - result &= bb_write_embedded(priv, - vt3253b0_rfmd[ii][0], - vt3253b0_rfmd[ii][1]); - - for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++) - result &= bb_write_embedded(priv, - vt3253b0_agc4_rfmd2959[ii][0], - vt3253b0_agc4_rfmd2959[ii][1]); - - iowrite32(0x23, iobase + MAC_REG_ITRTMSET); - vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0)); - } - priv->bbvga[0] = 0x18; - priv->bbvga[1] = 0x0A; - priv->bbvga[2] = 0x0; - priv->bbvga[3] = 0x0; - priv->dbm_threshold[0] = -70; - priv->dbm_threshold[1] = -50; - priv->dbm_threshold[2] = 0; - priv->dbm_threshold[3] = 0; - } else if ((rf_type == RF_AIROHA) || (rf_type == RF_AL2230S)) { - for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) - result &= bb_write_embedded(priv, - vt3253b0_airoha2230[ii][0], - vt3253b0_airoha2230[ii][1]); - - for (ii = 0; ii < CB_VT3253B0_AGC; ii++) - result &= bb_write_embedded(priv, - vt3253b0_agc[ii][0], vt3253b0_agc[ii][1]); - - priv->bbvga[0] = 0x1C; - priv->bbvga[1] = 0x10; - priv->bbvga[2] = 0x0; - priv->bbvga[3] = 0x0; - priv->dbm_threshold[0] = -70; - priv->dbm_threshold[1] = -48; - priv->dbm_threshold[2] = 0; - priv->dbm_threshold[3] = 0; - } else if (rf_type == RF_UW2451) { - for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++) - result &= bb_write_embedded(priv, - vt3253b0_uw2451[ii][0], - vt3253b0_uw2451[ii][1]); - - for (ii = 0; ii < CB_VT3253B0_AGC; ii++) - result &= bb_write_embedded(priv, - vt3253b0_agc[ii][0], - vt3253b0_agc[ii][1]); - - iowrite8(0x23, iobase + MAC_REG_ITRTMSET); - vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0)); - - priv->bbvga[0] = 0x14; - priv->bbvga[1] = 0x0A; - priv->bbvga[2] = 0x0; - priv->bbvga[3] = 0x0; - priv->dbm_threshold[0] = -60; - priv->dbm_threshold[1] = -50; - priv->dbm_threshold[2] = 0; - priv->dbm_threshold[3] = 0; - } else if (rf_type == RF_VT3226) { - for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++) - result &= bb_write_embedded(priv, - vt3253b0_airoha2230[ii][0], - vt3253b0_airoha2230[ii][1]); - - for (ii = 0; ii < CB_VT3253B0_AGC; ii++) - result &= bb_write_embedded(priv, - vt3253b0_agc[ii][0], vt3253b0_agc[ii][1]); - - priv->bbvga[0] = 0x1C; - priv->bbvga[1] = 0x10; - priv->bbvga[2] = 0x0; - priv->bbvga[3] = 0x0; - priv->dbm_threshold[0] = -70; - priv->dbm_threshold[1] = -48; - priv->dbm_threshold[2] = 0; - priv->dbm_threshold[3] = 0; - /* Fix VT3226 DFC system timing issue */ - vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT); - /* {{ RobertYu: 20050104 */ - } else { - /* No VGA Table now */ - priv->update_bbvga = false; - priv->bbvga[0] = 0x1C; - } - - if (by_local_id > REV_ID_VT3253_A1) { - bb_write_embedded(priv, 0x04, 0x7F); - bb_write_embedded(priv, 0x0D, 0x01); - } - - return result; -} - -/* - * Description: Set ShortSlotTime mode - * - * Parameters: - * In: - * priv - Device Structure - * Out: - * none - * - * Return Value: none - * - */ -void -bb_set_short_slot_time(struct vnt_private *priv) -{ - unsigned char by_bb_rx_conf = 0; - unsigned char by_bb_vga = 0; - - bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */ - - if (priv->short_slot_time) - by_bb_rx_conf &= 0xDF; /* 1101 1111 */ - else - by_bb_rx_conf |= 0x20; /* 0010 0000 */ - - /* patch for 3253B0 Baseband with Cardbus module */ - bb_read_embedded(priv, 0xE7, &by_bb_vga); - if (by_bb_vga == priv->bbvga[0]) - by_bb_rx_conf |= 0x20; /* 0010 0000 */ - - bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */ -} - -void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data) -{ - unsigned char by_bb_rx_conf = 0; - - bb_write_embedded(priv, 0xE7, by_data); - - bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */ - /* patch for 3253B0 Baseband with Cardbus module */ - if (by_data == priv->bbvga[0]) - by_bb_rx_conf |= 0x20; /* 0010 0000 */ - else if (priv->short_slot_time) - by_bb_rx_conf &= 0xDF; /* 1101 1111 */ - else - by_bb_rx_conf |= 0x20; /* 0010 0000 */ - priv->bbvga_current = by_data; - bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */ -} - -/* - * Description: Baseband SoftwareReset - * - * Parameters: - * In: - * iobase - I/O base address - * Out: - * none - * - * Return Value: none - * - */ -void -bb_software_reset(struct vnt_private *priv) -{ - bb_write_embedded(priv, 0x50, 0x40); - bb_write_embedded(priv, 0x50, 0); - bb_write_embedded(priv, 0x9C, 0x01); - bb_write_embedded(priv, 0x9C, 0); -} - -/* - * Description: Set Tx Antenna mode - * - * Parameters: - * In: - * priv - Device Structure - * by_antenna_mode - Antenna Mode - * Out: - * none - * - * Return Value: none - * - */ - -void -bb_set_tx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode) -{ - unsigned char by_bb_tx_conf; - - bb_read_embedded(priv, 0x09, &by_bb_tx_conf); /* CR09 */ - if (by_antenna_mode == ANT_DIVERSITY) { - /* bit 1 is diversity */ - by_bb_tx_conf |= 0x02; - } else if (by_antenna_mode == ANT_A) { - /* bit 2 is ANTSEL */ - by_bb_tx_conf &= 0xF9; /* 1111 1001 */ - } else if (by_antenna_mode == ANT_B) { - by_bb_tx_conf &= 0xFD; /* 1111 1101 */ - by_bb_tx_conf |= 0x04; - } - bb_write_embedded(priv, 0x09, by_bb_tx_conf); /* CR09 */ -} - -/* - * Description: Set Rx Antenna mode - * - * Parameters: - * In: - * priv - Device Structure - * by_antenna_mode - Antenna Mode - * Out: - * none - * - * Return Value: none - * - */ - -void -bb_set_rx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode) -{ - unsigned char by_bb_rx_conf; - - bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */ - if (by_antenna_mode == ANT_DIVERSITY) { - by_bb_rx_conf |= 0x01; - - } else if (by_antenna_mode == ANT_A) { - by_bb_rx_conf &= 0xFC; /* 1111 1100 */ - } else if (by_antenna_mode == ANT_B) { - by_bb_rx_conf &= 0xFE; /* 1111 1110 */ - by_bb_rx_conf |= 0x02; - } - bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */ -} - -/* - * Description: bb_set_deep_sleep - * - * Parameters: - * In: - * priv - Device Structure - * Out: - * none - * - * Return Value: none - * - */ -void -bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id) -{ - bb_write_embedded(priv, 0x0C, 0x17); /* CR12 */ - bb_write_embedded(priv, 0x0D, 0xB9); /* CR13 */ -} - diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h deleted file mode 100644 index e4a02c240a1c1c3f453229ef7538b4be8568ef94..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/baseband.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions to access baseband - * - * Author: Jerry Chen - * - * Date: Jun. 5, 2002 - * - */ - -#ifndef __BASEBAND_H__ -#define __BASEBAND_H__ - -#include "device.h" - -/* - * Registers in the BASEBAND - */ -#define BB_MAX_CONTEXT_SIZE 256 - -/* - * Baseband RF pair definition in eeprom (Bits 6..0) - */ - -#define PREAMBLE_LONG 0 -#define PREAMBLE_SHORT 1 - -#define F5G 0 -#define F2_4G 1 - -#define TOP_RATE_54M 0x80000000 -#define TOP_RATE_48M 0x40000000 -#define TOP_RATE_36M 0x20000000 -#define TOP_RATE_24M 0x10000000 -#define TOP_RATE_18M 0x08000000 -#define TOP_RATE_12M 0x04000000 -#define TOP_RATE_11M 0x02000000 -#define TOP_RATE_9M 0x01000000 -#define TOP_RATE_6M 0x00800000 -#define TOP_RATE_55M 0x00400000 -#define TOP_RATE_2M 0x00200000 -#define TOP_RATE_1M 0x00100000 - -unsigned int bb_get_frame_time(unsigned char preamble_type, - unsigned char by_pkt_type, - unsigned int cb_frame_length, - unsigned short w_rate); - -void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, - u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy); - -bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr, - unsigned char *pby_data); -bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr, - unsigned char by_data); - -void bb_set_short_slot_time(struct vnt_private *priv); -void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data); - -/* VT3253 Baseband */ -bool bb_vt3253_init(struct vnt_private *priv); -void bb_software_reset(struct vnt_private *priv); -void bb_set_tx_antenna_mode(struct vnt_private *priv, - unsigned char by_antenna_mode); -void bb_set_rx_antenna_mode(struct vnt_private *priv, - unsigned char by_antenna_mode); -void bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id); - -#endif /* __BASEBAND_H__ */ diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c deleted file mode 100644 index 6a2e390e94939a9c6e0181f920de4d550c4c772c..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/card.c +++ /dev/null @@ -1,836 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Provide functions to setup NIC operation mode - * Functions: - * s_vSafeResetTx - Rest Tx - * card_set_rspinf - Set RSPINF - * CARDvUpdateBasicTopRate - Update BasicTopRate - * CARDbAddBasicRate - Add to BasicRateSet - * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet - * card_get_tsf_offset - Calculate TSFOffset - * vt6655_get_current_tsf - Read Current NIC TSF counter - * card_get_next_tbtt - Calculate Next Beacon TSF counter - * CARDvSetFirstNextTBTT - Set NIC Beacon time - * CARDvUpdateNextTBTT - Sync. NIC Beacon time - * card_radio_power_off - Turn Off NIC Radio Power - * - * Revision History: - * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-26-2003 Kyle Hsu: Modify the definition type of iobase. - * 09-01-2003 Bryan YC Fan: Add vUpdateIFS(). - * - */ - -#include "card.h" -#include "baseband.h" -#include "mac.h" -#include "desc.h" -#include "rf.h" -#include "power.h" - -/*--------------------- Static Definitions -------------------------*/ - -#define C_SIFS_A 16 /* micro sec. */ -#define C_SIFS_BG 10 - -#define C_EIFS 80 /* micro sec. */ - -#define C_SLOT_SHORT 9 /* micro sec. */ -#define C_SLOT_LONG 20 - -#define C_CWMIN_A 15 /* slot time */ -#define C_CWMIN_B 31 - -#define C_CWMAX 1023 /* slot time */ - -#define WAIT_BEACON_TX_DOWN_TMO 3 /* Times */ - -/*--------------------- Static Variables --------------------------*/ - -static const unsigned short rx_bcn_tsf_off[MAX_RATE] = { - 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; - -/*--------------------- Static Functions --------------------------*/ - -static void vt6655_mac_set_bb_type(void __iomem *iobase, u32 mask) -{ - u32 reg_value; - - reg_value = ioread32(iobase + MAC_REG_ENCFG); - reg_value = reg_value & ~ENCFG_BBTYPE_MASK; - reg_value = reg_value | mask; - iowrite32(reg_value, iobase + MAC_REG_ENCFG); -} - -/*--------------------- Export Functions --------------------------*/ - -/* - * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode. - * - * Parameters: - * In: - * wRate - Tx Rate - * byPktType - Tx Packet type - * Out: - * tx_rate - pointer to RSPINF TxRate field - * rsv_time - pointer to RSPINF RsvTime field - * - * Return Value: none - */ -static void calculate_ofdmr_parameter(unsigned char rate, - u8 bb_type, - unsigned char *tx_rate, - unsigned char *rsv_time) -{ - switch (rate) { - case RATE_6M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x9B; - *rsv_time = 44; - } else { - *tx_rate = 0x8B; - *rsv_time = 50; - } - break; - - case RATE_9M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x9F; - *rsv_time = 36; - } else { - *tx_rate = 0x8F; - *rsv_time = 42; - } - break; - - case RATE_12M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x9A; - *rsv_time = 32; - } else { - *tx_rate = 0x8A; - *rsv_time = 38; - } - break; - - case RATE_18M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x9E; - *rsv_time = 28; - } else { - *tx_rate = 0x8E; - *rsv_time = 34; - } - break; - - case RATE_36M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x9D; - *rsv_time = 24; - } else { - *tx_rate = 0x8D; - *rsv_time = 30; - } - break; - - case RATE_48M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x98; - *rsv_time = 24; - } else { - *tx_rate = 0x88; - *rsv_time = 30; - } - break; - - case RATE_54M: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x9C; - *rsv_time = 24; - } else { - *tx_rate = 0x8C; - *rsv_time = 30; - } - break; - - case RATE_24M: - default: - if (bb_type == BB_TYPE_11A) { /* 5GHZ */ - *tx_rate = 0x99; - *rsv_time = 28; - } else { - *tx_rate = 0x89; - *rsv_time = 34; - } - break; - } -} - -/*--------------------- Export Functions --------------------------*/ - -/* - * Description: Update IFS - * - * Parameters: - * In: - * priv - The adapter to be set - * Out: - * none - * - * Return Value: None. - */ -bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type) -{ - unsigned char cw_max_min = 0; - unsigned char slot = 0; - unsigned char sifs = 0; - unsigned char difs = 0; - int i; - - /* Set SIFS, DIFS, EIFS, SlotTime, CwMin */ - if (bb_type == BB_TYPE_11A) { - vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11A); - bb_write_embedded(priv, 0x88, 0x03); - slot = C_SLOT_SHORT; - sifs = C_SIFS_A; - difs = C_SIFS_A + 2 * C_SLOT_SHORT; - cw_max_min = 0xA4; - } else if (bb_type == BB_TYPE_11B) { - vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11B); - bb_write_embedded(priv, 0x88, 0x02); - slot = C_SLOT_LONG; - sifs = C_SIFS_BG; - difs = C_SIFS_BG + 2 * C_SLOT_LONG; - cw_max_min = 0xA5; - } else { /* PK_TYPE_11GA & PK_TYPE_11GB */ - vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11G); - bb_write_embedded(priv, 0x88, 0x08); - sifs = C_SIFS_BG; - - if (priv->short_slot_time) { - slot = C_SLOT_SHORT; - difs = C_SIFS_BG + 2 * C_SLOT_SHORT; - } else { - slot = C_SLOT_LONG; - difs = C_SIFS_BG + 2 * C_SLOT_LONG; - } - - cw_max_min = 0xa4; - - for (i = RATE_54M; i >= RATE_6M; i--) { - if (priv->basic_rates & ((u32)(0x1 << i))) { - cw_max_min |= 0x1; - break; - } - } - } - - if (priv->rf_type == RF_RFMD2959) { - /* - * bcs TX_PE will reserve 3 us hardware's processing - * time here is 2 us. - */ - sifs -= 3; - difs -= 3; - /* - * TX_PE will reserve 3 us for MAX2829 A mode only, it is for - * better TX throughput; MAC will need 2 us to process, so the - * SIFS, DIFS can be shorter by 2 us. - */ - } - - if (priv->sifs != sifs) { - priv->sifs = sifs; - iowrite8(priv->sifs, priv->port_offset + MAC_REG_SIFS); - } - if (priv->difs != difs) { - priv->difs = difs; - iowrite8(priv->difs, priv->port_offset + MAC_REG_DIFS); - } - if (priv->eifs != C_EIFS) { - priv->eifs = C_EIFS; - iowrite8(priv->eifs, priv->port_offset + MAC_REG_EIFS); - } - if (priv->slot != slot) { - priv->slot = slot; - iowrite8(priv->slot, priv->port_offset + MAC_REG_SLOT); - - bb_set_short_slot_time(priv); - } - if (priv->cw_max_min != cw_max_min) { - priv->cw_max_min = cw_max_min; - iowrite8(priv->cw_max_min, priv->port_offset + MAC_REG_CWMAXMIN0); - } - - priv->packet_type = card_get_pkt_type(priv); - - card_set_rspinf(priv, bb_type); - - return true; -} - -/* - * Description: Sync. TSF counter to BSS - * Get TSF offset and write to HW - * - * Parameters: - * In: - * priv - The adapter to be sync. - * rx_rate - data rate of receive beacon - * bss_timestamp - Rx BCN's TSF - * qwLocalTSF - Local TSF - * Out: - * none - * - * Return Value: none - */ -bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate, - u64 bss_timestamp) -{ - u64 local_tsf; - u64 tsf_offset = 0; - - local_tsf = vt6655_get_current_tsf(priv); - - if (bss_timestamp != local_tsf) { - tsf_offset = card_get_tsf_offset(rx_rate, bss_timestamp, - local_tsf); - /* adjust TSF, HW's TSF add TSF Offset reg */ - tsf_offset = le64_to_cpu(tsf_offset); - iowrite32((u32)tsf_offset, priv->port_offset + MAC_REG_TSFOFST); - iowrite32((u32)(tsf_offset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4); - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN); - } - return true; -} - -/* - * Description: Set NIC TSF counter for first Beacon time - * Get NEXTTBTT from adjusted TSF and Beacon Interval - * - * Parameters: - * In: - * priv - The adapter to be set. - * beacon_interval - Beacon Interval - * Out: - * none - * - * Return Value: true if succeed; otherwise false - */ -bool card_set_beacon_period(struct vnt_private *priv, - unsigned short beacon_interval) -{ - u64 next_tbtt; - - next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */ - - next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval); - - /* set HW beacon interval */ - iowrite16(beacon_interval, priv->port_offset + MAC_REG_BI); - priv->beacon_interval = beacon_interval; - /* Set NextTBTT */ - next_tbtt = le64_to_cpu(next_tbtt); - iowrite32((u32)next_tbtt, priv->port_offset + MAC_REG_NEXTTBTT); - iowrite32((u32)(next_tbtt >> 32), priv->port_offset + MAC_REG_NEXTTBTT + 4); - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); - - return true; -} - -/* - * Description: Turn off Radio power - * - * Parameters: - * In: - * priv - The adapter to be turned off - * Out: - * none - * - */ -void card_radio_power_off(struct vnt_private *priv) -{ - if (priv->radio_off) - return; - - switch (priv->rf_type) { - case RF_RFMD2959: - vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, - SOFTPWRCTL_TXPEINV); - vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_SOFTPWRCTL, - SOFTPWRCTL_SWPE1); - break; - - case RF_AIROHA: - case RF_AL2230S: - vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, - SOFTPWRCTL_SWPE2); - vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL, - SOFTPWRCTL_SWPE3); - break; - } - - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_RXON); - - bb_set_deep_sleep(priv, priv->local_id); - - priv->radio_off = true; - pr_debug("chester power off\n"); - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */ -} - -void card_safe_reset_tx(struct vnt_private *priv) -{ - unsigned int uu; - struct vnt_tx_desc *curr_td; - - /* initialize TD index */ - priv->tail_td[0] = &priv->ap_td0_rings[0]; - priv->apCurrTD[0] = &priv->ap_td0_rings[0]; - - priv->tail_td[1] = &priv->ap_td1_rings[0]; - priv->apCurrTD[1] = &priv->ap_td1_rings[0]; - - for (uu = 0; uu < TYPE_MAXTD; uu++) - priv->iTDUsed[uu] = 0; - - for (uu = 0; uu < priv->opts.tx_descs[0]; uu++) { - curr_td = &priv->ap_td0_rings[uu]; - curr_td->td0.owner = OWNED_BY_HOST; - /* init all Tx Packet pointer to NULL */ - } - for (uu = 0; uu < priv->opts.tx_descs[1]; uu++) { - curr_td = &priv->ap_td1_rings[uu]; - curr_td->td0.owner = OWNED_BY_HOST; - /* init all Tx Packet pointer to NULL */ - } - - /* set MAC TD pointer */ - vt6655_mac_set_curr_tx_desc_addr(TYPE_TXDMA0, priv, priv->td0_pool_dma); - - vt6655_mac_set_curr_tx_desc_addr(TYPE_AC0DMA, priv, priv->td1_pool_dma); - - /* set MAC Beacon TX pointer */ - iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR); -} - -/* - * Description: - * Reset Rx - * - * Parameters: - * In: - * priv - Pointer to the adapter - * Out: - * none - * - * Return Value: none - */ -void CARDvSafeResetRx(struct vnt_private *priv) -{ - unsigned int uu; - struct vnt_rx_desc *pDesc; - - /* initialize RD index */ - priv->pCurrRD[0] = &priv->aRD0Ring[0]; - priv->pCurrRD[1] = &priv->aRD1Ring[0]; - - /* init state, all RD is chip's */ - for (uu = 0; uu < priv->opts.rx_descs0; uu++) { - pDesc = &priv->aRD0Ring[uu]; - pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); - pDesc->rd0.owner = OWNED_BY_NIC; - pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); - } - - /* init state, all RD is chip's */ - for (uu = 0; uu < priv->opts.rx_descs1; uu++) { - pDesc = &priv->aRD1Ring[uu]; - pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); - pDesc->rd0.owner = OWNED_BY_NIC; - pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); - } - - /* set perPkt mode */ - iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL0); - iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL1); - /* set MAC RD pointer */ - vt6655_mac_set_curr_rx_0_desc_addr(priv, priv->rd0_pool_dma); - - vt6655_mac_set_curr_rx_1_desc_addr(priv, priv->rd1_pool_dma); -} - -/* - * Description: Get response Control frame rate in CCK mode - * - * Parameters: - * In: - * priv - The adapter to be set - * wRateIdx - Receiving data rate - * Out: - * none - * - * Return Value: response Control frame rate - */ -static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv, - unsigned short wRateIdx) -{ - unsigned int ui = (unsigned int)wRateIdx; - - while (ui > RATE_1M) { - if (priv->basic_rates & ((u32)0x1 << ui)) - return (unsigned short)ui; - - ui--; - } - return (unsigned short)RATE_1M; -} - -/* - * Description: Get response Control frame rate in OFDM mode - * - * Parameters: - * In: - * priv - The adapter to be set - * wRateIdx - Receiving data rate - * Out: - * none - * - * Return Value: response Control frame rate - */ -static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv, - unsigned short wRateIdx) -{ - unsigned int ui = (unsigned int)wRateIdx; - - pr_debug("BASIC RATE: %X\n", priv->basic_rates); - - if (!CARDbIsOFDMinBasicRate((void *)priv)) { - pr_debug("%s:(NO OFDM) %d\n", __func__, wRateIdx); - if (wRateIdx > RATE_24M) - wRateIdx = RATE_24M; - return wRateIdx; - } - while (ui > RATE_11M) { - if (priv->basic_rates & ((u32)0x1 << ui)) { - pr_debug("%s : %d\n", __func__, ui); - return (unsigned short)ui; - } - ui--; - } - pr_debug("%s: 6M\n", __func__); - return (unsigned short)RATE_24M; -} - -/* - * Description: Set RSPINF - * - * Parameters: - * In: - * priv - The adapter to be set - * Out: - * none - * - * Return Value: None. - */ -void card_set_rspinf(struct vnt_private *priv, u8 bb_type) -{ - union vnt_phy_field_swap phy; - unsigned char byTxRate, byRsvTime; /* For OFDM */ - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - /* Set to Page1 */ - VT6655_MAC_SELECT_PAGE1(priv->port_offset); - - /* RSPINF_b_1 */ - vnt_get_phy_field(priv, 14, - CARDwGetCCKControlRate(priv, RATE_1M), - PK_TYPE_11B, &phy.field_read); - - /* swap over to get correct write order */ - swap(phy.swap[0], phy.swap[1]); - - iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_1); - - /* RSPINF_b_2 */ - vnt_get_phy_field(priv, 14, - CARDwGetCCKControlRate(priv, RATE_2M), - PK_TYPE_11B, &phy.field_read); - - swap(phy.swap[0], phy.swap[1]); - - iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_2); - - /* RSPINF_b_5 */ - vnt_get_phy_field(priv, 14, - CARDwGetCCKControlRate(priv, RATE_5M), - PK_TYPE_11B, &phy.field_read); - - swap(phy.swap[0], phy.swap[1]); - - iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_5); - - /* RSPINF_b_11 */ - vnt_get_phy_field(priv, 14, - CARDwGetCCKControlRate(priv, RATE_11M), - PK_TYPE_11B, &phy.field_read); - - swap(phy.swap[0], phy.swap[1]); - - iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_11); - - /* RSPINF_a_6 */ - calculate_ofdmr_parameter(RATE_6M, - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_6); - /* RSPINF_a_9 */ - calculate_ofdmr_parameter(RATE_9M, - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_9); - /* RSPINF_a_12 */ - calculate_ofdmr_parameter(RATE_12M, - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_12); - /* RSPINF_a_18 */ - calculate_ofdmr_parameter(RATE_18M, - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_18); - /* RSPINF_a_24 */ - calculate_ofdmr_parameter(RATE_24M, - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_24); - /* RSPINF_a_36 */ - calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, - RATE_36M), - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_36); - /* RSPINF_a_48 */ - calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, - RATE_48M), - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_48); - /* RSPINF_a_54 */ - calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, - RATE_54M), - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_54); - /* RSPINF_a_72 */ - calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv, - RATE_54M), - bb_type, - &byTxRate, - &byRsvTime); - iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_72); - /* Set to Page0 */ - VT6655_MAC_SELECT_PAGE0(priv->port_offset); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -void CARDvUpdateBasicTopRate(struct vnt_private *priv) -{ - unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M; - unsigned char ii; - - /* Determines the highest basic rate. */ - for (ii = RATE_54M; ii >= RATE_6M; ii--) { - if ((priv->basic_rates) & ((u32)(1 << ii))) { - byTopOFDM = ii; - break; - } - } - priv->byTopOFDMBasicRate = byTopOFDM; - - for (ii = RATE_11M;; ii--) { - if ((priv->basic_rates) & ((u32)(1 << ii))) { - byTopCCK = ii; - break; - } - if (ii == RATE_1M) - break; - } - priv->byTopCCKBasicRate = byTopCCK; -} - -bool CARDbIsOFDMinBasicRate(struct vnt_private *priv) -{ - int ii; - - for (ii = RATE_54M; ii >= RATE_6M; ii--) { - if ((priv->basic_rates) & ((u32)BIT(ii))) - return true; - } - return false; -} - -unsigned char card_get_pkt_type(struct vnt_private *priv) -{ - if (priv->byBBType == BB_TYPE_11A || priv->byBBType == BB_TYPE_11B) - return (unsigned char)priv->byBBType; - else if (CARDbIsOFDMinBasicRate((void *)priv)) - return PK_TYPE_11GA; - else - return PK_TYPE_11GB; -} - -/* - * Description: Calculate TSF offset of two TSF input - * Get TSF Offset from RxBCN's TSF and local TSF - * - * Parameters: - * In: - * priv - The adapter to be sync. - * qwTSF1 - Rx BCN's TSF - * qwTSF2 - Local TSF - * Out: - * none - * - * Return Value: TSF Offset value - */ -u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2) -{ - unsigned short wRxBcnTSFOffst; - - wRxBcnTSFOffst = rx_bcn_tsf_off[rx_rate % MAX_RATE]; - - qwTSF2 += (u64)wRxBcnTSFOffst; - - return qwTSF1 - qwTSF2; -} - -/* - * Description: Read NIC TSF counter - * Get local TSF counter - * - * Parameters: - * In: - * priv - The adapter to be read - * Out: - * none - * - * Return Value: Current TSF counter - */ -u64 vt6655_get_current_tsf(struct vnt_private *priv) -{ - void __iomem *iobase = priv->port_offset; - unsigned short ww; - unsigned char data; - u32 low, high; - - vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD); - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - data = ioread8(iobase + MAC_REG_TFTCTL); - if (!(data & TFTCTL_TSFCNTRRD)) - break; - } - if (ww == W_MAX_TIMEOUT) - return 0; - low = ioread32(iobase + MAC_REG_TSFCNTR); - high = ioread32(iobase + MAC_REG_TSFCNTR + 4); - return le64_to_cpu(low + ((u64)high << 32)); -} - -/* - * Description: Read NIC TSF counter - * Get NEXTTBTT from adjusted TSF and Beacon Interval - * - * Parameters: - * In: - * qwTSF - Current TSF counter - * wbeaconInterval - Beacon Interval - * Out: - * qwCurrTSF - Current TSF counter - * - * Return Value: TSF value of next Beacon - */ -u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval) -{ - u32 beacon_int; - - beacon_int = beacon_interval * 1024; - if (beacon_int) { - do_div(qwTSF, beacon_int); - qwTSF += 1; - qwTSF *= beacon_int; - } - - return qwTSF; -} - -/* - * Description: Set NIC TSF counter for first Beacon time - * Get NEXTTBTT from adjusted TSF and Beacon Interval - * - * Parameters: - * In: - * iobase - IO Base - * beacon_interval - Beacon Interval - * Out: - * none - * - * Return Value: none - */ -void CARDvSetFirstNextTBTT(struct vnt_private *priv, - unsigned short beacon_interval) -{ - void __iomem *iobase = priv->port_offset; - u64 next_tbtt; - - next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */ - - next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval); - /* Set NextTBTT */ - next_tbtt = le64_to_cpu(next_tbtt); - iowrite32((u32)next_tbtt, iobase + MAC_REG_NEXTTBTT); - iowrite32((u32)(next_tbtt >> 32), iobase + MAC_REG_NEXTTBTT + 4); - vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); -} - -/* - * Description: Sync NIC TSF counter for Beacon time - * Get NEXTTBTT and write to HW - * - * Parameters: - * In: - * priv - The adapter to be set - * qwTSF - Current TSF counter - * beacon_interval - Beacon Interval - * Out: - * none - * - * Return Value: none - */ -void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, - unsigned short beacon_interval) -{ - void __iomem *iobase = priv->port_offset; - - qwTSF = card_get_next_tbtt(qwTSF, beacon_interval); - /* Set NextTBTT */ - qwTSF = le64_to_cpu(qwTSF); - iowrite32((u32)qwTSF, iobase + MAC_REG_NEXTTBTT); - iowrite32((u32)(qwTSF >> 32), iobase + MAC_REG_NEXTTBTT + 4); - vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN); - pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF); -} diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h deleted file mode 100644 index f6b462ebca51cd885e0d528a0d4901aa436d8025..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/card.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Provide functions to setup NIC operation mode - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - */ - -#ifndef __CARD_H__ -#define __CARD_H__ - -#include <linux/types.h> -#include <linux/nl80211.h> - -/* - * Loopback mode - * - * LOBYTE is MAC LB mode, HIBYTE is MII LB mode - */ -#define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, 0) -/* PHY must ISO, avoid MAC loopback packet go out */ -#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0) -#define CARD_LB_PHY MAKEWORD(MAC_LB_EXT, 0) - -#define DEFAULT_MSDU_LIFETIME 512 /* ms */ -#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */ - -#define DEFAULT_MGN_LIFETIME 8 /* ms */ -#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */ - -#define CB_MAX_CHANNEL_24G 14 -#define CB_MAX_CHANNEL_5G 42 -#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G) - -struct vnt_private; - -void card_set_rspinf(struct vnt_private *priv, u8 bb_type); -void CARDvUpdateBasicTopRate(struct vnt_private *priv); -bool CARDbIsOFDMinBasicRate(struct vnt_private *priv); -void CARDvSetFirstNextTBTT(struct vnt_private *priv, - unsigned short beacon_interval); -void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF, - unsigned short beacon_interval); -u64 vt6655_get_current_tsf(struct vnt_private *priv); -u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval); -u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2); -unsigned char card_get_pkt_type(struct vnt_private *priv); -void card_safe_reset_tx(struct vnt_private *priv); -void CARDvSafeResetRx(struct vnt_private *priv); -void card_radio_power_off(struct vnt_private *priv); -bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type); -bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate, - u64 bss_timestamp); -bool card_set_beacon_period(struct vnt_private *priv, - unsigned short beacon_interval); - -#endif /* __CARD_H__ */ diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c deleted file mode 100644 index 771c1364b0f08ef39f2048fef68bf9ef79f5456f..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/channel.c +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - */ - -#include "baseband.h" -#include "channel.h" -#include "device.h" -#include "rf.h" - -static struct ieee80211_rate vnt_rates_bg[] = { - { .bitrate = 10, .hw_value = RATE_1M }, - { .bitrate = 20, .hw_value = RATE_2M }, - { .bitrate = 55, .hw_value = RATE_5M }, - { .bitrate = 110, .hw_value = RATE_11M }, - { .bitrate = 60, .hw_value = RATE_6M }, - { .bitrate = 90, .hw_value = RATE_9M }, - { .bitrate = 120, .hw_value = RATE_12M }, - { .bitrate = 180, .hw_value = RATE_18M }, - { .bitrate = 240, .hw_value = RATE_24M }, - { .bitrate = 360, .hw_value = RATE_36M }, - { .bitrate = 480, .hw_value = RATE_48M }, - { .bitrate = 540, .hw_value = RATE_54M }, -}; - -static struct ieee80211_channel vnt_channels_2ghz[] = { - { .center_freq = 2412, .hw_value = 1 }, - { .center_freq = 2417, .hw_value = 2 }, - { .center_freq = 2422, .hw_value = 3 }, - { .center_freq = 2427, .hw_value = 4 }, - { .center_freq = 2432, .hw_value = 5 }, - { .center_freq = 2437, .hw_value = 6 }, - { .center_freq = 2442, .hw_value = 7 }, - { .center_freq = 2447, .hw_value = 8 }, - { .center_freq = 2452, .hw_value = 9 }, - { .center_freq = 2457, .hw_value = 10 }, - { .center_freq = 2462, .hw_value = 11 }, - { .center_freq = 2467, .hw_value = 12 }, - { .center_freq = 2472, .hw_value = 13 }, - { .center_freq = 2484, .hw_value = 14 } -}; - -static struct ieee80211_supported_band vnt_supported_2ghz_band = { - .channels = vnt_channels_2ghz, - .n_channels = ARRAY_SIZE(vnt_channels_2ghz), - .bitrates = vnt_rates_bg, - .n_bitrates = ARRAY_SIZE(vnt_rates_bg), -}; - -static void vnt_init_band(struct vnt_private *priv, - struct ieee80211_supported_band *supported_band, - enum nl80211_band band) -{ - int i; - - for (i = 0; i < supported_band->n_channels; i++) { - supported_band->channels[i].max_power = 0x3f; - supported_band->channels[i].flags = - IEEE80211_CHAN_NO_HT40; - } - - priv->hw->wiphy->bands[band] = supported_band; -} - -void vnt_init_bands(struct vnt_private *priv) -{ - vnt_init_band(priv, &vnt_supported_2ghz_band, NL80211_BAND_2GHZ); -} - -/** - * set_channel() - Set NIC media channel - * - * @priv: The adapter to be set - * @ch: Channel to be set - * - * Return Value: true if succeeded; false if failed. - * - */ -bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) -{ - bool ret = true; - - if (priv->current_ch == ch->hw_value) - return ret; - - /* Set VGA to max sensitivity */ - if (priv->update_bbvga && - priv->bbvga_current != priv->bbvga[0]) { - priv->bbvga_current = priv->bbvga[0]; - - bb_set_vga_gain_offset(priv, priv->bbvga_current); - } - - /* clear NAV */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_MACCR, MACCR_CLRNAV); - - /* TX_PE will reserve 3 us for MAX2829 A mode only, - * it is for better TX throughput - */ - - priv->current_ch = ch->hw_value; - ret &= RFbSelectChannel(priv, priv->rf_type, - ch->hw_value); - - /* Init Synthesizer Table */ - if (priv->bEnablePSMode) - rf_write_wake_prog_syn(priv, priv->rf_type, ch->hw_value); - - bb_software_reset(priv); - - if (priv->local_id > REV_ID_VT3253_B1) { - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - /* set HW default power register */ - VT6655_MAC_SELECT_PAGE1(priv->port_offset); - RFbSetPower(priv, RATE_1M, priv->current_ch); - iowrite8(priv->cur_pwr, priv->port_offset + MAC_REG_PWRCCK); - RFbSetPower(priv, RATE_6M, priv->current_ch); - iowrite8(priv->cur_pwr, priv->port_offset + MAC_REG_PWROFDM); - VT6655_MAC_SELECT_PAGE0(priv->port_offset); - - spin_unlock_irqrestore(&priv->lock, flags); - } - - if (priv->byBBType == BB_TYPE_11B) - RFbSetPower(priv, RATE_1M, priv->current_ch); - else - RFbSetPower(priv, RATE_6M, priv->current_ch); - - return ret; -} diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h deleted file mode 100644 index 78b2d82317e52dd18d807ea8f732d66ffb2de682..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/channel.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - */ - -#ifndef _CHANNEL_H_ -#define _CHANNEL_H_ - -#include "card.h" - -void vnt_init_bands(struct vnt_private *priv); - -bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch); - -#endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h deleted file mode 100644 index 17a40c53b8ffd0c336990d9a9b3c6890148352ec..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/desc.h +++ /dev/null @@ -1,249 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose:The header file of descriptor - * - * Revision History: - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - */ - -#ifndef __DESC_H__ -#define __DESC_H__ - -#include <linux/types.h> -#include <linux/mm.h> -#include "linux/ieee80211.h" - -#define B_OWNED_BY_CHIP 1 -#define B_OWNED_BY_HOST 0 - -/* Bits in the RSR register */ -#define RSR_ADDRBROAD 0x80 -#define RSR_ADDRMULTI 0x40 -#define RSR_ADDRUNI 0x00 -#define RSR_IVLDTYP 0x20 -#define RSR_IVLDLEN 0x10 /* invalid len (> 2312 byte) */ -#define RSR_BSSIDOK 0x08 -#define RSR_CRCOK 0x04 -#define RSR_BCNSSIDOK 0x02 -#define RSR_ADDROK 0x01 - -/* Bits in the new RSR register */ -#define NEWRSR_DECRYPTOK 0x10 -#define NEWRSR_CFPIND 0x08 -#define NEWRSR_HWUTSF 0x04 -#define NEWRSR_BCNHITAID 0x02 -#define NEWRSR_BCNHITAID0 0x01 - -/* Bits in the TSR0 register */ -#define TSR0_PWRSTS1_2 0xC0 -#define TSR0_PWRSTS7 0x20 -#define TSR0_NCR 0x1F - -/* Bits in the TSR1 register */ -#define TSR1_TERR 0x80 -#define TSR1_PWRSTS4_6 0x70 -#define TSR1_RETRYTMO 0x08 -#define TSR1_TMO 0x04 -#define TSR1_PWRSTS3 0x02 -#define ACK_DATA 0x01 - -/* Bits in the TCR register */ -#define EDMSDU 0x04 /* end of sdu */ -#define TCR_EDP 0x02 /* end of packet */ -#define TCR_STP 0x01 /* start of packet */ - -/* max transmit or receive buffer size */ -#define CB_MAX_BUF_SIZE 2900U - /* NOTE: must be multiple of 4 */ -#define CB_MAX_TX_BUF_SIZE CB_MAX_BUF_SIZE -#define CB_MAX_RX_BUF_SIZE_NORMAL CB_MAX_BUF_SIZE - -#define CB_BEACON_BUF_SIZE 512U - -#define CB_MAX_RX_DESC 128 -#define CB_MIN_RX_DESC 16 -#define CB_MAX_TX_DESC 64 -#define CB_MIN_TX_DESC 16 - -#define CB_MAX_RECEIVED_PACKETS 16 - /* - * limit our receive routine to indicating - * this many at a time for 2 reasons: - * 1. driver flow control to protocol layer - * 2. limit the time used in ISR routine - */ - -#define CB_EXTRA_RD_NUM 32 -#define CB_RD_NUM 32 -#define CB_TD_NUM 32 - -/* - * max number of physical segments in a single NDIS packet. Above this - * threshold, the packet is copied into a single physically contiguous buffer - */ -#define CB_MAX_SEGMENT 4 - -#define CB_MIN_MAP_REG_NUM 4 -#define CB_MAX_MAP_REG_NUM CB_MAX_TX_DESC - -#define CB_PROTOCOL_RESERVED_SECTION 16 - -/* - * if retrys excess 15 times , tx will abort, and if tx fifo underflow, - * tx will fail, we should try to resend it - */ -#define CB_MAX_TX_ABORT_RETRY 3 - -/* WMAC definition FIFO Control */ -#define FIFOCTL_AUTO_FB_1 0x1000 -#define FIFOCTL_AUTO_FB_0 0x0800 -#define FIFOCTL_GRPACK 0x0400 -#define FIFOCTL_11GA 0x0300 -#define FIFOCTL_11GB 0x0200 -#define FIFOCTL_11B 0x0100 -#define FIFOCTL_11A 0x0000 -#define FIFOCTL_RTS 0x0080 -#define FIFOCTL_ISDMA0 0x0040 -#define FIFOCTL_GENINT 0x0020 -#define FIFOCTL_TMOEN 0x0010 -#define FIFOCTL_LRETRY 0x0008 -#define FIFOCTL_CRCDIS 0x0004 -#define FIFOCTL_NEEDACK 0x0002 -#define FIFOCTL_LHEAD 0x0001 - -/* WMAC definition Frag Control */ -#define FRAGCTL_AES 0x0300 -#define FRAGCTL_TKIP 0x0200 -#define FRAGCTL_LEGACY 0x0100 -#define FRAGCTL_NONENCRYPT 0x0000 -#define FRAGCTL_ENDFRAG 0x0003 -#define FRAGCTL_MIDFRAG 0x0002 -#define FRAGCTL_STAFRAG 0x0001 -#define FRAGCTL_NONFRAG 0x0000 - -#define TYPE_TXDMA0 0 -#define TYPE_AC0DMA 1 -#define TYPE_ATIMDMA 2 -#define TYPE_SYNCDMA 3 -#define TYPE_MAXTD 2 - -#define TYPE_BEACONDMA 4 - -#define TYPE_RXDMA0 0 -#define TYPE_RXDMA1 1 -#define TYPE_MAXRD 2 - -/* TD_INFO flags control bit */ -#define TD_FLAGS_NETIF_SKB 0x01 /* check if need release skb */ -/* check if called from private skb (hostap) */ -#define TD_FLAGS_PRIV_SKB 0x02 -#define TD_FLAGS_PS_RETRY 0x04 /* check if PS STA frame re-transmit */ - -/* - * ref_sk_buff is used for mapping the skb structure between pre-built - * driver-obj & running kernel. Since different kernel version (2.4x) may - * change skb structure, i.e. pre-built driver-obj may link to older skb that - * leads error. - */ - -struct vnt_rd_info { - struct sk_buff *skb; - dma_addr_t skb_dma; -}; - -struct vnt_rdes0 { - volatile __le16 res_count; -#ifdef __BIG_ENDIAN - union { - volatile u16 f15_reserved; - struct { - volatile u8 f8_reserved1; - volatile u8 owner:1; - volatile u8 f7_reserved:7; - } __packed; - } __packed; -#else - u16 f15_reserved:15; - u16 owner:1; -#endif -} __packed; - -struct vnt_rdes1 { - __le16 req_count; - u16 reserved; -} __packed; - -/* Rx descriptor*/ -struct vnt_rx_desc { - volatile struct vnt_rdes0 rd0; - volatile struct vnt_rdes1 rd1; - volatile __le32 buff_addr; - volatile __le32 next_desc; - struct vnt_rx_desc *next __aligned(8); - struct vnt_rd_info *rd_info __aligned(8); -} __packed; - -struct vnt_tdes0 { - volatile u8 tsr0; - volatile u8 tsr1; -#ifdef __BIG_ENDIAN - union { - volatile u16 f15_txtime; - struct { - volatile u8 f8_reserved; - volatile u8 owner:1; - volatile u8 f7_reserved:7; - } __packed; - } __packed; -#else - volatile u16 f15_txtime:15; - volatile u16 owner:1; -#endif -} __packed; - -struct vnt_tdes1 { - volatile __le16 req_count; - volatile u8 tcr; - volatile u8 reserved; -} __packed; - -struct vnt_td_info { - void *mic_hdr; - struct sk_buff *skb; - unsigned char *buf; - dma_addr_t buf_dma; - u16 req_count; - u8 flags; -}; - -/* transmit descriptor */ -struct vnt_tx_desc { - volatile struct vnt_tdes0 td0; - volatile struct vnt_tdes1 td1; - volatile __le32 buff_addr; - volatile __le32 next_desc; - struct vnt_tx_desc *next __aligned(8); - struct vnt_td_info *td_info __aligned(8); -} __packed; - -/* Length, Service, and Signal fields of Phy for Tx */ -struct vnt_phy_field { - u8 signal; - u8 service; - __le16 len; -} __packed; - -union vnt_phy_field_swap { - struct vnt_phy_field field_read; - u16 swap[2]; - u32 field_write; -}; - -#endif /* __DESC_H__ */ diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h deleted file mode 100644 index 5eaab6b172d370966d089db3b8a8eb3014f2a469..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/device.h +++ /dev/null @@ -1,292 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: MAC Data structure - * - * Author: Tevin Chen - * - * Date: Mar 17, 1997 - * - */ - -#ifndef __DEVICE_H__ -#define __DEVICE_H__ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/interrupt.h> -#include <linux/crc32.h> -#include <net/mac80211.h> - -/* device specific */ - -#include "device_cfg.h" -#include "card.h" -#include "srom.h" -#include "desc.h" -#include "key.h" -#include "mac.h" - -/*--------------------- Export Definitions -------------------------*/ - -#define RATE_1M 0 -#define RATE_2M 1 -#define RATE_5M 2 -#define RATE_11M 3 -#define RATE_6M 4 -#define RATE_9M 5 -#define RATE_12M 6 -#define RATE_18M 7 -#define RATE_24M 8 -#define RATE_36M 9 -#define RATE_48M 10 -#define RATE_54M 11 -#define MAX_RATE 12 - -#define AUTO_FB_NONE 0 -#define AUTO_FB_0 1 -#define AUTO_FB_1 2 - -#define FB_RATE0 0 -#define FB_RATE1 1 - -/* Antenna Mode */ -#define ANT_A 0 -#define ANT_B 1 -#define ANT_DIVERSITY 2 -#define ANT_RXD_TXA 3 -#define ANT_RXD_TXB 4 -#define ANT_UNKNOWN 0xFF - -#define BB_VGA_LEVEL 4 -#define BB_VGA_CHANGE_THRESHOLD 16 - -#define MAKE_BEACON_RESERVED 10 /* (us) */ - -/* BUILD OBJ mode */ - -#define AVAIL_TD(p, q) ((p)->opts.tx_descs[(q)] - ((p)->iTDUsed[(q)])) - -/* 0:11A 1:11B 2:11G */ -#define BB_TYPE_11A 0 -#define BB_TYPE_11B 1 -#define BB_TYPE_11G 2 - -/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */ -#define PK_TYPE_11A 0 -#define PK_TYPE_11B 1 -#define PK_TYPE_11GB 2 -#define PK_TYPE_11GA 3 - -#define OWNED_BY_HOST 0 -#define OWNED_BY_NIC 1 - -struct vnt_options { - int rx_descs0; /* Number of RX descriptors0 */ - int rx_descs1; /* Number of RX descriptors1 */ - int tx_descs[2]; /* Number of TX descriptors 0, 1 */ - int int_works; /* interrupt limits */ - int short_retry; - int long_retry; - int bbp_type; - u32 flags; -}; - -struct vnt_private { - struct pci_dev *pcid; - /* mac80211 */ - struct ieee80211_hw *hw; - struct ieee80211_vif *vif; - unsigned long key_entry_inuse; - u32 basic_rates; - u16 current_aid; - int mc_list_count; - u8 mac_hw; - -/* dma addr, rx/tx pool */ - dma_addr_t pool_dma; - dma_addr_t rd0_pool_dma; - dma_addr_t rd1_pool_dma; - - dma_addr_t td0_pool_dma; - dma_addr_t td1_pool_dma; - - dma_addr_t tx_bufs_dma0; - dma_addr_t tx_bufs_dma1; - dma_addr_t tx_beacon_dma; - - unsigned char *tx0_bufs; - unsigned char *tx1_bufs; - unsigned char *tx_beacon_bufs; - - void __iomem *port_offset; - u32 memaddr; - u32 ioaddr; - - spinlock_t lock; - - volatile int iTDUsed[TYPE_MAXTD]; - - struct vnt_tx_desc *apCurrTD[TYPE_MAXTD]; - struct vnt_tx_desc *tail_td[TYPE_MAXTD]; - - struct vnt_tx_desc *ap_td0_rings; - struct vnt_tx_desc *ap_td1_rings; - - struct vnt_rx_desc *aRD0Ring; - struct vnt_rx_desc *aRD1Ring; - struct vnt_rx_desc *pCurrRD[TYPE_MAXRD]; - - struct vnt_options opts; - - u32 flags; - - u32 rx_buf_sz; - u8 rx_rate; - - u32 rx_bytes; - - /* Version control */ - unsigned char local_id; - unsigned char rf_type; - - unsigned char max_pwr_level; - unsigned char byZoneType; - bool bZoneRegExist; - unsigned char byOriginalZonetype; - - unsigned char abyCurrentNetAddr[ETH_ALEN]; __aligned(2) - bool bLinkPass; /* link status: OK or fail */ - - unsigned int current_rssi; - unsigned char byCurrSQ; - - unsigned long dwTxAntennaSel; - unsigned long dwRxAntennaSel; - unsigned char byAntennaCount; - unsigned char byRxAntennaMode; - unsigned char byTxAntennaMode; - bool bTxRxAntInv; - - unsigned char *pbyTmpBuff; - unsigned int uSIFS; /* Current SIFS */ - unsigned int uDIFS; /* Current DIFS */ - unsigned int uEIFS; /* Current EIFS */ - unsigned int uSlot; /* Current SlotTime */ - unsigned int uCwMin; /* Current CwMin */ - unsigned int uCwMax; /* CwMax is fixed on 1023. */ - /* PHY parameter */ - unsigned char sifs; - unsigned char difs; - unsigned char eifs; - unsigned char slot; - unsigned char cw_max_min; - - u8 byBBType; /* 0:11A, 1:11B, 2:11G */ - u8 packet_type; /* - * 0:11a,1:11b,2:11gb (only CCK - * in BasicRate), 3:11ga (OFDM in - * Basic Rate) - */ - unsigned short wBasicRate; - unsigned char byACKRate; - unsigned char byTopOFDMBasicRate; - unsigned char byTopCCKBasicRate; - - unsigned char byMinChannel; - unsigned char byMaxChannel; - - unsigned char preamble_type; - unsigned char byShortPreamble; - - unsigned short wCurrentRate; - unsigned char byShortRetryLimit; - unsigned char byLongRetryLimit; - enum nl80211_iftype op_mode; - bool bBSSIDFilter; - unsigned short wMaxTransmitMSDULifetime; - - bool bEncryptionEnable; - bool bLongHeader; - bool short_slot_time; - bool bProtectMode; - bool bNonERPPresent; - bool bBarkerPreambleMd; - - bool bRadioControlOff; - bool radio_off; - bool bEnablePSMode; - unsigned short wListenInterval; - bool bPWBitOn; - - /* GPIO Radio Control */ - unsigned char byRadioCtl; - unsigned char byGPIO; - bool hw_radio_off; - bool bPrvActive4RadioOFF; - bool bGPIOBlockRead; - - /* Beacon related */ - unsigned short wSeqCounter; - unsigned short wBCNBufLen; - bool bBeaconBufReady; - bool bBeaconSent; - bool bIsBeaconBufReadySet; - unsigned int cbBeaconBufReadySetCnt; - bool bFixRate; - u16 current_ch; - - bool bAES; - - unsigned char byAutoFBCtrl; - - /* For Update BaseBand VGA Gain Offset */ - bool update_bbvga; - unsigned int uBBVGADiffCount; - unsigned char bbvga_new; - unsigned char bbvga_current; - unsigned char bbvga[BB_VGA_LEVEL]; - long dbm_threshold[BB_VGA_LEVEL]; - - unsigned char bb_pre_edrssi; - unsigned char byBBPreEDIndex; - - unsigned long dwDiagRefCount; - - /* For FOE Tuning */ - unsigned char byFOETuning; - - /* For RF Power table */ - unsigned char byCCKPwr; - unsigned char byOFDMPwrG; - unsigned char cur_pwr; - char byCurPwrdBm; - unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G + 1]; - unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL + 1]; - char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G + 1]; - char abyOFDMDefaultPwr[CB_MAX_CHANNEL + 1]; - char abyRegPwr[CB_MAX_CHANNEL + 1]; - char abyLocalPwr[CB_MAX_CHANNEL + 1]; - - /* BaseBand Loopback Use */ - unsigned char byBBCR4d; - unsigned char byBBCRc9; - unsigned char byBBCR88; - unsigned char byBBCR09; - - unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */ - - unsigned short beacon_interval; - u16 wake_up_count; - - struct work_struct interrupt_work; - - struct ieee80211_low_level_stats low_stats; -}; - -#endif diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h deleted file mode 100644 index 2d647a3619bad19c087314400efae2ca892b739e..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/device_cfg.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Driver configuration header - * Author: Lyndon Chen - * - * Date: Dec 17, 2002 - * - */ - -#ifndef __DEVICE_CONFIG_H -#define __DEVICE_CONFIG_H - -#include <linux/types.h> - -#define VID_TABLE_SIZE 64 -#define MCAST_TABLE_SIZE 64 -#define MCAM_SIZE 32 -#define VCAM_SIZE 32 -#define TX_QUEUE_NO 8 - -#define DEVICE_NAME "vt6655" -#define DEVICE_FULL_DRV_NAM "VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver" - -#ifndef MAJOR_VERSION -#define MAJOR_VERSION 1 -#endif - -#ifndef MINOR_VERSION -#define MINOR_VERSION 17 -#endif - -#ifndef DEVICE_VERSION -#define DEVICE_VERSION "1.19.12" -#endif - -#include <linux/fs.h> -#include <linux/fcntl.h> - -#define PKT_BUF_SZ 2390 - -#endif diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c deleted file mode 100644 index bf3ecf72020666170bfa00c3b6a7ab4d9086350b..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/device_main.c +++ /dev/null @@ -1,1868 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: driver entry for initial, open, close, tx and rx. - * - * Author: Lyndon Chen - * - * Date: Jan 8, 2003 - * - * Functions: - * - * vt6655_probe - module initial (insmod) driver entry - * vt6655_remove - module remove entry - * device_free_info - device structure resource free function - * device_print_info - print out resource - * device_rx_srv - rx service function - * device_alloc_rx_buf - rx buffer pre-allocated function - * device_free_rx_buf - free rx buffer function - * device_free_tx_buf - free tx buffer function - * device_init_rd0_ring - initial rd dma0 ring - * device_init_rd1_ring - initial rd dma1 ring - * device_init_td0_ring - initial tx dma0 ring buffer - * device_init_td1_ring - initial tx dma1 ring buffer - * device_init_registers - initial MAC & BBP & RF internal registers. - * device_init_rings - initial tx/rx ring buffer - * device_free_rings - free all allocated ring buffer - * device_tx_srv - tx interrupt service function - * - * Revision History: - */ - -#include <linux/file.h> -#include "device.h" -#include "card.h" -#include "channel.h" -#include "baseband.h" -#include "mac.h" -#include "power.h" -#include "rxtx.h" -#include "dpc.h" -#include "rf.h" -#include <linux/delay.h> -#include <linux/kthread.h> -#include <linux/slab.h> - -/*--------------------- Static Definitions -------------------------*/ -/* - * Define module options - */ -MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); - -#define DEVICE_PARAM(N, D) - -#define RX_DESC_MIN0 16 -#define RX_DESC_MAX0 128 -#define RX_DESC_DEF0 32 -DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0"); - -#define RX_DESC_MIN1 16 -#define RX_DESC_MAX1 128 -#define RX_DESC_DEF1 32 -DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1"); - -#define TX_DESC_MIN0 16 -#define TX_DESC_MAX0 128 -#define TX_DESC_DEF0 32 -DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0"); - -#define TX_DESC_MIN1 16 -#define TX_DESC_MAX1 128 -#define TX_DESC_DEF1 64 -DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1"); - -#define INT_WORKS_DEF 20 -#define INT_WORKS_MIN 10 -#define INT_WORKS_MAX 64 - -DEVICE_PARAM(int_works, "Number of packets per interrupt services"); - -#define RTS_THRESH_DEF 2347 - -#define FRAG_THRESH_DEF 2346 - -#define SHORT_RETRY_MIN 0 -#define SHORT_RETRY_MAX 31 -#define SHORT_RETRY_DEF 8 - -DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); - -#define LONG_RETRY_MIN 0 -#define LONG_RETRY_MAX 15 -#define LONG_RETRY_DEF 4 - -DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); - -/* BasebandType[] baseband type selected - * 0: indicate 802.11a type - * 1: indicate 802.11b type - * 2: indicate 802.11g type - */ -#define BBP_TYPE_MIN 0 -#define BBP_TYPE_MAX 2 -#define BBP_TYPE_DEF 2 - -DEVICE_PARAM(BasebandType, "baseband type"); - -/* - * Static vars definitions - */ -static const struct pci_device_id vt6655_pci_id_table[] = { - { PCI_VDEVICE(VIA, 0x3253) }, - { 0, } -}; - -/*--------------------- Static Functions --------------------------*/ - -static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); -static void device_free_info(struct vnt_private *priv); -static void device_print_info(struct vnt_private *priv); - -static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr); -static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr); - -static int device_init_rd0_ring(struct vnt_private *priv); -static int device_init_rd1_ring(struct vnt_private *priv); -static int device_init_td0_ring(struct vnt_private *priv); -static int device_init_td1_ring(struct vnt_private *priv); - -static int device_rx_srv(struct vnt_private *priv, unsigned int idx); -static int device_tx_srv(struct vnt_private *priv, unsigned int idx); -static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *); -static void device_free_rx_buf(struct vnt_private *priv, - struct vnt_rx_desc *rd); -static void device_init_registers(struct vnt_private *priv); -static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *); -static void device_free_td0_ring(struct vnt_private *priv); -static void device_free_td1_ring(struct vnt_private *priv); -static void device_free_rd0_ring(struct vnt_private *priv); -static void device_free_rd1_ring(struct vnt_private *priv); -static void device_free_rings(struct vnt_private *priv); - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ - -static void vt6655_remove(struct pci_dev *pcid) -{ - struct vnt_private *priv = pci_get_drvdata(pcid); - - if (!priv) - return; - device_free_info(priv); -} - -static void device_get_options(struct vnt_private *priv) -{ - struct vnt_options *opts = &priv->opts; - - opts->rx_descs0 = RX_DESC_DEF0; - opts->rx_descs1 = RX_DESC_DEF1; - opts->tx_descs[0] = TX_DESC_DEF0; - opts->tx_descs[1] = TX_DESC_DEF1; - opts->int_works = INT_WORKS_DEF; - - opts->short_retry = SHORT_RETRY_DEF; - opts->long_retry = LONG_RETRY_DEF; - opts->bbp_type = BBP_TYPE_DEF; -} - -static void -device_set_options(struct vnt_private *priv) -{ - priv->byShortRetryLimit = priv->opts.short_retry; - priv->byLongRetryLimit = priv->opts.long_retry; - priv->byBBType = priv->opts.bbp_type; - priv->packet_type = priv->byBBType; - priv->byAutoFBCtrl = AUTO_FB_0; - priv->update_bbvga = true; - priv->preamble_type = 0; - - pr_debug(" byShortRetryLimit= %d\n", (int)priv->byShortRetryLimit); - pr_debug(" byLongRetryLimit= %d\n", (int)priv->byLongRetryLimit); - pr_debug(" preamble_type= %d\n", (int)priv->preamble_type); - pr_debug(" byShortPreamble= %d\n", (int)priv->byShortPreamble); - pr_debug(" byBBType= %d\n", (int)priv->byBBType); -} - -static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr) -{ - iowrite8(1, iobase + MAC_REG_PAGE1SEL); - for (int i = 0; i < 6; i++) - iowrite8(mac_addr[i], iobase + MAC_REG_BSSID0 + i); - iowrite8(0, iobase + MAC_REG_PAGE1SEL); -} - -static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr) -{ - iowrite8(1, iobase + MAC_REG_PAGE1SEL); - for (int i = 0; i < 6; i++) - mac_addr[i] = ioread8(iobase + MAC_REG_PAR0 + i); - iowrite8(0, iobase + MAC_REG_PAGE1SEL); -} - -static void vt6655_mac_dma_ctl(void __iomem *iobase, u8 reg_index) -{ - u32 reg_value; - - reg_value = ioread32(iobase + reg_index); - if (reg_value & DMACTL_RUN) - iowrite32(DMACTL_WAKE, iobase + reg_index); - else - iowrite32(DMACTL_RUN, iobase + reg_index); -} - -static void vt6655_mac_set_bits(void __iomem *iobase, u32 mask) -{ - u32 reg_value; - - reg_value = ioread32(iobase + MAC_REG_ENCFG); - reg_value = reg_value | mask; - iowrite32(reg_value, iobase + MAC_REG_ENCFG); -} - -static void vt6655_mac_clear_bits(void __iomem *iobase, u32 mask) -{ - u32 reg_value; - - reg_value = ioread32(iobase + MAC_REG_ENCFG); - reg_value = reg_value & ~mask; - iowrite32(reg_value, iobase + MAC_REG_ENCFG); -} - -static void vt6655_mac_en_protect_md(void __iomem *iobase) -{ - vt6655_mac_set_bits(iobase, ENCFG_PROTECTMD); -} - -static void vt6655_mac_dis_protect_md(void __iomem *iobase) -{ - vt6655_mac_clear_bits(iobase, ENCFG_PROTECTMD); -} - -static void vt6655_mac_en_barker_preamble_md(void __iomem *iobase) -{ - vt6655_mac_set_bits(iobase, ENCFG_BARKERPREAM); -} - -static void vt6655_mac_dis_barker_preamble_md(void __iomem *iobase) -{ - vt6655_mac_clear_bits(iobase, ENCFG_BARKERPREAM); -} - -/* - * Initialisation of MAC & BBP registers - */ - -static void device_init_registers(struct vnt_private *priv) -{ - unsigned long flags; - unsigned int ii; - unsigned char byValue; - unsigned char byCCKPwrdBm = 0; - unsigned char byOFDMPwrdBm = 0; - - MACbShutdown(priv); - bb_software_reset(priv); - - /* Do MACbSoftwareReset in MACvInitialize */ - MACbSoftwareReset(priv); - - priv->bAES = false; - - /* Only used in 11g type, sync with ERP IE */ - priv->bProtectMode = false; - - priv->bNonERPPresent = false; - priv->bBarkerPreambleMd = false; - priv->wCurrentRate = RATE_1M; - priv->byTopOFDMBasicRate = RATE_24M; - priv->byTopCCKBasicRate = RATE_1M; - - /* init MAC */ - MACvInitialize(priv); - - /* Get Local ID */ - priv->local_id = ioread8(priv->port_offset + MAC_REG_LOCALID); - - spin_lock_irqsave(&priv->lock, flags); - - SROMvReadAllContents(priv->port_offset, priv->abyEEPROM); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Get Channel range */ - priv->byMinChannel = 1; - priv->byMaxChannel = CB_MAX_CHANNEL; - - /* Get Antena */ - byValue = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_ANTENNA); - if (byValue & EEP_ANTINV) - priv->bTxRxAntInv = true; - else - priv->bTxRxAntInv = false; - - byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - /* if not set default is All */ - if (byValue == 0) - byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - - if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { - priv->byAntennaCount = 2; - priv->byTxAntennaMode = ANT_B; - priv->dwTxAntennaSel = 1; - priv->dwRxAntennaSel = 1; - - if (priv->bTxRxAntInv) - priv->byRxAntennaMode = ANT_A; - else - priv->byRxAntennaMode = ANT_B; - } else { - priv->byAntennaCount = 1; - priv->dwTxAntennaSel = 0; - priv->dwRxAntennaSel = 0; - - if (byValue & EEP_ANTENNA_AUX) { - priv->byTxAntennaMode = ANT_A; - - if (priv->bTxRxAntInv) - priv->byRxAntennaMode = ANT_B; - else - priv->byRxAntennaMode = ANT_A; - } else { - priv->byTxAntennaMode = ANT_B; - - if (priv->bTxRxAntInv) - priv->byRxAntennaMode = ANT_A; - else - priv->byRxAntennaMode = ANT_B; - } - } - - /* Set initial antenna mode */ - bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode); - bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode); - - /* zonetype initial */ - priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE]; - - if (!priv->bZoneRegExist) - priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE]; - - pr_debug("priv->byZoneType = %x\n", priv->byZoneType); - - /* Init RF module */ - RFbInit(priv); - - /* Get Desire Power Value */ - priv->cur_pwr = 0xFF; - priv->byCCKPwr = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_PWR_CCK); - priv->byOFDMPwrG = SROMbyReadEmbedded(priv->port_offset, - EEP_OFS_PWR_OFDMG); - - /* Load power Table */ - for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { - priv->abyCCKPwrTbl[ii + 1] = - SROMbyReadEmbedded(priv->port_offset, - (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL)); - if (priv->abyCCKPwrTbl[ii + 1] == 0) - priv->abyCCKPwrTbl[ii + 1] = priv->byCCKPwr; - - priv->abyOFDMPwrTbl[ii + 1] = - SROMbyReadEmbedded(priv->port_offset, - (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL)); - if (priv->abyOFDMPwrTbl[ii + 1] == 0) - priv->abyOFDMPwrTbl[ii + 1] = priv->byOFDMPwrG; - - priv->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm; - priv->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm; - } - - /* recover 12,13 ,14channel for EUROPE by 11 channel */ - for (ii = 11; ii < 14; ii++) { - priv->abyCCKPwrTbl[ii] = priv->abyCCKPwrTbl[10]; - priv->abyOFDMPwrTbl[ii] = priv->abyOFDMPwrTbl[10]; - } - - /* Load OFDM A Power Table */ - for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { - priv->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = - SROMbyReadEmbedded(priv->port_offset, - (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL)); - - priv->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = - SROMbyReadEmbedded(priv->port_offset, - (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm)); - } - - if (priv->local_id > REV_ID_VT3253_B1) { - VT6655_MAC_SELECT_PAGE1(priv->port_offset); - - iowrite8(MSRCTL1_TXPWR | MSRCTL1_CSAPAREN, priv->port_offset + MAC_REG_MSRCTL + 1); - - VT6655_MAC_SELECT_PAGE0(priv->port_offset); - } - - /* use relative tx timeout and 802.11i D4 */ - vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_CFG, - (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); - - /* set performance parameter by registry */ - vt6655_mac_set_short_retry_limit(priv, priv->byShortRetryLimit); - MACvSetLongRetryLimit(priv, priv->byLongRetryLimit); - - /* reset TSF counter */ - iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); - /* enable TSF counter */ - iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL); - - /* initialize BBP registers */ - bb_vt3253_init(priv); - - if (priv->update_bbvga) { - priv->bbvga_current = priv->bbvga[0]; - priv->bbvga_new = priv->bbvga_current; - bb_set_vga_gain_offset(priv, priv->bbvga[0]); - } - - bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode); - bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode); - - /* Set BB and packet type at the same time. */ - /* Set Short Slot Time, xIFS, and RSPINF. */ - priv->wCurrentRate = RATE_54M; - - priv->radio_off = false; - - priv->byRadioCtl = SROMbyReadEmbedded(priv->port_offset, - EEP_OFS_RADIOCTL); - priv->hw_radio_off = false; - - if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) { - /* Get GPIO */ - priv->byGPIO = ioread8(priv->port_offset + MAC_REG_GPIOCTL1); - - if (((priv->byGPIO & GPIO0_DATA) && - !(priv->byRadioCtl & EEP_RADIOCTL_INV)) || - (!(priv->byGPIO & GPIO0_DATA) && - (priv->byRadioCtl & EEP_RADIOCTL_INV))) - priv->hw_radio_off = true; - } - - if (priv->hw_radio_off || priv->bRadioControlOff) - card_radio_power_off(priv); - - /* get Permanent network address */ - SROMvReadEtherAddress(priv->port_offset, priv->abyCurrentNetAddr); - pr_debug("Network address = %pM\n", priv->abyCurrentNetAddr); - - /* reset Tx pointer */ - CARDvSafeResetRx(priv); - /* reset Rx pointer */ - card_safe_reset_tx(priv); - - if (priv->local_id <= REV_ID_VT3253_A1) - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_RCR, RCR_WPAERR); - - /* Turn On Rx DMA */ - vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0); - vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1); - - /* start the adapter */ - iowrite8(HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON, priv->port_offset + MAC_REG_HOSTCR); -} - -static void device_print_info(struct vnt_private *priv) -{ - dev_info(&priv->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n", - priv->abyCurrentNetAddr, (unsigned long)priv->ioaddr, - (unsigned long)priv->port_offset, priv->pcid->irq); -} - -static void device_free_info(struct vnt_private *priv) -{ - if (!priv) - return; - - if (priv->mac_hw) - ieee80211_unregister_hw(priv->hw); - - if (priv->port_offset) - iounmap(priv->port_offset); - - if (priv->pcid) - pci_release_regions(priv->pcid); - - if (priv->hw) - ieee80211_free_hw(priv->hw); -} - -static bool device_init_rings(struct vnt_private *priv) -{ - void *vir_pool; - - /*allocate all RD/TD rings a single pool*/ - vir_pool = dma_alloc_coherent(&priv->pcid->dev, - priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + - priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + - priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + - priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), - &priv->pool_dma, GFP_ATOMIC); - if (!vir_pool) { - dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n"); - return false; - } - - priv->aRD0Ring = vir_pool; - priv->aRD1Ring = vir_pool + - priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); - - priv->rd0_pool_dma = priv->pool_dma; - priv->rd1_pool_dma = priv->rd0_pool_dma + - priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc); - - priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev, - priv->opts.tx_descs[0] * PKT_BUF_SZ + - priv->opts.tx_descs[1] * PKT_BUF_SZ + - CB_BEACON_BUF_SIZE + - CB_MAX_BUF_SIZE, - &priv->tx_bufs_dma0, GFP_ATOMIC); - if (!priv->tx0_bufs) { - dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n"); - - dma_free_coherent(&priv->pcid->dev, - priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + - priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + - priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + - priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), - vir_pool, priv->pool_dma); - return false; - } - - priv->td0_pool_dma = priv->rd1_pool_dma + - priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc); - - priv->td1_pool_dma = priv->td0_pool_dma + - priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc); - - /* vir_pool: pvoid type */ - priv->ap_td0_rings = vir_pool - + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) - + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc); - - priv->ap_td1_rings = vir_pool - + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) - + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) - + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc); - - priv->tx1_bufs = priv->tx0_bufs + - priv->opts.tx_descs[0] * PKT_BUF_SZ; - - priv->tx_beacon_bufs = priv->tx1_bufs + - priv->opts.tx_descs[1] * PKT_BUF_SZ; - - priv->pbyTmpBuff = priv->tx_beacon_bufs + - CB_BEACON_BUF_SIZE; - - priv->tx_bufs_dma1 = priv->tx_bufs_dma0 + - priv->opts.tx_descs[0] * PKT_BUF_SZ; - - priv->tx_beacon_dma = priv->tx_bufs_dma1 + - priv->opts.tx_descs[1] * PKT_BUF_SZ; - - return true; -} - -static void device_free_rings(struct vnt_private *priv) -{ - dma_free_coherent(&priv->pcid->dev, - priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + - priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + - priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + - priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc), - priv->aRD0Ring, priv->pool_dma); - - dma_free_coherent(&priv->pcid->dev, - priv->opts.tx_descs[0] * PKT_BUF_SZ + - priv->opts.tx_descs[1] * PKT_BUF_SZ + - CB_BEACON_BUF_SIZE + - CB_MAX_BUF_SIZE, - priv->tx0_bufs, priv->tx_bufs_dma0); -} - -static int device_init_rd0_ring(struct vnt_private *priv) -{ - int i; - dma_addr_t curr = priv->rd0_pool_dma; - struct vnt_rx_desc *desc; - int ret; - - /* Init the RD0 ring entries */ - for (i = 0; i < priv->opts.rx_descs0; - i ++, curr += sizeof(struct vnt_rx_desc)) { - desc = &priv->aRD0Ring[i]; - desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); - if (!desc->rd_info) { - ret = -ENOMEM; - goto err_free_desc; - } - - if (!device_alloc_rx_buf(priv, desc)) { - dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); - ret = -ENOMEM; - goto err_free_rd; - } - - desc->next = &priv->aRD0Ring[(i + 1) % priv->opts.rx_descs0]; - desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); - } - - if (i > 0) - priv->aRD0Ring[i - 1].next_desc = cpu_to_le32(priv->rd0_pool_dma); - priv->pCurrRD[0] = &priv->aRD0Ring[0]; - - return 0; - -err_free_rd: - kfree(desc->rd_info); - -err_free_desc: - while (i--) { - desc = &priv->aRD0Ring[i]; - device_free_rx_buf(priv, desc); - kfree(desc->rd_info); - } - - return ret; -} - -static int device_init_rd1_ring(struct vnt_private *priv) -{ - int i; - dma_addr_t curr = priv->rd1_pool_dma; - struct vnt_rx_desc *desc; - int ret; - - /* Init the RD1 ring entries */ - for (i = 0; i < priv->opts.rx_descs1; - i ++, curr += sizeof(struct vnt_rx_desc)) { - desc = &priv->aRD1Ring[i]; - desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); - if (!desc->rd_info) { - ret = -ENOMEM; - goto err_free_desc; - } - - if (!device_alloc_rx_buf(priv, desc)) { - dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); - ret = -ENOMEM; - goto err_free_rd; - } - - desc->next = &priv->aRD1Ring[(i + 1) % priv->opts.rx_descs1]; - desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); - } - - if (i > 0) - priv->aRD1Ring[i - 1].next_desc = cpu_to_le32(priv->rd1_pool_dma); - priv->pCurrRD[1] = &priv->aRD1Ring[0]; - - return 0; - -err_free_rd: - kfree(desc->rd_info); - -err_free_desc: - while (i--) { - desc = &priv->aRD1Ring[i]; - device_free_rx_buf(priv, desc); - kfree(desc->rd_info); - } - - return ret; -} - -static void device_free_rd0_ring(struct vnt_private *priv) -{ - int i; - - for (i = 0; i < priv->opts.rx_descs0; i++) { - struct vnt_rx_desc *desc = &priv->aRD0Ring[i]; - - device_free_rx_buf(priv, desc); - kfree(desc->rd_info); - } -} - -static void device_free_rd1_ring(struct vnt_private *priv) -{ - int i; - - for (i = 0; i < priv->opts.rx_descs1; i++) { - struct vnt_rx_desc *desc = &priv->aRD1Ring[i]; - - device_free_rx_buf(priv, desc); - kfree(desc->rd_info); - } -} - -static int device_init_td0_ring(struct vnt_private *priv) -{ - int i; - dma_addr_t curr; - struct vnt_tx_desc *desc; - int ret; - - curr = priv->td0_pool_dma; - for (i = 0; i < priv->opts.tx_descs[0]; - i++, curr += sizeof(struct vnt_tx_desc)) { - desc = &priv->ap_td0_rings[i]; - desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); - if (!desc->td_info) { - ret = -ENOMEM; - goto err_free_desc; - } - - desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ; - desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ; - - desc->next = &(priv->ap_td0_rings[(i + 1) % priv->opts.tx_descs[0]]); - desc->next_desc = cpu_to_le32(curr + - sizeof(struct vnt_tx_desc)); - } - - if (i > 0) - priv->ap_td0_rings[i - 1].next_desc = cpu_to_le32(priv->td0_pool_dma); - priv->tail_td[0] = priv->apCurrTD[0] = &priv->ap_td0_rings[0]; - - return 0; - -err_free_desc: - while (i--) { - desc = &priv->ap_td0_rings[i]; - kfree(desc->td_info); - } - - return ret; -} - -static int device_init_td1_ring(struct vnt_private *priv) -{ - int i; - dma_addr_t curr; - struct vnt_tx_desc *desc; - int ret; - - /* Init the TD ring entries */ - curr = priv->td1_pool_dma; - for (i = 0; i < priv->opts.tx_descs[1]; - i++, curr += sizeof(struct vnt_tx_desc)) { - desc = &priv->ap_td1_rings[i]; - desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); - if (!desc->td_info) { - ret = -ENOMEM; - goto err_free_desc; - } - - desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ; - desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ; - - desc->next = &(priv->ap_td1_rings[(i + 1) % priv->opts.tx_descs[1]]); - desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc)); - } - - if (i > 0) - priv->ap_td1_rings[i - 1].next_desc = cpu_to_le32(priv->td1_pool_dma); - priv->tail_td[1] = priv->apCurrTD[1] = &priv->ap_td1_rings[0]; - - return 0; - -err_free_desc: - while (i--) { - desc = &priv->ap_td1_rings[i]; - kfree(desc->td_info); - } - - return ret; -} - -static void device_free_td0_ring(struct vnt_private *priv) -{ - int i; - - for (i = 0; i < priv->opts.tx_descs[0]; i++) { - struct vnt_tx_desc *desc = &priv->ap_td0_rings[i]; - struct vnt_td_info *td_info = desc->td_info; - - dev_kfree_skb(td_info->skb); - kfree(desc->td_info); - } -} - -static void device_free_td1_ring(struct vnt_private *priv) -{ - int i; - - for (i = 0; i < priv->opts.tx_descs[1]; i++) { - struct vnt_tx_desc *desc = &priv->ap_td1_rings[i]; - struct vnt_td_info *td_info = desc->td_info; - - dev_kfree_skb(td_info->skb); - kfree(desc->td_info); - } -} - -/*-----------------------------------------------------------------*/ - -static int device_rx_srv(struct vnt_private *priv, unsigned int idx) -{ - struct vnt_rx_desc *rd; - int works = 0; - - for (rd = priv->pCurrRD[idx]; - rd->rd0.owner == OWNED_BY_HOST; - rd = rd->next) { - if (works++ > 15) - break; - - if (!rd->rd_info->skb) - break; - - if (vnt_receive_frame(priv, rd)) { - if (!device_alloc_rx_buf(priv, rd)) { - dev_err(&priv->pcid->dev, - "can not allocate rx buf\n"); - break; - } - } - rd->rd0.owner = OWNED_BY_NIC; - } - - priv->pCurrRD[idx] = rd; - - return works; -} - -static bool device_alloc_rx_buf(struct vnt_private *priv, - struct vnt_rx_desc *rd) -{ - struct vnt_rd_info *rd_info = rd->rd_info; - - rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz); - if (!rd_info->skb) - return false; - - rd_info->skb_dma = - dma_map_single(&priv->pcid->dev, - skb_put(rd_info->skb, skb_tailroom(rd_info->skb)), - priv->rx_buf_sz, DMA_FROM_DEVICE); - if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) { - dev_kfree_skb(rd_info->skb); - rd_info->skb = NULL; - return false; - } - - *((unsigned int *)&rd->rd0) = 0; /* FIX cast */ - - rd->rd0.res_count = cpu_to_le16(priv->rx_buf_sz); - rd->rd0.owner = OWNED_BY_NIC; - rd->rd1.req_count = cpu_to_le16(priv->rx_buf_sz); - rd->buff_addr = cpu_to_le32(rd_info->skb_dma); - - return true; -} - -static void device_free_rx_buf(struct vnt_private *priv, - struct vnt_rx_desc *rd) -{ - struct vnt_rd_info *rd_info = rd->rd_info; - - dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, - priv->rx_buf_sz, DMA_FROM_DEVICE); - dev_kfree_skb(rd_info->skb); -} - -static const u8 fallback_rate0[5][5] = { - {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, - {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, - {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, - {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, - {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} -}; - -static const u8 fallback_rate1[5][5] = { - {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, - {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, - {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, - {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M}, - {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M} -}; - -static int vnt_int_report_rate(struct vnt_private *priv, - struct vnt_td_info *context, u8 tsr0, u8 tsr1) -{ - struct vnt_tx_fifo_head *fifo_head; - struct ieee80211_tx_info *info; - struct ieee80211_rate *rate; - u16 fb_option; - u8 tx_retry = (tsr0 & TSR0_NCR); - s8 idx; - - if (!context) - return -ENOMEM; - - if (!context->skb) - return -EINVAL; - - fifo_head = (struct vnt_tx_fifo_head *)context->buf; - fb_option = (le16_to_cpu(fifo_head->fifo_ctl) & - (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1)); - - info = IEEE80211_SKB_CB(context->skb); - idx = info->control.rates[0].idx; - - if (fb_option && !(tsr1 & TSR1_TERR)) { - u8 tx_rate; - u8 retry = tx_retry; - - rate = ieee80211_get_tx_rate(priv->hw, info); - tx_rate = rate->hw_value - RATE_18M; - - if (retry > 4) - retry = 4; - - if (fb_option & FIFOCTL_AUTO_FB_0) - tx_rate = fallback_rate0[tx_rate][retry]; - else if (fb_option & FIFOCTL_AUTO_FB_1) - tx_rate = fallback_rate1[tx_rate][retry]; - - if (info->band == NL80211_BAND_5GHZ) - idx = tx_rate - RATE_6M; - else - idx = tx_rate; - } - - ieee80211_tx_info_clear_status(info); - - info->status.rates[0].count = tx_retry; - - if (!(tsr1 & TSR1_TERR)) { - info->status.rates[0].idx = idx; - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; - else - info->flags |= IEEE80211_TX_STAT_ACK; - } - - return 0; -} - -static int device_tx_srv(struct vnt_private *priv, unsigned int idx) -{ - struct vnt_tx_desc *desc; - int works = 0; - unsigned char byTsr0; - unsigned char byTsr1; - - for (desc = priv->tail_td[idx]; priv->iTDUsed[idx] > 0; desc = desc->next) { - if (desc->td0.owner == OWNED_BY_NIC) - break; - if (works++ > 15) - break; - - byTsr0 = desc->td0.tsr0; - byTsr1 = desc->td0.tsr1; - - /* Only the status of first TD in the chain is correct */ - if (desc->td1.tcr & TCR_STP) { - if ((desc->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) { - if (!(byTsr1 & TSR1_TERR)) { - if (byTsr0 != 0) { - pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n", - (int)idx, byTsr1, - byTsr0); - } - } else { - pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n", - (int)idx, byTsr1, byTsr0); - } - } - - if (byTsr1 & TSR1_TERR) { - if ((desc->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) { - pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n", - (int)idx, byTsr1, byTsr0); - } - } - - vnt_int_report_rate(priv, desc->td_info, byTsr0, byTsr1); - - device_free_tx_buf(priv, desc); - priv->iTDUsed[idx]--; - } - } - - priv->tail_td[idx] = desc; - - return works; -} - -static void device_error(struct vnt_private *priv, unsigned short status) -{ - if (status & ISR_FETALERR) { - dev_err(&priv->pcid->dev, "Hardware fatal error\n"); - - MACbShutdown(priv); - return; - } -} - -static void device_free_tx_buf(struct vnt_private *priv, - struct vnt_tx_desc *desc) -{ - struct vnt_td_info *td_info = desc->td_info; - struct sk_buff *skb = td_info->skb; - - if (skb) - ieee80211_tx_status_irqsafe(priv->hw, skb); - - td_info->skb = NULL; - td_info->flags = 0; -} - -static void vnt_check_bb_vga(struct vnt_private *priv) -{ - long dbm; - int i; - - if (!priv->update_bbvga) - return; - - if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) - return; - - if (!(priv->vif->cfg.assoc && priv->current_rssi)) - return; - - RFvRSSITodBm(priv, (u8)priv->current_rssi, &dbm); - - for (i = 0; i < BB_VGA_LEVEL; i++) { - if (dbm < priv->dbm_threshold[i]) { - priv->bbvga_new = priv->bbvga[i]; - break; - } - } - - if (priv->bbvga_new == priv->bbvga_current) { - priv->uBBVGADiffCount = 1; - return; - } - - priv->uBBVGADiffCount++; - - if (priv->uBBVGADiffCount == 1) { - /* first VGA diff gain */ - bb_set_vga_gain_offset(priv, priv->bbvga_new); - - dev_dbg(&priv->pcid->dev, - "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)dbm, priv->bbvga_new, - priv->bbvga_current, - (int)priv->uBBVGADiffCount); - } - - if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { - dev_dbg(&priv->pcid->dev, - "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)dbm, priv->bbvga_new, - priv->bbvga_current, - (int)priv->uBBVGADiffCount); - - bb_set_vga_gain_offset(priv, priv->bbvga_new); - } -} - -static void vnt_interrupt_process(struct vnt_private *priv) -{ - struct ieee80211_low_level_stats *low_stats = &priv->low_stats; - int max_count = 0; - u32 mib_counter; - u32 isr; - unsigned long flags; - - isr = ioread32(priv->port_offset + MAC_REG_ISR); - - if (isr == 0) - return; - - if (isr == 0xffffffff) { - pr_debug("isr = 0xffff\n"); - return; - } - - spin_lock_irqsave(&priv->lock, flags); - - /* Read low level stats */ - mib_counter = ioread32(priv->port_offset + MAC_REG_MIBCNTR); - - low_stats->dot11RTSSuccessCount += mib_counter & 0xff; - low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff; - low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff; - low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff; - - /* - * TBD.... - * Must do this after doing rx/tx, cause ISR bit is slow - * than RD/TD write back - * update ISR counter - */ - while (isr && priv->vif) { - iowrite32(isr, priv->port_offset + MAC_REG_ISR); - - if (isr & ISR_FETALERR) { - pr_debug(" ISR_FETALERR\n"); - iowrite8(0, priv->port_offset + MAC_REG_SOFTPWRCTL); - iowrite16(SOFTPWRCTL_SWPECTI, priv->port_offset + MAC_REG_SOFTPWRCTL); - device_error(priv, isr); - } - - if (isr & ISR_TBTT) { - if (priv->op_mode != NL80211_IFTYPE_ADHOC) - vnt_check_bb_vga(priv); - - priv->bBeaconSent = false; - if (priv->bEnablePSMode) - PSbIsNextTBTTWakeUp((void *)priv); - - if ((priv->op_mode == NL80211_IFTYPE_AP || - priv->op_mode == NL80211_IFTYPE_ADHOC) && - priv->vif->bss_conf.enable_beacon) - MACvOneShotTimer1MicroSec(priv, - (priv->vif->bss_conf.beacon_int - - MAKE_BEACON_RESERVED) << 10); - - /* TODO: adhoc PS mode */ - } - - if (isr & ISR_BNTX) { - if (priv->op_mode == NL80211_IFTYPE_ADHOC) { - priv->bIsBeaconBufReadySet = false; - priv->cbBeaconBufReadySetCnt = 0; - } - - priv->bBeaconSent = true; - } - - if (isr & ISR_RXDMA0) - max_count += device_rx_srv(priv, TYPE_RXDMA0); - - if (isr & ISR_RXDMA1) - max_count += device_rx_srv(priv, TYPE_RXDMA1); - - if (isr & ISR_TXDMA0) - max_count += device_tx_srv(priv, TYPE_TXDMA0); - - if (isr & ISR_AC0DMA) - max_count += device_tx_srv(priv, TYPE_AC0DMA); - - if (isr & ISR_SOFTTIMER1) { - if (priv->vif->bss_conf.enable_beacon) - vnt_beacon_make(priv, priv->vif); - } - - /* If both buffers available wake the queue */ - if (AVAIL_TD(priv, TYPE_TXDMA0) && - AVAIL_TD(priv, TYPE_AC0DMA) && - ieee80211_queue_stopped(priv->hw, 0)) - ieee80211_wake_queues(priv->hw); - - isr = ioread32(priv->port_offset + MAC_REG_ISR); - - vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0); - vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1); - - if (max_count > priv->opts.int_works) - break; - } - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void vnt_interrupt_work(struct work_struct *work) -{ - struct vnt_private *priv = - container_of(work, struct vnt_private, interrupt_work); - - if (priv->vif) - vnt_interrupt_process(priv); - - iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR); -} - -static irqreturn_t vnt_interrupt(int irq, void *arg) -{ - struct vnt_private *priv = arg; - - schedule_work(&priv->interrupt_work); - - iowrite32(0, priv->port_offset + MAC_REG_IMR); - - return IRQ_HANDLED; -} - -static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct vnt_tx_desc *head_td; - u32 dma_idx; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - if (ieee80211_is_data(hdr->frame_control)) - dma_idx = TYPE_AC0DMA; - else - dma_idx = TYPE_TXDMA0; - - if (AVAIL_TD(priv, dma_idx) < 1) { - spin_unlock_irqrestore(&priv->lock, flags); - ieee80211_stop_queues(priv->hw); - return -ENOMEM; - } - - head_td = priv->apCurrTD[dma_idx]; - - head_td->td1.tcr = 0; - - head_td->td_info->skb = skb; - - if (dma_idx == TYPE_AC0DMA) - head_td->td_info->flags = TD_FLAGS_NETIF_SKB; - - priv->apCurrTD[dma_idx] = head_td->next; - - spin_unlock_irqrestore(&priv->lock, flags); - - vnt_generate_fifo_header(priv, dma_idx, head_td, skb); - - spin_lock_irqsave(&priv->lock, flags); - - priv->bPWBitOn = false; - - /* Set TSR1 & ReqCount in TxDescHead */ - head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU); - head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count); - - head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma); - - /* Poll Transmit the adapter */ - wmb(); - head_td->td0.owner = OWNED_BY_NIC; - wmb(); /* second memory barrier */ - - if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB) - vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_AC0DMACTL); - else - vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_TXDMACTL0); - - priv->iTDUsed[dma_idx]++; - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static void vnt_tx_80211(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct vnt_private *priv = hw->priv; - - if (vnt_tx_packet(priv, skb)) - ieee80211_free_txskb(hw, skb); -} - -static int vnt_start(struct ieee80211_hw *hw) -{ - struct vnt_private *priv = hw->priv; - int ret; - - priv->rx_buf_sz = PKT_BUF_SZ; - if (!device_init_rings(priv)) - return -ENOMEM; - - ret = request_irq(priv->pcid->irq, vnt_interrupt, - IRQF_SHARED, "vt6655", priv); - if (ret) { - dev_dbg(&priv->pcid->dev, "failed to start irq\n"); - goto err_free_rings; - } - - dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n"); - ret = device_init_rd0_ring(priv); - if (ret) - goto err_free_irq; - ret = device_init_rd1_ring(priv); - if (ret) - goto err_free_rd0_ring; - ret = device_init_td0_ring(priv); - if (ret) - goto err_free_rd1_ring; - ret = device_init_td1_ring(priv); - if (ret) - goto err_free_td0_ring; - - device_init_registers(priv); - - dev_dbg(&priv->pcid->dev, "enable MAC interrupt\n"); - iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR); - - ieee80211_wake_queues(hw); - - return 0; - -err_free_td0_ring: - device_free_td0_ring(priv); -err_free_rd1_ring: - device_free_rd1_ring(priv); -err_free_rd0_ring: - device_free_rd0_ring(priv); -err_free_irq: - free_irq(priv->pcid->irq, priv); -err_free_rings: - device_free_rings(priv); - return ret; -} - -static void vnt_stop(struct ieee80211_hw *hw, bool suspend) -{ - struct vnt_private *priv = hw->priv; - - ieee80211_stop_queues(hw); - - cancel_work_sync(&priv->interrupt_work); - - MACbShutdown(priv); - MACbSoftwareReset(priv); - card_radio_power_off(priv); - - device_free_td0_ring(priv); - device_free_td1_ring(priv); - device_free_rd0_ring(priv); - device_free_rd1_ring(priv); - device_free_rings(priv); - - free_irq(priv->pcid->irq, priv); -} - -static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - priv->vif = vif; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_ADHOC: - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST); - - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC); - - break; - case NL80211_IFTYPE_AP: - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST); - - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP); - - break; - default: - return -EOPNOTSUPP; - } - - priv->op_mode = vif->type; - - return 0; -} - -static void vnt_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_ADHOC: - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); - vt6655_mac_reg_bits_off(priv->port_offset, - MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC); - break; - case NL80211_IFTYPE_AP: - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); - vt6655_mac_reg_bits_off(priv->port_offset, - MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP); - break; - default: - break; - } - - priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; -} - -static int vnt_config(struct ieee80211_hw *hw, u32 changed) -{ - struct vnt_private *priv = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - u8 bb_type; - - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) - PSvEnablePowerSaving(priv, conf->listen_interval); - else - PSvDisablePowerSaving(priv); - } - - if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || - (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { - set_channel(priv, conf->chandef.chan); - - if (conf->chandef.chan->band == NL80211_BAND_5GHZ) - bb_type = BB_TYPE_11A; - else - bb_type = BB_TYPE_11G; - - if (priv->byBBType != bb_type) { - priv->byBBType = bb_type; - - card_set_phy_parameter(priv, priv->byBBType); - } - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - if (priv->byBBType == BB_TYPE_11B) - priv->wCurrentRate = RATE_1M; - else - priv->wCurrentRate = RATE_54M; - - RFbSetPower(priv, priv->wCurrentRate, - conf->chandef.chan->hw_value); - } - - return 0; -} - -static void vnt_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, u64 changed) -{ - struct vnt_private *priv = hw->priv; - - priv->current_aid = vif->cfg.aid; - - if (changed & BSS_CHANGED_BSSID && conf->bssid) { - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - vt6655_mac_write_bssid_addr(priv->port_offset, conf->bssid); - - spin_unlock_irqrestore(&priv->lock, flags); - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - priv->basic_rates = conf->basic_rates; - - CARDvUpdateBasicTopRate(priv); - - dev_dbg(&priv->pcid->dev, - "basic rates %x\n", conf->basic_rates); - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - if (conf->use_short_preamble) { - vt6655_mac_en_barker_preamble_md(priv->port_offset); - priv->preamble_type = true; - } else { - vt6655_mac_dis_barker_preamble_md(priv->port_offset); - priv->preamble_type = false; - } - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - if (conf->use_cts_prot) - vt6655_mac_en_protect_md(priv->port_offset); - else - vt6655_mac_dis_protect_md(priv->port_offset); - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - if (conf->use_short_slot) - priv->short_slot_time = true; - else - priv->short_slot_time = false; - - card_set_phy_parameter(priv, priv->byBBType); - bb_set_vga_gain_offset(priv, priv->bbvga[0]); - } - - if (changed & BSS_CHANGED_TXPOWER) - RFbSetPower(priv, priv->wCurrentRate, - conf->chanreq.oper.chan->hw_value); - - if (changed & BSS_CHANGED_BEACON_ENABLED) { - dev_dbg(&priv->pcid->dev, - "Beacon enable %d\n", conf->enable_beacon); - - if (conf->enable_beacon) { - vnt_beacon_enable(priv, vif, conf); - - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); - } else { - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, - TCR_AUTOBCNTX); - } - } - - if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) && - priv->op_mode != NL80211_IFTYPE_AP) { - if (vif->cfg.assoc && conf->beacon_rate) { - card_update_tsf(priv, conf->beacon_rate->hw_value, - conf->sync_tsf); - - card_set_beacon_period(priv, conf->beacon_int); - - CARDvSetFirstNextTBTT(priv, conf->beacon_int); - } else { - iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); - iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL); - } - } -} - -static u64 vnt_prepare_multicast(struct ieee80211_hw *hw, - struct netdev_hw_addr_list *mc_list) -{ - struct vnt_private *priv = hw->priv; - struct netdev_hw_addr *ha; - u64 mc_filter = 0; - u32 bit_nr = 0; - - netdev_hw_addr_list_for_each(ha, mc_list) { - bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - - mc_filter |= 1ULL << (bit_nr & 0x3f); - } - - priv->mc_list_count = mc_list->count; - - return mc_filter; -} - -static void vnt_configure(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast) -{ - struct vnt_private *priv = hw->priv; - u8 rx_mode = 0; - - *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC; - - rx_mode = ioread8(priv->port_offset + MAC_REG_RCR); - - dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode); - - if (changed_flags & FIF_ALLMULTI) { - if (*total_flags & FIF_ALLMULTI) { - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->mc_list_count > 2) { - VT6655_MAC_SELECT_PAGE1(priv->port_offset); - - iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0); - iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0 + 4); - - VT6655_MAC_SELECT_PAGE0(priv->port_offset); - } else { - VT6655_MAC_SELECT_PAGE1(priv->port_offset); - - multicast = le64_to_cpu(multicast); - iowrite32((u32)multicast, priv->port_offset + MAC_REG_MAR0); - iowrite32((u32)(multicast >> 32), - priv->port_offset + MAC_REG_MAR0 + 4); - - VT6655_MAC_SELECT_PAGE0(priv->port_offset); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - rx_mode |= RCR_MULTICAST | RCR_BROADCAST; - } else { - rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); - } - } - - if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) { - rx_mode |= RCR_MULTICAST | RCR_BROADCAST; - - if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) - rx_mode &= ~RCR_BSSID; - else - rx_mode |= RCR_BSSID; - } - - iowrite8(rx_mode, priv->port_offset + MAC_REG_RCR); - - dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode); -} - -static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct vnt_private *priv = hw->priv; - - switch (cmd) { - case SET_KEY: - if (vnt_set_keys(hw, sta, vif, key)) - return -EOPNOTSUPP; - break; - case DISABLE_KEY: - if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) - clear_bit(key->hw_key_idx, &priv->key_entry_inuse); - break; - default: - break; - } - - return 0; -} - -static int vnt_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct vnt_private *priv = hw->priv; - - memcpy(stats, &priv->low_stats, sizeof(*stats)); - - return 0; -} - -static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - u64 tsf; - - tsf = vt6655_get_current_tsf(priv); - - return tsf; -} - -static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 tsf) -{ - struct vnt_private *priv = hw->priv; - - CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int); -} - -static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - /* reset TSF counter */ - iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); -} - -static const struct ieee80211_ops vnt_mac_ops = { - .add_chanctx = ieee80211_emulate_add_chanctx, - .remove_chanctx = ieee80211_emulate_remove_chanctx, - .change_chanctx = ieee80211_emulate_change_chanctx, - .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, - .tx = vnt_tx_80211, - .wake_tx_queue = ieee80211_handle_wake_tx_queue, - .start = vnt_start, - .stop = vnt_stop, - .add_interface = vnt_add_interface, - .remove_interface = vnt_remove_interface, - .config = vnt_config, - .bss_info_changed = vnt_bss_info_changed, - .prepare_multicast = vnt_prepare_multicast, - .configure_filter = vnt_configure, - .set_key = vnt_set_key, - .get_stats = vnt_get_stats, - .get_tsf = vnt_get_tsf, - .set_tsf = vnt_set_tsf, - .reset_tsf = vnt_reset_tsf, -}; - -static int vnt_init(struct vnt_private *priv) -{ - SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr); - - vnt_init_bands(priv); - - if (ieee80211_register_hw(priv->hw)) - return -ENODEV; - - priv->mac_hw = true; - - card_radio_power_off(priv); - - return 0; -} - -static int -vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) -{ - struct vnt_private *priv; - struct ieee80211_hw *hw; - struct wiphy *wiphy; - int rc; - - dev_notice(&pcid->dev, - "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION); - - dev_notice(&pcid->dev, - "Copyright (c) 2003 VIA Networking Technologies, Inc.\n"); - - hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops); - if (!hw) { - dev_err(&pcid->dev, "could not register ieee80211_hw\n"); - return -ENOMEM; - } - - priv = hw->priv; - priv->pcid = pcid; - - spin_lock_init(&priv->lock); - - priv->hw = hw; - - SET_IEEE80211_DEV(priv->hw, &pcid->dev); - - if (pci_enable_device(pcid)) { - device_free_info(priv); - return -ENODEV; - } - - dev_dbg(&pcid->dev, - "Before get pci_info memaddr is %x\n", priv->memaddr); - - pci_set_master(pcid); - - priv->memaddr = pci_resource_start(pcid, 0); - priv->ioaddr = pci_resource_start(pcid, 1); - priv->port_offset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK, - 256); - if (!priv->port_offset) { - dev_err(&pcid->dev, ": Failed to IO remapping ..\n"); - device_free_info(priv); - return -ENODEV; - } - - rc = pci_request_regions(pcid, DEVICE_NAME); - if (rc) { - dev_err(&pcid->dev, ": Failed to find PCI device\n"); - device_free_info(priv); - return -ENODEV; - } - - if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) { - dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n"); - device_free_info(priv); - return -ENODEV; - } - - INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); - - /* do reset */ - if (!MACbSoftwareReset(priv)) { - dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); - device_free_info(priv); - return -ENODEV; - } - /* initial to reload eeprom */ - MACvInitialize(priv); - vt6655_mac_read_ether_addr(priv->port_offset, priv->abyCurrentNetAddr); - - /* Get RFType */ - priv->rf_type = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_RFTYPE); - priv->rf_type &= RF_MASK; - - dev_dbg(&pcid->dev, "RF Type = %x\n", priv->rf_type); - - device_get_options(priv); - device_set_options(priv); - - wiphy = priv->hw->wiphy; - - wiphy->frag_threshold = FRAG_THRESH_DEF; - wiphy->rts_threshold = RTS_THRESH_DEF; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); - - ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY); - ieee80211_hw_set(priv->hw, SIGNAL_DBM); - ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); - ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(priv->hw, SUPPORTS_PS); - - priv->hw->max_signal = 100; - - if (vnt_init(priv)) { - device_free_info(priv); - return -ENODEV; - } - - device_print_info(priv); - pci_set_drvdata(pcid, priv); - - return 0; -} - -/*------------------------------------------------------------------*/ - -static int __maybe_unused vt6655_suspend(struct device *dev_d) -{ - struct vnt_private *priv = dev_get_drvdata(dev_d); - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - MACbShutdown(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static int __maybe_unused vt6655_resume(struct device *dev_d) -{ - device_wakeup_disable(dev_d); - - return 0; -} - -MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); - -static SIMPLE_DEV_PM_OPS(vt6655_pm_ops, vt6655_suspend, vt6655_resume); - -static struct pci_driver device_driver = { - .name = DEVICE_NAME, - .id_table = vt6655_pci_id_table, - .probe = vt6655_probe, - .remove = vt6655_remove, - .driver.pm = &vt6655_pm_ops, -}; - -module_pci_driver(device_driver); diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c deleted file mode 100644 index 7ada188e2048946e4934049d22af613eb53492af..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/dpc.c +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: handle dpc rx functions - * - * Author: Lyndon Chen - * - * Date: May 20, 2003 - * - * Functions: - * - * Revision History: - * - */ - -#include "device.h" -#include "baseband.h" -#include "rf.h" -#include "dpc.h" - -static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, - u16 bytes_received) -{ - struct ieee80211_hw *hw = priv->hw; - struct ieee80211_supported_band *sband; - struct ieee80211_rx_status rx_status = { 0 }; - struct ieee80211_hdr *hdr; - __le16 fc; - u8 *rsr, *new_rsr, *rssi; - __le64 *tsf_time; - u16 frame_size; - int ii, r; - u8 *rx_rate; - u8 *skb_data; - u8 rate_idx = 0; - u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; - long rx_dbm; - - /* [31:16]RcvByteCount ( not include 4-byte Status ) */ - frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2))); - if (frame_size > 2346 || frame_size < 14) { - dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n"); - return false; - } - - skb_data = (u8 *)skb->data; - - rx_rate = skb_data + 1; - - sband = hw->wiphy->bands[hw->conf.chandef.chan->band]; - - for (r = RATE_1M; r < MAX_RATE; r++) { - if (*rx_rate == rate[r]) - break; - } - - priv->rx_rate = r; - - for (ii = 0; ii < sband->n_bitrates; ii++) { - if (sband->bitrates[ii].hw_value == r) { - rate_idx = ii; - break; - } - } - - if (ii == sband->n_bitrates) { - dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate); - return false; - } - - tsf_time = (__le64 *)(skb_data + bytes_received - 12); - new_rsr = skb_data + bytes_received - 3; - rssi = skb_data + bytes_received - 2; - rsr = skb_data + bytes_received - 1; - if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) - return false; - - RFvRSSITodBm(priv, *rssi, &rx_dbm); - - priv->bb_pre_edrssi = (u8)rx_dbm + 1; - priv->current_rssi = *rssi; - - skb_pull(skb, 4); - skb_trim(skb, frame_size); - - rx_status.mactime = le64_to_cpu(*tsf_time); - rx_status.band = hw->conf.chandef.chan->band; - rx_status.signal = rx_dbm; - rx_status.flag = 0; - rx_status.freq = hw->conf.chandef.chan->center_freq; - - if (!(*rsr & RSR_CRCOK)) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; - - rx_status.rate_idx = rate_idx; - - if (ieee80211_has_protected(fc)) { - if (priv->local_id > REV_ID_VT3253_A1) - rx_status.flag |= RX_FLAG_DECRYPTED; - - /* Drop packet */ - if (!(*new_rsr & NEWRSR_DECRYPTOK)) - return false; - } - - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - - ieee80211_rx_irqsafe(priv->hw, skb); - - return true; -} - -bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd) -{ - struct vnt_rd_info *rd_info = curr_rd->rd_info; - struct sk_buff *skb; - u16 frame_size; - - skb = rd_info->skb; - - dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, - priv->rx_buf_sz, DMA_FROM_DEVICE); - - frame_size = le16_to_cpu(curr_rd->rd1.req_count) - - le16_to_cpu(curr_rd->rd0.res_count); - - if ((frame_size > 2364) || (frame_size < 33)) { - /* Frame Size error drop this packet.*/ - dev_dbg(&priv->pcid->dev, "Wrong frame size %d\n", frame_size); - dev_kfree_skb_irq(skb); - return true; - } - - if (vnt_rx_data(priv, skb, frame_size)) - return true; - - dev_kfree_skb_irq(skb); - - return true; -} diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h deleted file mode 100644 index 40364c0ab7f64f2fbc50620f7f72690be05d2504..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/dpc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: - * - * Author: Jerry Chen - * - * Date: Jun. 27, 2002 - * - */ - -#ifndef __DPC_H__ -#define __DPC_H__ - -#include "device.h" - -bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd); - -#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c deleted file mode 100644 index 1469015eb5b4a63a55772637edcb6dae6acb428f..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/key.c +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions for 802.11i Key management - * - * Author: Jerry Chen - * - * Date: May 29, 2003 - * - */ - -#include "key.h" -#include "mac.h" - -static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, - struct ieee80211_key_conf *key, u32 key_type, - u32 mode, bool onfly_latch) -{ - struct vnt_private *priv = hw->priv; - u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u16 key_mode = 0; - u32 entry = 0; - u8 *bssid; - u8 key_inx = key->keyidx; - u8 i; - - if (mac_addr) - bssid = mac_addr; - else - bssid = &broadcast[0]; - - if (key_type != VNT_KEY_DEFAULTKEY) { - for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { - if (!test_bit(i, &priv->key_entry_inuse)) { - set_bit(i, &priv->key_entry_inuse); - - key->hw_key_idx = i; - entry = key->hw_key_idx; - break; - } - } - } - - switch (key_type) { - case VNT_KEY_DEFAULTKEY: - /* default key last entry */ - entry = MAX_KEY_TABLE - 1; - key->hw_key_idx = entry; - fallthrough; - case VNT_KEY_ALLGROUP: - key_mode |= VNT_KEY_ALLGROUP; - if (onfly_latch) - key_mode |= VNT_KEY_ONFLY_ALL; - fallthrough; - case VNT_KEY_GROUP_ADDRESS: - key_mode |= mode; - fallthrough; - case VNT_KEY_GROUP: - key_mode |= (mode << 4); - key_mode |= VNT_KEY_GROUP; - break; - case VNT_KEY_PAIRWISE: - key_mode |= mode; - key_inx = 4; - break; - default: - return -EINVAL; - } - - if (onfly_latch) - key_mode |= VNT_KEY_ONFLY; - - if (mode == KEY_CTL_WEP) { - if (key->keylen == WLAN_KEY_LEN_WEP40) - key->key[15] &= 0x7f; - if (key->keylen == WLAN_KEY_LEN_WEP104) - key->key[15] |= 0x80; - } - - MACvSetKeyEntry(priv, key_mode, entry, key_inx, - bssid, (u32 *)key->key, priv->local_id); - - return 0; -} - -int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - struct ieee80211_vif *vif, struct ieee80211_key_conf *key) -{ - struct ieee80211_bss_conf *conf = &vif->bss_conf; - struct vnt_private *priv = hw->priv; - u8 *mac_addr = NULL; - u8 key_dec_mode = 0; - int ret = 0; - u32 u; - - if (sta) - mac_addr = &sta->addr[0]; - - switch (key->cipher) { - case 0: - for (u = 0 ; u < MAX_KEY_TABLE; u++) - MACvDisableKeyEntry(priv, u); - return ret; - - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - for (u = 0; u < MAX_KEY_TABLE; u++) - MACvDisableKeyEntry(priv, u); - - vnt_set_keymode(hw, mac_addr, - key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true); - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - - return ret; - case WLAN_CIPHER_SUITE_TKIP: - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - - key_dec_mode = KEY_CTL_TKIP; - - break; - case WLAN_CIPHER_SUITE_CCMP: - key_dec_mode = KEY_CTL_CCMP; - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { - vnt_set_keymode(hw, mac_addr, - key, VNT_KEY_PAIRWISE, key_dec_mode, true); - } else { - vnt_set_keymode(hw, mac_addr, - key, VNT_KEY_DEFAULTKEY, key_dec_mode, true); - - vnt_set_keymode(hw, (u8 *)conf->bssid, - key, VNT_KEY_GROUP_ADDRESS, key_dec_mode, true); - } - - return 0; -} diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h deleted file mode 100644 index d88da9dfb5c3be3a3b4d5b6a550f18f42360ecf0..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/key.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions for 802.11i Key management - * - * Author: Jerry Chen - * - * Date: May 29, 2003 - * - */ - -#ifndef __KEY_H__ -#define __KEY_H__ - -#include <net/mac80211.h> - -/*--------------------- Export Definitions -------------------------*/ -#define MAX_GROUP_KEY 4 -#define MAX_KEY_TABLE 11 -#define MAX_KEY_LEN 32 -#define AES_KEY_LEN 16 - -#define AUTHENTICATOR_KEY 0x10000000 -#define USE_KEYRSC 0x20000000 -#define PAIRWISE_KEY 0x40000000 -#define TRANSMIT_KEY 0x80000000 - -#define GROUP_KEY 0x00000000 - -#define KEY_CTL_WEP 0x00 -#define KEY_CTL_NONE 0x01 -#define KEY_CTL_TKIP 0x02 -#define KEY_CTL_CCMP 0x03 -#define KEY_CTL_INVALID 0xFF - -#define VNT_KEY_DEFAULTKEY 0x1 -#define VNT_KEY_GROUP_ADDRESS 0x2 -#define VNT_KEY_ALLGROUP 0x4 -#define VNT_KEY_GROUP 0x40 -#define VNT_KEY_PAIRWISE 0x00 -#define VNT_KEY_ONFLY 0x8000 -#define VNT_KEY_ONFLY_ALL 0x4000 - -struct vnt_private; - -int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - struct ieee80211_vif *vif, struct ieee80211_key_conf *key); - -#endif /* __KEY_H__ */ diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c deleted file mode 100644 index b4ebc7d319619065cbdf1153581c7ce9212772b2..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/mac.c +++ /dev/null @@ -1,851 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: MAC routines - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - * Functions: - * vt6655_mac_is_reg_bits_off - Test if All test Bits Off - * vt6655_mac_set_short_retry_limit - Set 802.11 Short Retry limit - * MACvSetLongRetryLimit - Set 802.11 Long Retry limit - * vt6655_mac_set_loopback_mode - Set MAC Loopback Mode - * vt6655_mac_save_context - Save Context of MAC Registers - * vt6655_mac_restore_context - Restore Context of MAC Registers - * MACbSoftwareReset - Software Reset MAC - * vt6655_mac_safe_rx_off - Turn Off MAC Rx - * vt6655_mac_safe_tx_off - Turn Off MAC Tx - * vt6655_mac_safe_stop - Stop MAC function - * MACbShutdown - Shut down MAC - * MACvInitialize - Initialize MAC - * MACvSetCurrRxDescAddr - Set Rx Descriptors Address - * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address - * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address - * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC - * - * Revision History: - * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53 - * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()& - * MACvEnableBusSusEn() - * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry - * - */ - -#include "mac.h" - -void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask) -{ - unsigned char reg_value; - - reg_value = ioread8(iobase + reg_offset); - iowrite8(reg_value | bit_mask, iobase + reg_offset); -} - -void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask) -{ - unsigned short reg_value; - - reg_value = ioread16(iobase + reg_offset); - iowrite16(reg_value | (bit_mask), iobase + reg_offset); -} - -void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask) -{ - unsigned char reg_value; - - reg_value = ioread8(iobase + reg_offset); - iowrite8(reg_value & ~(bit_mask), iobase + reg_offset); -} - -void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask) -{ - unsigned short reg_value; - - reg_value = ioread16(iobase + reg_offset); - iowrite16(reg_value & ~(bit_mask), iobase + reg_offset); -} - -static void vt6655_mac_clear_stck_ds(void __iomem *iobase) -{ - u8 reg_value; - - reg_value = ioread8(iobase + MAC_REG_STICKHW); - reg_value = reg_value & 0xFC; - iowrite8(reg_value, iobase + MAC_REG_STICKHW); -} - -/* - * Description: - * Test if all test bits off - * - * Parameters: - * In: - * io_base - Base Address for MAC - * reg_offset - Offset of MAC Register - * mask - Test bits - * Out: - * none - * - * Return Value: true if all test bits Off; otherwise false - * - */ -static bool vt6655_mac_is_reg_bits_off(struct vnt_private *priv, - unsigned char reg_offset, - unsigned char mask) -{ - void __iomem *io_base = priv->port_offset; - - return !(ioread8(io_base + reg_offset) & mask); -} - -/* - * Description: - * Set 802.11 Short Retry Limit - * - * Parameters: - * In: - * io_base - Base Address for MAC - * retry_limit - Retry Limit - * Out: - * none - * - * Return Value: none - * - */ -void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit) -{ - void __iomem *io_base = priv->port_offset; - /* set SRT */ - iowrite8(retry_limit, io_base + MAC_REG_SRT); -} - -/* - * Description: - * Set 802.11 Long Retry Limit - * - * Parameters: - * In: - * io_base - Base Address for MAC - * byRetryLimit- Retry Limit - * Out: - * none - * - * Return Value: none - * - */ -void MACvSetLongRetryLimit(struct vnt_private *priv, - unsigned char byRetryLimit) -{ - void __iomem *io_base = priv->port_offset; - /* set LRT */ - iowrite8(byRetryLimit, io_base + MAC_REG_LRT); -} - -/* - * Description: - * Set MAC Loopback mode - * - * Parameters: - * In: - * io_base - Base Address for MAC - * loopback_mode - Loopback Mode - * Out: - * none - * - * Return Value: none - * - */ -static void vt6655_mac_set_loopback_mode(struct vnt_private *priv, u8 loopback_mode) -{ - void __iomem *io_base = priv->port_offset; - - loopback_mode <<= 6; - /* set TCR */ - iowrite8((ioread8(io_base + MAC_REG_TEST) & 0x3f) | loopback_mode, io_base + MAC_REG_TEST); -} - -/* - * Description: - * Save MAC registers to context buffer - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * cxt_buf - Context buffer - * - * Return Value: none - * - */ -static void vt6655_mac_save_context(struct vnt_private *priv, u8 *cxt_buf) -{ - void __iomem *io_base = priv->port_offset; - - /* read page0 register */ - memcpy_fromio(cxt_buf, io_base, MAC_MAX_CONTEXT_SIZE_PAGE0); - - VT6655_MAC_SELECT_PAGE1(io_base); - - /* read page1 register */ - memcpy_fromio(cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, io_base, - MAC_MAX_CONTEXT_SIZE_PAGE1); - - VT6655_MAC_SELECT_PAGE0(io_base); -} - -/* - * Description: - * Restore MAC registers from context buffer - * - * Parameters: - * In: - * io_base - Base Address for MAC - * cxt_buf - Context buffer - * Out: - * none - * - * Return Value: none - * - */ -static void vt6655_mac_restore_context(struct vnt_private *priv, u8 *cxt_buf) -{ - void __iomem *io_base = priv->port_offset; - - VT6655_MAC_SELECT_PAGE1(io_base); - /* restore page1 */ - memcpy_toio(io_base, cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, - MAC_MAX_CONTEXT_SIZE_PAGE1); - - VT6655_MAC_SELECT_PAGE0(io_base); - - /* restore RCR,TCR,IMR... */ - memcpy_toio(io_base + MAC_REG_RCR, cxt_buf + MAC_REG_RCR, - MAC_REG_ISR - MAC_REG_RCR); - - /* restore MAC Config. */ - memcpy_toio(io_base + MAC_REG_LRT, cxt_buf + MAC_REG_LRT, - MAC_REG_PAGE1SEL - MAC_REG_LRT); - - iowrite8(*(cxt_buf + MAC_REG_CFG), io_base + MAC_REG_CFG); - - /* restore PS Config. */ - memcpy_toio(io_base + MAC_REG_PSCFG, cxt_buf + MAC_REG_PSCFG, - MAC_REG_BBREGCTL - MAC_REG_PSCFG); - - /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */ - iowrite32(*(u32 *)(cxt_buf + MAC_REG_TXDMAPTR0), - io_base + MAC_REG_TXDMAPTR0); - iowrite32(*(u32 *)(cxt_buf + MAC_REG_AC0DMAPTR), - io_base + MAC_REG_AC0DMAPTR); - iowrite32(*(u32 *)(cxt_buf + MAC_REG_BCNDMAPTR), - io_base + MAC_REG_BCNDMAPTR); - iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR0), - io_base + MAC_REG_RXDMAPTR0); - iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR1), - io_base + MAC_REG_RXDMAPTR1); -} - -/* - * Description: - * Software Reset MAC - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: true if Reset Success; otherwise false - * - */ -bool MACbSoftwareReset(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - - /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */ - iowrite8(0x01, io_base + MAC_REG_HOSTCR); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_SOFTRST)) - break; - } - if (ww == W_MAX_TIMEOUT) - return false; - return true; -} - -/* - * Description: - * save some important register's value, then do reset, then restore - * register's value - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -static void vt6655_mac_save_soft_reset(struct vnt_private *priv) -{ - u8 tmp_reg_data[MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1]; - - /* PATCH.... - * save some important register's value, then do - * reset, then restore register's value - */ - /* save MAC context */ - vt6655_mac_save_context(priv, tmp_reg_data); - /* do reset */ - MACbSoftwareReset(priv); - /* restore MAC context, except CR0 */ - vt6655_mac_restore_context(priv, tmp_reg_data); -} - -/* - * Description: - * Turn Off MAC Rx - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -static bool vt6655_mac_safe_rx_off(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - - /* turn off wow temp for turn off Rx safely */ - - /* Clear RX DMA0,1 */ - iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL0); - iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL1); - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread32(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN)) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x10)\n"); - return false; - } - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread32(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN)) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x11)\n"); - return false; - } - - /* try to safe shutdown RX */ - vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_RXON); - /* W_MAX_TIMEOUT is the timeout period */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_RXONST)) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x12)\n"); - return false; - } - return true; -} - -/* - * Description: - * Turn Off MAC Tx - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -static bool vt6655_mac_safe_tx_off(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - - /* Clear TX DMA */ - /* Tx0 */ - iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_TXDMACTL0); - /* AC0 */ - iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_AC0DMACTL); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread32(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN)) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x20)\n"); - return false; - } - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread32(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN)) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x21)\n"); - return false; - } - - /* try to safe shutdown TX */ - vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_TXON); - - /* W_MAX_TIMEOUT is the timeout period */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_TXONST)) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x24)\n"); - return false; - } - return true; -} - -/* - * Description: - * Stop MAC function - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -static bool vt6655_mac_safe_stop(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - - vt6655_mac_reg_bits_off(io_base, MAC_REG_TCR, TCR_AUTOBCNTX); - - if (!vt6655_mac_safe_rx_off(priv)) { - pr_debug(" vt6655_mac_safe_rx_off == false)\n"); - vt6655_mac_save_soft_reset(priv); - return false; - } - if (!vt6655_mac_safe_tx_off(priv)) { - pr_debug(" vt6655_mac_safe_tx_off == false)\n"); - vt6655_mac_save_soft_reset(priv); - return false; - } - - vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_MACEN); - - return true; -} - -/* - * Description: - * Shut Down MAC - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -bool MACbShutdown(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - /* disable MAC IMR */ - iowrite32(0, io_base + MAC_REG_IMR); - vt6655_mac_set_loopback_mode(priv, MAC_LB_INTERNAL); - /* stop the adapter */ - if (!vt6655_mac_safe_stop(priv)) { - vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE); - return false; - } - vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE); - return true; -} - -/* - * Description: - * Initialize MAC - * - * Parameters: - * In: - * io_base - Base Address for MAC - * Out: - * none - * - * Return Value: none - * - */ -void MACvInitialize(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - /* clear sticky bits */ - vt6655_mac_clear_stck_ds(io_base); - /* disable force PME-enable */ - iowrite8(PME_OVR, io_base + MAC_REG_PMC1); - /* only 3253 A */ - - /* do reset */ - MACbSoftwareReset(priv); - - /* reset TSF counter */ - iowrite8(TFTCTL_TSFCNTRST, io_base + MAC_REG_TFTCTL); - /* enable TSF counter */ - iowrite8(TFTCTL_TSFCNTREN, io_base + MAC_REG_TFTCTL); -} - -/* - * Description: - * Set the chip with current rx descriptor address - * - * Parameters: - * In: - * io_base - Base Address for MAC - * curr_desc_addr - Descriptor Address - * Out: - * none - * - * Return Value: none - * - */ -void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - unsigned char org_dma_ctl; - - org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL0); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0 + 2); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN)) - break; - } - - iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR0); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0); -} - -/* - * Description: - * Set the chip with current rx descriptor address - * - * Parameters: - * In: - * io_base - Base Address for MAC - * curr_desc_addr - Descriptor Address - * Out: - * none - * - * Return Value: none - * - */ -void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - unsigned char org_dma_ctl; - - org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL1); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1 + 2); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN)) - break; - } - - iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR1); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1); -} - -/* - * Description: - * Set the chip with current tx0 descriptor address - * - * Parameters: - * In: - * io_base - Base Address for MAC - * curr_desc_addr - Descriptor Address - * Out: - * none - * - * Return Value: none - * - */ -static void vt6655_mac_set_curr_tx_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - unsigned char org_dma_ctl; - - org_dma_ctl = ioread8(io_base + MAC_REG_TXDMACTL0); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0 + 2); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN)) - break; - } - - iowrite32(curr_desc_addr, io_base + MAC_REG_TXDMAPTR0); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0); -} - -/* - * Description: - * Set the chip with current AC0 descriptor address - * - * Parameters: - * In: - * io_base - Base Address for MAC - * curr_desc_addr - Descriptor Address - * Out: - * none - * - * Return Value: none - * - */ -/* TxDMA1 = AC0DMA */ -static void vt6655_mac_set_curr_ac_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr) -{ - void __iomem *io_base = priv->port_offset; - unsigned short ww; - unsigned char org_dma_ctl; - - org_dma_ctl = ioread8(io_base + MAC_REG_AC0DMACTL); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL + 2); - - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (!(ioread8(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN)) - break; - } - if (ww == W_MAX_TIMEOUT) - pr_debug(" DBG_PORT80(0x26)\n"); - iowrite32(curr_desc_addr, io_base + MAC_REG_AC0DMAPTR); - if (org_dma_ctl & DMACTL_RUN) - iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL); -} - -void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr) -{ - if (tx_type == TYPE_AC0DMA) - vt6655_mac_set_curr_ac_0_desc_addr_ex(priv, curr_desc_addr); - else if (tx_type == TYPE_TXDMA0) - vt6655_mac_set_curr_tx_0_desc_addr_ex(priv, curr_desc_addr); -} - -/* - * Description: - * Micro Second Delay via MAC - * - * Parameters: - * In: - * io_base - Base Address for MAC - * uDelay - Delay time (timer resolution is 4 us) - * Out: - * none - * - * Return Value: none - * - */ -void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay) -{ - void __iomem *io_base = priv->port_offset; - unsigned char byValue; - unsigned int uu, ii; - - iowrite8(0, io_base + MAC_REG_TMCTL0); - iowrite32(uDelay, io_base + MAC_REG_TMDATA0); - iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL0); - for (ii = 0; ii < 66; ii++) { /* assume max PCI clock is 66Mhz */ - for (uu = 0; uu < uDelay; uu++) { - byValue = ioread8(io_base + MAC_REG_TMCTL0); - if ((byValue == 0) || - (byValue & TMCTL_TSUSP)) { - iowrite8(0, io_base + MAC_REG_TMCTL0); - return; - } - } - } - iowrite8(0, io_base + MAC_REG_TMCTL0); -} - -/* - * Description: - * Micro Second One shot timer via MAC - * - * Parameters: - * In: - * io_base - Base Address for MAC - * uDelay - Delay time - * Out: - * none - * - * Return Value: none - * - */ -void MACvOneShotTimer1MicroSec(struct vnt_private *priv, - unsigned int uDelayTime) -{ - void __iomem *io_base = priv->port_offset; - - iowrite8(0, io_base + MAC_REG_TMCTL1); - iowrite32(uDelayTime, io_base + MAC_REG_TMDATA1); - iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL1); -} - -void MACvSetMISCFifo(struct vnt_private *priv, unsigned short offset, - u32 data) -{ - void __iomem *io_base = priv->port_offset; - - if (offset > 273) - return; - iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); - iowrite32(data, io_base + MAC_REG_MISCFFDATA); - iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); -} - -bool MACbPSWakeup(struct vnt_private *priv) -{ - void __iomem *io_base = priv->port_offset; - unsigned int ww; - /* Read PSCTL */ - if (vt6655_mac_is_reg_bits_off(priv, MAC_REG_PSCTL, PSCTL_PS)) - return true; - - /* Disable PS */ - vt6655_mac_reg_bits_off(io_base, MAC_REG_PSCTL, PSCTL_PSEN); - - /* Check if SyncFlushOK */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - if (ioread8(io_base + MAC_REG_PSCTL) & PSCTL_WAKEDONE) - break; - } - if (ww == W_MAX_TIMEOUT) { - pr_debug(" DBG_PORT80(0x33)\n"); - return false; - } - return true; -} - -/* - * Description: - * Set the Key by MISCFIFO - * - * Parameters: - * In: - * io_base - Base Address for MAC - * - * Out: - * none - * - * Return Value: none - * - */ - -void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl, - unsigned int uEntryIdx, unsigned int uKeyIdx, - unsigned char *pbyAddr, u32 *pdwKey, - unsigned char local_id) -{ - void __iomem *io_base = priv->port_offset; - unsigned short offset; - u32 data; - int ii; - - if (local_id <= 1) - return; - - offset = MISCFIFO_KEYETRY0; - offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); - - data = 0; - data |= wKeyCtl; - data <<= 16; - data |= MAKEWORD(*(pbyAddr + 4), *(pbyAddr + 5)); - pr_debug("1. offset: %d, Data: %X, KeyCtl:%X\n", - offset, data, wKeyCtl); - - iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); - iowrite32(data, io_base + MAC_REG_MISCFFDATA); - iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); - offset++; - - data = 0; - data |= *(pbyAddr + 3); - data <<= 8; - data |= *(pbyAddr + 2); - data <<= 8; - data |= *(pbyAddr + 1); - data <<= 8; - data |= *pbyAddr; - pr_debug("2. offset: %d, Data: %X\n", offset, data); - - iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); - iowrite32(data, io_base + MAC_REG_MISCFFDATA); - iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); - offset++; - - offset += (uKeyIdx * 4); - for (ii = 0; ii < 4; ii++) { - /* always push 128 bits */ - pr_debug("3.(%d) offset: %d, Data: %X\n", - ii, offset + ii, *pdwKey); - iowrite16(offset + ii, io_base + MAC_REG_MISCFFNDEX); - iowrite32(*pdwKey++, io_base + MAC_REG_MISCFFDATA); - iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); - } -} - -/* - * Description: - * Disable the Key Entry by MISCFIFO - * - * Parameters: - * In: - * io_base - Base Address for MAC - * - * Out: - * none - * - * Return Value: none - * - */ -void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx) -{ - void __iomem *io_base = priv->port_offset; - unsigned short offset; - - offset = MISCFIFO_KEYETRY0; - offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE); - - iowrite16(offset, io_base + MAC_REG_MISCFFNDEX); - iowrite32(0, io_base + MAC_REG_MISCFFDATA); - iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL); -} diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h deleted file mode 100644 index a33af28522276324034edc884ae2823ad7a68ad0..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/mac.h +++ /dev/null @@ -1,580 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: MAC routines - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - * Revision History: - * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53. - * 09-03-2003 Bryan YC Fan: Add vt6655_mac_dis_protect_md & vt6655_mac_en_protect_md - */ - -#ifndef __MAC_H__ -#define __MAC_H__ - -#include "device.h" - -/*--------------------- Export Definitions -------------------------*/ -/* Registers in the MAC */ -#define MAC_MAX_CONTEXT_SIZE_PAGE0 256 -#define MAC_MAX_CONTEXT_SIZE_PAGE1 128 - -/* Registers not related to 802.11b */ -#define MAC_REG_BCFG0 0x00 -#define MAC_REG_BCFG1 0x01 -#define MAC_REG_FCR0 0x02 -#define MAC_REG_FCR1 0x03 -#define MAC_REG_BISTCMD 0x04 -#define MAC_REG_BISTSR0 0x05 -#define MAC_REG_BISTSR1 0x06 -#define MAC_REG_BISTSR2 0x07 -#define MAC_REG_I2MCSR 0x08 -#define MAC_REG_I2MTGID 0x09 -#define MAC_REG_I2MTGAD 0x0A -#define MAC_REG_I2MCFG 0x0B -#define MAC_REG_I2MDIPT 0x0C -#define MAC_REG_I2MDOPT 0x0E -#define MAC_REG_PMC0 0x10 -#define MAC_REG_PMC1 0x11 -#define MAC_REG_STICKHW 0x12 -#define MAC_REG_LOCALID 0x14 -#define MAC_REG_TESTCFG 0x15 -#define MAC_REG_JUMPER0 0x16 -#define MAC_REG_JUMPER1 0x17 -#define MAC_REG_TMCTL0 0x18 -#define MAC_REG_TMCTL1 0x19 -#define MAC_REG_TMDATA0 0x1C - -/* MAC Parameter related */ -#define MAC_REG_LRT 0x20 -#define MAC_REG_SRT 0x21 -#define MAC_REG_SIFS 0x22 -#define MAC_REG_DIFS 0x23 -#define MAC_REG_EIFS 0x24 -#define MAC_REG_SLOT 0x25 -#define MAC_REG_BI 0x26 -#define MAC_REG_CWMAXMIN0 0x28 -#define MAC_REG_LINKOFFTOTM 0x2A -#define MAC_REG_SWTMOT 0x2B -#define MAC_REG_MIBCNTR 0x2C -#define MAC_REG_RTSOKCNT 0x2C -#define MAC_REG_RTSFAILCNT 0x2D -#define MAC_REG_ACKFAILCNT 0x2E -#define MAC_REG_FCSERRCNT 0x2F - -/* TSF Related */ -#define MAC_REG_TSFCNTR 0x30 -#define MAC_REG_NEXTTBTT 0x38 -#define MAC_REG_TSFOFST 0x40 -#define MAC_REG_TFTCTL 0x48 - -/* WMAC Control/Status Related */ -#define MAC_REG_ENCFG 0x4C -#define MAC_REG_PAGE1SEL 0x4F -#define MAC_REG_CFG 0x50 -#define MAC_REG_TEST 0x52 -#define MAC_REG_HOSTCR 0x54 -#define MAC_REG_MACCR 0x55 -#define MAC_REG_RCR 0x56 -#define MAC_REG_TCR 0x57 -#define MAC_REG_IMR 0x58 -#define MAC_REG_ISR 0x5C - -/* Power Saving Related */ -#define MAC_REG_PSCFG 0x60 -#define MAC_REG_PSCTL 0x61 -#define MAC_REG_PSPWRSIG 0x62 -#define MAC_REG_BBCR13 0x63 -#define MAC_REG_AIDATIM 0x64 -#define MAC_REG_PWBT 0x66 -#define MAC_REG_WAKEOKTMR 0x68 -#define MAC_REG_CALTMR 0x69 -#define MAC_REG_SYNSPACCNT 0x6A -#define MAC_REG_WAKSYNOPT 0x6B - -/* Baseband/IF Control Group */ -#define MAC_REG_BBREGCTL 0x6C -#define MAC_REG_CHANNEL 0x6D -#define MAC_REG_BBREGADR 0x6E -#define MAC_REG_BBREGDATA 0x6F -#define MAC_REG_IFREGCTL 0x70 -#define MAC_REG_IFDATA 0x71 -#define MAC_REG_ITRTMSET 0x74 -#define MAC_REG_PAPEDELAY 0x77 -#define MAC_REG_SOFTPWRCTL 0x78 -#define MAC_REG_GPIOCTL0 0x7A -#define MAC_REG_GPIOCTL1 0x7B - -/* MAC DMA Related Group */ -#define MAC_REG_TXDMACTL0 0x7C -#define MAC_REG_TXDMAPTR0 0x80 -#define MAC_REG_AC0DMACTL 0x84 -#define MAC_REG_AC0DMAPTR 0x88 -#define MAC_REG_BCNDMACTL 0x8C -#define MAC_REG_BCNDMAPTR 0x90 -#define MAC_REG_RXDMACTL0 0x94 -#define MAC_REG_RXDMAPTR0 0x98 -#define MAC_REG_RXDMACTL1 0x9C -#define MAC_REG_RXDMAPTR1 0xA0 -#define MAC_REG_SYNCDMACTL 0xA4 -#define MAC_REG_SYNCDMAPTR 0xA8 -#define MAC_REG_ATIMDMACTL 0xAC -#define MAC_REG_ATIMDMAPTR 0xB0 - -/* MiscFF PIO related */ -#define MAC_REG_MISCFFNDEX 0xB4 -#define MAC_REG_MISCFFCTL 0xB6 -#define MAC_REG_MISCFFDATA 0xB8 - -/* Extend SW Timer */ -#define MAC_REG_TMDATA1 0xBC - -/* WOW Related Group */ -#define MAC_REG_WAKEUPEN0 0xC0 -#define MAC_REG_WAKEUPEN1 0xC1 -#define MAC_REG_WAKEUPSR0 0xC2 -#define MAC_REG_WAKEUPSR1 0xC3 -#define MAC_REG_WAKE128_0 0xC4 -#define MAC_REG_WAKE128_1 0xD4 -#define MAC_REG_WAKE128_2 0xE4 -#define MAC_REG_WAKE128_3 0xF4 - -/************** Page 1 ******************/ -#define MAC_REG_CRC_128_0 0x04 -#define MAC_REG_CRC_128_1 0x06 -#define MAC_REG_CRC_128_2 0x08 -#define MAC_REG_CRC_128_3 0x0A - -/* MAC Configuration Group */ -#define MAC_REG_PAR0 0x0C -#define MAC_REG_PAR4 0x10 -#define MAC_REG_BSSID0 0x14 -#define MAC_REG_BSSID4 0x18 -#define MAC_REG_MAR0 0x1C -#define MAC_REG_MAR4 0x20 - -/* MAC RSPPKT INFO Group */ -#define MAC_REG_RSPINF_B_1 0x24 -#define MAC_REG_RSPINF_B_2 0x28 -#define MAC_REG_RSPINF_B_5 0x2C -#define MAC_REG_RSPINF_B_11 0x30 -#define MAC_REG_RSPINF_A_6 0x34 -#define MAC_REG_RSPINF_A_9 0x36 -#define MAC_REG_RSPINF_A_12 0x38 -#define MAC_REG_RSPINF_A_18 0x3A -#define MAC_REG_RSPINF_A_24 0x3C -#define MAC_REG_RSPINF_A_36 0x3E -#define MAC_REG_RSPINF_A_48 0x40 -#define MAC_REG_RSPINF_A_54 0x42 -#define MAC_REG_RSPINF_A_72 0x44 - -/* 802.11h relative */ -#define MAC_REG_QUIETINIT 0x60 -#define MAC_REG_QUIETGAP 0x62 -#define MAC_REG_QUIETDUR 0x64 -#define MAC_REG_MSRCTL 0x66 -#define MAC_REG_MSRBBSTS 0x67 -#define MAC_REG_MSRSTART 0x68 -#define MAC_REG_MSRDURATION 0x70 -#define MAC_REG_CCAFRACTION 0x72 -#define MAC_REG_PWRCCK 0x73 -#define MAC_REG_PWROFDM 0x7C - -/* Bits in the BCFG0 register */ -#define BCFG0_PERROFF 0x40 -#define BCFG0_MRDMDIS 0x20 -#define BCFG0_MRDLDIS 0x10 -#define BCFG0_MWMEN 0x08 -#define BCFG0_VSERREN 0x02 -#define BCFG0_LATMEN 0x01 - -/* Bits in the BCFG1 register */ -#define BCFG1_CFUNOPT 0x80 -#define BCFG1_CREQOPT 0x40 -#define BCFG1_DMA8 0x10 -#define BCFG1_ARBITOPT 0x08 -#define BCFG1_PCIMEN 0x04 -#define BCFG1_MIOEN 0x02 -#define BCFG1_CISDLYEN 0x01 - -/* Bits in RAMBIST registers */ -#define BISTCMD_TSTPAT5 0x00 -#define BISTCMD_TSTPATA 0x80 -#define BISTCMD_TSTERR 0x20 -#define BISTCMD_TSTPATF 0x18 -#define BISTCMD_TSTPAT0 0x10 -#define BISTCMD_TSTMODE 0x04 -#define BISTCMD_TSTITTX 0x03 -#define BISTCMD_TSTATRX 0x02 -#define BISTCMD_TSTATTX 0x01 -#define BISTCMD_TSTRX 0x00 -#define BISTSR0_BISTGO 0x01 -#define BISTSR1_TSTSR 0x01 -#define BISTSR2_CMDPRTEN 0x02 -#define BISTSR2_RAMTSTEN 0x01 - -/* Bits in the I2MCFG EEPROM register */ -#define I2MCFG_BOUNDCTL 0x80 -#define I2MCFG_WAITCTL 0x20 -#define I2MCFG_SCLOECTL 0x10 -#define I2MCFG_WBUSYCTL 0x08 -#define I2MCFG_NORETRY 0x04 -#define I2MCFG_I2MLDSEQ 0x02 -#define I2MCFG_I2CMFAST 0x01 - -/* Bits in the I2MCSR EEPROM register */ -#define I2MCSR_EEMW 0x80 -#define I2MCSR_EEMR 0x40 -#define I2MCSR_AUTOLD 0x08 -#define I2MCSR_NACK 0x02 -#define I2MCSR_DONE 0x01 - -/* Bits in the PMC1 register */ -#define SPS_RST 0x80 -#define PCISTIKY 0x40 -#define PME_OVR 0x02 - -/* Bits in the STICKYHW register */ -#define STICKHW_DS1_SHADOW 0x02 -#define STICKHW_DS0_SHADOW 0x01 - -/* Bits in the TMCTL register */ -#define TMCTL_TSUSP 0x04 -#define TMCTL_TMD 0x02 -#define TMCTL_TE 0x01 - -/* Bits in the TFTCTL register */ -#define TFTCTL_HWUTSF 0x80 -#define TFTCTL_TBTTSYNC 0x40 -#define TFTCTL_HWUTSFEN 0x20 -#define TFTCTL_TSFCNTRRD 0x10 -#define TFTCTL_TBTTSYNCEN 0x08 -#define TFTCTL_TSFSYNCEN 0x04 -#define TFTCTL_TSFCNTRST 0x02 -#define TFTCTL_TSFCNTREN 0x01 - -/* Bits in the EnhanceCFG register */ -#define ENCFG_BARKERPREAM 0x00020000 -#define ENCFG_NXTBTTCFPSTR 0x00010000 -#define ENCFG_BCNSUSCLR 0x00000200 -#define ENCFG_BCNSUSIND 0x00000100 -#define ENCFG_CFP_PROTECTEN 0x00000040 -#define ENCFG_PROTECTMD 0x00000020 -#define ENCFG_HWPARCFP 0x00000010 -#define ENCFG_CFNULRSP 0x00000004 -#define ENCFG_BBTYPE_MASK 0x00000003 -#define ENCFG_BBTYPE_G 0x00000002 -#define ENCFG_BBTYPE_B 0x00000001 -#define ENCFG_BBTYPE_A 0x00000000 - -/* Bits in the Page1Sel register */ -#define PAGE1_SEL 0x01 - -/* Bits in the CFG register */ -#define CFG_TKIPOPT 0x80 -#define CFG_RXDMAOPT 0x40 -#define CFG_TMOT_SW 0x20 -#define CFG_TMOT_HWLONG 0x10 -#define CFG_TMOT_HW 0x00 -#define CFG_CFPENDOPT 0x08 -#define CFG_BCNSUSEN 0x04 -#define CFG_NOTXTIMEOUT 0x02 -#define CFG_NOBUFOPT 0x01 - -/* Bits in the TEST register */ -#define TEST_LBEXT 0x80 -#define TEST_LBINT 0x40 -#define TEST_LBNONE 0x00 -#define TEST_SOFTINT 0x20 -#define TEST_CONTTX 0x10 -#define TEST_TXPE 0x08 -#define TEST_NAVDIS 0x04 -#define TEST_NOCTS 0x02 -#define TEST_NOACK 0x01 - -/* Bits in the HOSTCR register */ -#define HOSTCR_TXONST 0x80 -#define HOSTCR_RXONST 0x40 -#define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */ -#define HOSTCR_AP 0x10 /* Port Type 1 = AP */ -#define HOSTCR_TXON 0x08 /* 0000 1000 */ -#define HOSTCR_RXON 0x04 /* 0000 0100 */ -#define HOSTCR_MACEN 0x02 /* 0000 0010 */ -#define HOSTCR_SOFTRST 0x01 /* 0000 0001 */ - -/* Bits in the MACCR register */ -#define MACCR_SYNCFLUSHOK 0x04 -#define MACCR_SYNCFLUSH 0x02 -#define MACCR_CLRNAV 0x01 - -/* Bits in the MAC_REG_GPIOCTL0 register */ -#define LED_ACTSET 0x01 -#define LED_RFOFF 0x02 -#define LED_NOCONNECT 0x04 - -/* Bits in the RCR register */ -#define RCR_SSID 0x80 -#define RCR_RXALLTYPE 0x40 -#define RCR_UNICAST 0x20 -#define RCR_BROADCAST 0x10 -#define RCR_MULTICAST 0x08 -#define RCR_WPAERR 0x04 -#define RCR_ERRCRC 0x02 -#define RCR_BSSID 0x01 - -/* Bits in the TCR register */ -#define TCR_SYNCDCFOPT 0x02 -#define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */ - -/* Bits in the IMR register */ -#define IMR_MEASURESTART 0x80000000 -#define IMR_QUIETSTART 0x20000000 -#define IMR_RADARDETECT 0x10000000 -#define IMR_MEASUREEND 0x08000000 -#define IMR_SOFTTIMER1 0x00200000 -#define IMR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ -#define IMR_RXNOBUF 0x00000800 -#define IMR_MIBNEARFULL 0x00000400 -#define IMR_SOFTINT 0x00000200 -#define IMR_FETALERR 0x00000100 -#define IMR_WATCHDOG 0x00000080 -#define IMR_SOFTTIMER 0x00000040 -#define IMR_GPIO 0x00000020 -#define IMR_TBTT 0x00000010 -#define IMR_RXDMA0 0x00000008 -#define IMR_BNTX 0x00000004 -#define IMR_AC0DMA 0x00000002 -#define IMR_TXDMA0 0x00000001 - -/* Bits in the ISR register */ -#define ISR_MEASURESTART 0x80000000 -#define ISR_QUIETSTART 0x20000000 -#define ISR_RADARDETECT 0x10000000 -#define ISR_MEASUREEND 0x08000000 -#define ISR_SOFTTIMER1 0x00200000 -#define ISR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ -#define ISR_RXNOBUF 0x00000800 /* 0000 0000 0000 1000 0000 0000 */ -#define ISR_MIBNEARFULL 0x00000400 /* 0000 0000 0000 0100 0000 0000 */ -#define ISR_SOFTINT 0x00000200 -#define ISR_FETALERR 0x00000100 -#define ISR_WATCHDOG 0x00000080 -#define ISR_SOFTTIMER 0x00000040 -#define ISR_GPIO 0x00000020 -#define ISR_TBTT 0x00000010 -#define ISR_RXDMA0 0x00000008 -#define ISR_BNTX 0x00000004 -#define ISR_AC0DMA 0x00000002 -#define ISR_TXDMA0 0x00000001 - -/* Bits in the PSCFG register */ -#define PSCFG_PHILIPMD 0x40 -#define PSCFG_WAKECALEN 0x20 -#define PSCFG_WAKETMREN 0x10 -#define PSCFG_BBPSPROG 0x08 -#define PSCFG_WAKESYN 0x04 -#define PSCFG_SLEEPSYN 0x02 -#define PSCFG_AUTOSLEEP 0x01 - -/* Bits in the PSCTL register */ -#define PSCTL_WAKEDONE 0x20 -#define PSCTL_PS 0x10 -#define PSCTL_GO2DOZE 0x08 -#define PSCTL_LNBCN 0x04 -#define PSCTL_ALBCN 0x02 -#define PSCTL_PSEN 0x01 - -/* Bits in the PSPWSIG register */ -#define PSSIG_WPE3 0x80 -#define PSSIG_WPE2 0x40 -#define PSSIG_WPE1 0x20 -#define PSSIG_WRADIOPE 0x10 -#define PSSIG_SPE3 0x08 -#define PSSIG_SPE2 0x04 -#define PSSIG_SPE1 0x02 -#define PSSIG_SRADIOPE 0x01 - -/* Bits in the BBREGCTL register */ -#define BBREGCTL_DONE 0x04 -#define BBREGCTL_REGR 0x02 -#define BBREGCTL_REGW 0x01 - -/* Bits in the IFREGCTL register */ -#define IFREGCTL_DONE 0x04 -#define IFREGCTL_IFRF 0x02 -#define IFREGCTL_REGW 0x01 - -/* Bits in the SOFTPWRCTL register */ -#define SOFTPWRCTL_RFLEOPT 0x0800 -#define SOFTPWRCTL_TXPEINV 0x0200 -#define SOFTPWRCTL_SWPECTI 0x0100 -#define SOFTPWRCTL_SWPAPE 0x0020 -#define SOFTPWRCTL_SWCALEN 0x0010 -#define SOFTPWRCTL_SWRADIO_PE 0x0008 -#define SOFTPWRCTL_SWPE2 0x0004 -#define SOFTPWRCTL_SWPE1 0x0002 -#define SOFTPWRCTL_SWPE3 0x0001 - -/* Bits in the GPIOCTL1 register */ -#define GPIO1_DATA1 0x20 -#define GPIO1_MD1 0x10 -#define GPIO1_DATA0 0x02 -#define GPIO1_MD0 0x01 - -/* Bits in the DMACTL register */ -#define DMACTL_CLRRUN 0x00080000 -#define DMACTL_RUN 0x00000008 -#define DMACTL_WAKE 0x00000004 -#define DMACTL_DEAD 0x00000002 -#define DMACTL_ACTIVE 0x00000001 - -/* Bits in the RXDMACTL0 register */ -#define RX_PERPKT 0x00000100 -#define RX_PERPKTCLR 0x01000000 - -/* Bits in the BCNDMACTL register */ -#define BEACON_READY 0x01 - -/* Bits in the MISCFFCTL register */ -#define MISCFFCTL_WRITE 0x0001 - -/* Bits in WAKEUPEN0 */ -#define WAKEUPEN0_DIRPKT 0x10 -#define WAKEUPEN0_LINKOFF 0x08 -#define WAKEUPEN0_ATIMEN 0x04 -#define WAKEUPEN0_TIMEN 0x02 -#define WAKEUPEN0_MAGICEN 0x01 - -/* Bits in WAKEUPEN1 */ -#define WAKEUPEN1_128_3 0x08 -#define WAKEUPEN1_128_2 0x04 -#define WAKEUPEN1_128_1 0x02 -#define WAKEUPEN1_128_0 0x01 - -/* Bits in WAKEUPSR0 */ -#define WAKEUPSR0_DIRPKT 0x10 -#define WAKEUPSR0_LINKOFF 0x08 -#define WAKEUPSR0_ATIMEN 0x04 -#define WAKEUPSR0_TIMEN 0x02 -#define WAKEUPSR0_MAGICEN 0x01 - -/* Bits in WAKEUPSR1 */ -#define WAKEUPSR1_128_3 0x08 -#define WAKEUPSR1_128_2 0x04 -#define WAKEUPSR1_128_1 0x02 -#define WAKEUPSR1_128_0 0x01 - -/* Bits in the MAC_REG_GPIOCTL register */ -#define GPIO0_MD 0x01 -#define GPIO0_DATA 0x02 -#define GPIO0_INTMD 0x04 -#define GPIO1_MD 0x10 -#define GPIO1_DATA 0x20 - -/* Bits in the MSRCTL register */ -#define MSRCTL_FINISH 0x80 -#define MSRCTL_READY 0x40 -#define MSRCTL_RADARDETECT 0x20 -#define MSRCTL_EN 0x10 -#define MSRCTL_QUIETTXCHK 0x08 -#define MSRCTL_QUIETRPT 0x04 -#define MSRCTL_QUIETINT 0x02 -#define MSRCTL_QUIETEN 0x01 - -/* Bits in the MSRCTL1 register */ -#define MSRCTL1_TXPWR 0x08 -#define MSRCTL1_CSAPAREN 0x04 -#define MSRCTL1_TXPAUSE 0x01 - -/* Loopback mode */ -#define MAC_LB_EXT 0x02 -#define MAC_LB_INTERNAL 0x01 -#define MAC_LB_NONE 0x00 - -#define DEFAULT_BI 0x200 - -/* MiscFIFO Offset */ -#define MISCFIFO_KEYETRY0 32 -#define MISCFIFO_KEYENTRYSIZE 22 -#define MISCFIFO_SYNINFO_IDX 10 -#define MISCFIFO_SYNDATA_IDX 11 -#define MISCFIFO_SYNDATASIZE 21 - -/* enabled mask value of irq */ -#define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \ - IMR_RXDMA1 | \ - IMR_RXNOBUF | \ - IMR_MIBNEARFULL | \ - IMR_SOFTINT | \ - IMR_FETALERR | \ - IMR_WATCHDOG | \ - IMR_SOFTTIMER | \ - IMR_GPIO | \ - IMR_TBTT | \ - IMR_RXDMA0 | \ - IMR_BNTX | \ - IMR_AC0DMA | \ - IMR_TXDMA0) - -/* max time out delay time */ -#define W_MAX_TIMEOUT 0xFFF0U - -/* wait time within loop */ -#define CB_DELAY_LOOP_WAIT 10 /* 10ms */ - -/* revision id */ -#define REV_ID_VT3253_A0 0x00 -#define REV_ID_VT3253_A1 0x01 -#define REV_ID_VT3253_B0 0x08 -#define REV_ID_VT3253_B1 0x09 - -/*--------------------- Export Types ------------------------------*/ - -/*--------------------- Export Macros ------------------------------*/ - -#define VT6655_MAC_SELECT_PAGE0(iobase) iowrite8(0, (iobase) + MAC_REG_PAGE1SEL) - -#define VT6655_MAC_SELECT_PAGE1(iobase) iowrite8(1, (iobase) + MAC_REG_PAGE1SEL) - -#define MAKEWORD(lb, hb) \ - ((unsigned short)(((unsigned char)(lb)) | (((unsigned short)((unsigned char)(hb))) << 8))) - -void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask); -void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask); -void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask); -void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask); - -void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit); - -void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit); - -bool MACbSoftwareReset(struct vnt_private *priv); -bool MACbShutdown(struct vnt_private *priv); -void MACvInitialize(struct vnt_private *priv); -void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr); -void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr); -void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr); -void MACvSetCurrSyncDescAddrEx(struct vnt_private *priv, - u32 curr_desc_addr); -void MACvSetCurrATIMDescAddrEx(struct vnt_private *priv, - u32 curr_desc_addr); -void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay); -void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime); - -void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset, - u32 dwData); - -bool MACbPSWakeup(struct vnt_private *priv); - -void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl, - unsigned int uEntryIdx, unsigned int uKeyIdx, - unsigned char *pbyAddr, u32 *pdwKey, - unsigned char local_id); -void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx); - -#endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c deleted file mode 100644 index 8527ad3eff4862dcd72deeb0d8a4167027105050..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/power.c +++ /dev/null @@ -1,144 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handles 802.11 power management functions - * - * Author: Lyndon Chen - * - * Date: July 17, 2002 - * - * Functions: - * PSvEnablePowerSaving - Enable Power Saving Mode - * PSvDiasblePowerSaving - Disable Power Saving Mode - * PSbConsiderPowerDown - Decide if we can Power Down - * PSvSendPSPOLL - Send PS-POLL packet - * PSbSendNullPacket - Send Null packet - * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon - * - * Revision History: - * - */ - -#include "mac.h" -#include "device.h" -#include "power.h" -#include "card.h" - -/*--------------------- Static Definitions -------------------------*/ - -/*--------------------- Static Classes ----------------------------*/ - -/*--------------------- Static Functions --------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ - -/* - * - * Routine Description: - * Enable hw power saving functions - * - * Return Value: - * None. - * - */ - -void PSvEnablePowerSaving(struct vnt_private *priv, - unsigned short wListenInterval) -{ - u16 wAID = priv->current_aid | BIT(14) | BIT(15); - - /* set period of power up before TBTT */ - iowrite16(C_PWBT, priv->port_offset + MAC_REG_PWBT); - if (priv->op_mode != NL80211_IFTYPE_ADHOC) { - /* set AID */ - iowrite16(wAID, priv->port_offset + MAC_REG_AIDATIM); - } - - /* Set AutoSleep */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - - /* Set HWUTSF */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); - - if (wListenInterval >= 2) { - /* clear always listen beacon */ - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN); - /* first time set listen next beacon */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN); - } else { - /* always listen beacon */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN); - } - - /* enable power saving hw function */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_PSEN); - priv->bEnablePSMode = true; - - priv->bPWBitOn = true; - pr_debug("PS:Power Saving Mode Enable...\n"); -} - -/* - * - * Routine Description: - * Disable hw power saving functions - * - * Return Value: - * None. - * - */ - -void PSvDisablePowerSaving(struct vnt_private *priv) -{ - /* disable power saving hw function */ - MACbPSWakeup(priv); - - /* clear AutoSleep */ - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - - /* clear HWUTSF */ - vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); - - /* set always listen beacon */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN); - - priv->bEnablePSMode = false; - - priv->bPWBitOn = false; -} - -/* - * - * Routine Description: - * Check if Next TBTT must wake up - * - * Return Value: - * None. - * - */ - -bool PSbIsNextTBTTWakeUp(struct vnt_private *priv) -{ - struct ieee80211_hw *hw = priv->hw; - struct ieee80211_conf *conf = &hw->conf; - bool wake_up = false; - - if (conf->listen_interval > 1) { - if (!priv->wake_up_count) - priv->wake_up_count = conf->listen_interval; - - --priv->wake_up_count; - - if (priv->wake_up_count == 1) { - /* Turn on wake up to listen next beacon */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN); - wake_up = true; - } - } - - return wake_up; -} diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h deleted file mode 100644 index 060516f81f5bbd14e8f7a013b7b1bf602a14ffca..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/power.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handles 802.11 power management functions - * - * Author: Lyndon Chen - * - * Date: July 17, 2002 - * - */ - -#ifndef __POWER_H__ -#define __POWER_H__ - -#include "device.h" - -#define C_PWBT 1000 /* micro sec. power up before TBTT */ -#define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */ -#define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */ - -void PSvDisablePowerSaving(struct vnt_private *priv); - -void PSvEnablePowerSaving(struct vnt_private *priv, unsigned short wListenInterval); - -bool PSbIsNextTBTTWakeUp(struct vnt_private *priv); - -#endif /* __POWER_H__ */ diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c deleted file mode 100644 index d319ec21c97b89d45e2f9aed4d05174b3a7aef02..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/rf.c +++ /dev/null @@ -1,535 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: rf function code - * - * Author: Jerry Chen - * - * Date: Feb. 19, 2004 - * - * Functions: - * IFRFbWriteEmbedded - Embedded write RF register via MAC - * - * Revision History: - * RobertYu 2005 - * chester 2008 - * - */ - -#include "mac.h" -#include "srom.h" -#include "rf.h" -#include "baseband.h" - -#define BY_AL2230_REG_LEN 23 /* 24bit */ -#define CB_AL2230_INIT_SEQ 15 -#define SWITCH_CHANNEL_DELAY_AL2230 200 /* us */ -#define AL2230_PWR_IDX_LEN 64 - -#define BY_AL7230_REG_LEN 23 /* 24bit */ -#define CB_AL7230_INIT_SEQ 16 -#define SWITCH_CHANNEL_DELAY_AL7230 200 /* us */ -#define AL7230_PWR_IDX_LEN 64 - -static const unsigned long al2230_init_table[CB_AL2230_INIT_SEQ] = { - 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x01A00200 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x00FFF300 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0F4DC500 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0805B600 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0146C700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x00068800 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0403B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x00DBBA00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0BDFFC00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x00000D00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x00580F00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW -}; - -static const unsigned long al2230_channel_table0[CB_MAX_CHANNEL] = { - 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x03F7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x03E7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ -}; - -static const unsigned long al2230_channel_table1[CB_MAX_CHANNEL] = { - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */ - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */ - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */ - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */ - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */ - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */ - 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */ - 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */ - 0x06666100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */ -}; - -static unsigned long al2230_power_table[AL2230_PWR_IDX_LEN] = { - 0x04040900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04041900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04042900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04043900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04044900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04045900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04046900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04047900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04048900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04049900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0404A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0404B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0404C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0404D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0404E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0404F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04050900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04051900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04052900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04053900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04054900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04055900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04056900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04057900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04058900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04059900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0405A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0405B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0405C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0405D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0405E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0405F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04060900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04061900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04062900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04063900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04064900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04065900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04066900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04067900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04068900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04069900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0406A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0406B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0406C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0406D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0406E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0406F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04070900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04071900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04072900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04073900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04074900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04075900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04076900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04077900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04078900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x04079900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0407A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0407B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0407C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0407D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0407E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, - 0x0407F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW -}; - -/* - * Description: Write to IF/RF, by embedded programming - * - * Parameters: - * In: - * iobase - I/O base address - * dwData - data to write - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData) -{ - void __iomem *iobase = priv->port_offset; - unsigned short ww; - unsigned long dwValue; - - iowrite32((u32)dwData, iobase + MAC_REG_IFREGCTL); - - /* W_MAX_TIMEOUT is the timeout period */ - for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - dwValue = ioread32(iobase + MAC_REG_IFREGCTL); - if (dwValue & IFREGCTL_DONE) - break; - } - - if (ww == W_MAX_TIMEOUT) - return false; - - return true; -} - -/* - * Description: AIROHA IFRF chip init function - * - * Parameters: - * In: - * iobase - I/O base address - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -static bool RFbAL2230Init(struct vnt_private *priv) -{ - void __iomem *iobase = priv->port_offset; - int ii; - bool ret; - - ret = true; - - /* 3-wire control for normal mode */ - iowrite8(0, iobase + MAC_REG_SOFTPWRCTL); - - vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV)); - /* PLL Off */ - vt6655_mac_word_reg_bits_off(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - - /* patch abnormal AL2230 frequency output */ - IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); - - for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) - ret &= IFRFbWriteEmbedded(priv, al2230_init_table[ii]); - MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */ - - /* PLL On */ - vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - - MACvTimer0MicroSDelay(priv, 150);/* 150us */ - ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); - MACvTimer0MicroSDelay(priv, 30);/* 30us */ - ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW)); - MACvTimer0MicroSDelay(priv, 30);/* 30us */ - ret &= IFRFbWriteEmbedded(priv, - al2230_init_table[CB_AL2230_INIT_SEQ - 1]); - - vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | - SOFTPWRCTL_SWPE2 | - SOFTPWRCTL_SWPECTI | - SOFTPWRCTL_TXPEINV)); - - /* 3-wire control for power saving mode */ - iowrite8(PSSIG_WPE3 | PSSIG_WPE2, iobase + MAC_REG_PSPWRSIG); - - return ret; -} - -static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel) -{ - void __iomem *iobase = priv->port_offset; - bool ret; - - ret = true; - - ret &= IFRFbWriteEmbedded(priv, al2230_channel_table0[byChannel - 1]); - ret &= IFRFbWriteEmbedded(priv, al2230_channel_table1[byChannel - 1]); - - /* Set Channel[7] = 0 to tell H/W channel is changing now. */ - iowrite8(byChannel & 0x7F, iobase + MAC_REG_CHANNEL); - MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230); - /* Set Channel[7] = 1 to tell H/W channel change is done. */ - iowrite8(byChannel | 0x80, iobase + MAC_REG_CHANNEL); - - return ret; -} - -/* - * Description: RF init function - * - * Parameters: - * In: - * byBBType - * rf_type - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -bool RFbInit(struct vnt_private *priv) -{ - bool ret = true; - - switch (priv->rf_type) { - case RF_AIROHA: - case RF_AL2230S: - priv->max_pwr_level = AL2230_PWR_IDX_LEN; - ret = RFbAL2230Init(priv); - break; - case RF_NOTHING: - ret = true; - break; - default: - ret = false; - break; - } - return ret; -} - -/* - * Description: Select channel - * - * Parameters: - * In: - * rf_type - * byChannel - Channel number - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -bool RFbSelectChannel(struct vnt_private *priv, unsigned char rf_type, - u16 byChannel) -{ - bool ret = true; - - switch (rf_type) { - case RF_AIROHA: - case RF_AL2230S: - ret = RFbAL2230SelectChannel(priv, byChannel); - break; - /*{{ RobertYu: 20050104 */ - case RF_NOTHING: - ret = true; - break; - default: - ret = false; - break; - } - return ret; -} - -/* - * Description: Write WakeProgSyn - * - * Parameters: - * In: - * priv - Device Structure - * rf_type - RF type - * channel - Channel number - * - * Return Value: true if succeeded; false if failed. - * - */ -bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type, - u16 channel) -{ - void __iomem *iobase = priv->port_offset; - int i; - unsigned char init_count = 0; - unsigned char sleep_count = 0; - unsigned short idx = MISCFIFO_SYNDATA_IDX; - - iowrite16(0, iobase + MAC_REG_MISCFFNDEX); - switch (rf_type) { - case RF_AIROHA: - case RF_AL2230S: - - if (channel > CB_MAX_CHANNEL_24G) - return false; - - /* Init Reg + Channel Reg (2) */ - init_count = CB_AL2230_INIT_SEQ + 2; - sleep_count = 0; - - for (i = 0; i < CB_AL2230_INIT_SEQ; i++) - MACvSetMISCFifo(priv, idx++, al2230_init_table[i]); - - MACvSetMISCFifo(priv, idx++, al2230_channel_table0[channel - 1]); - MACvSetMISCFifo(priv, idx++, al2230_channel_table1[channel - 1]); - break; - - /* Need to check, PLLON need to be low for channel setting */ - - case RF_NOTHING: - return true; - - default: - return false; - } - - MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(sleep_count, init_count)); - - return true; -} - -/* - * Description: Set Tx power - * - * Parameters: - * In: - * iobase - I/O base address - * dwRFPowerTable - RF Tx Power Setting - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH) -{ - bool ret; - unsigned char byPwr = 0; - unsigned char byDec = 0; - - if (priv->dwDiagRefCount != 0) - return true; - - if ((uCH < 1) || (uCH > CB_MAX_CHANNEL)) - return false; - - switch (rate) { - case RATE_1M: - case RATE_2M: - case RATE_5M: - case RATE_11M: - if (uCH > CB_MAX_CHANNEL_24G) - return false; - - byPwr = priv->abyCCKPwrTbl[uCH]; - break; - case RATE_6M: - case RATE_9M: - case RATE_12M: - case RATE_18M: - byPwr = priv->abyOFDMPwrTbl[uCH]; - byDec = byPwr + 10; - - if (byDec >= priv->max_pwr_level) - byDec = priv->max_pwr_level - 1; - - byPwr = byDec; - break; - case RATE_24M: - case RATE_36M: - case RATE_48M: - case RATE_54M: - byPwr = priv->abyOFDMPwrTbl[uCH]; - break; - } - - if (priv->cur_pwr == byPwr) - return true; - - ret = RFbRawSetPower(priv, byPwr, rate); - if (ret) - priv->cur_pwr = byPwr; - - return ret; -} - -/* - * Description: Set Tx power - * - * Parameters: - * In: - * iobase - I/O base address - * dwRFPowerTable - RF Tx Power Setting - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ - -bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr, - unsigned int rate) -{ - bool ret = true; - - if (byPwr >= priv->max_pwr_level) - return false; - - switch (priv->rf_type) { - case RF_AIROHA: - ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]); - if (rate <= RATE_11M) - ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); - else - ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); - - break; - - case RF_AL2230S: - ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]); - if (rate <= RATE_11M) { - ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); - ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); - } else { - ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); - ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW); - } - - break; - - default: - break; - } - return ret; -} - -/* - * - * Routine Description: - * Translate RSSI to dBm - * - * Parameters: - * In: - * priv - The adapter to be translated - * byCurrRSSI - RSSI to be translated - * Out: - * pdwdbm - Translated dbm number - * - * Return Value: none - * - */ -void -RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI, long *pldBm) -{ - unsigned char byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03); - long b = (byCurrRSSI & 0x3F); - long a = 0; - unsigned char abyAIROHARF[4] = {0, 18, 0, 40}; - - switch (priv->rf_type) { - case RF_AIROHA: - case RF_AL2230S: - a = abyAIROHARF[byIdx]; - break; - default: - break; - } - - *pldBm = -1 * (a + b * 2); -} - diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h deleted file mode 100644 index 8eef100c7ef29e9aef650c715e6ca8d037aafbda..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/rf.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: - * - * Author: Jerry Chen - * - * Date: Feb. 19, 2004 - * - */ - -#ifndef __RF_H__ -#define __RF_H__ - -#include "device.h" - -/*--------------------- Export Definitions -------------------------*/ -/* - * Baseband RF pair definition in eeprom (Bits 6..0) - */ -#define RF_RFMD2959 0x01 -#define RF_MAXIMAG 0x02 -#define RF_AIROHA 0x03 - -#define RF_UW2451 0x05 -#define RF_MAXIMG 0x06 -#define RF_MAXIM2829 0x07 /* RobertYu: 20041118 */ -#define RF_UW2452 0x08 /* RobertYu: 20041210 */ -#define RF_AIROHA7230 0x0a /* RobertYu: 20050104 */ -#define RF_UW2453 0x0b - -#define RF_VT3226 0x09 -#define RF_AL2230S 0x0e - -#define RF_NOTHING 0x7E -#define RF_EMU 0x80 -#define RF_MASK 0x7F - -#define ZONE_FCC 0 -#define ZONE_MKK1 1 -#define ZONE_ETSI 2 -#define ZONE_IC 3 -#define ZONE_SPAIN 4 -#define ZONE_FRANCE 5 -#define ZONE_MKK 6 -#define ZONE_ISRAEL 7 - -/* [20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 */ -#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 /* Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 */ -#define CB_UW2452_CHANNEL_5G_HIGH 41 /* [20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 */ - -/*--------------------- Export Classes ----------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ - -bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData); -bool RFbSelectChannel(struct vnt_private *priv, unsigned char rf_type, u16 byChannel); -bool RFbInit(struct vnt_private *priv); -bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type, u16 channel); -bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH); -bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr, - unsigned int rate); - -void RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI, - long *pldBm); - -#endif /* __RF_H__ */ diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c deleted file mode 100644 index 3705cb1e87b635553e18be672c9b35144bcfef64..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/rxtx.c +++ /dev/null @@ -1,1462 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: handle WMAC/802.3/802.11 rx & tx functions - * - * Author: Lyndon Chen - * - * Date: May 20, 2003 - * - * Functions: - * s_vGenerateTxParameter - Generate tx dma required parameter. - * vGenerateMACHeader - Translate 802.3 to 802.11 header - * cbGetFragCount - Calculate fragment number count - * csBeacon_xmit - beacon tx function - * csMgmt_xmit - management tx function - * s_cbFillTxBufHead - fulfill tx dma buffer header - * s_uGetDataDuration - get tx data required duration - * s_uFillDataHead- fulfill tx data duration header - * s_uGetRTSCTSDuration- get rtx/cts required duration - * get_rtscts_time- get rts/cts reserved time - * s_uGetTxRsvTime- get frame reserved time - * s_vFillCTSHead- fulfill CTS ctl header - * s_vFillFragParameter- Set fragment ctl parameter. - * s_vFillRTSHead- fulfill RTS ctl header - * s_vFillTxKey- fulfill tx encrypt key - * s_vSWencryption- Software encrypt header - * vDMA0_tx_80211- tx 802.11 frame via dma0 - * vGenerateFIFOHeader- Generate tx FIFO ctl header - * - * Revision History: - * - */ - -#include "device.h" -#include "rxtx.h" -#include "card.h" -#include "mac.h" -#include "baseband.h" -#include "rf.h" - -/*--------------------- Static Definitions -------------------------*/ - -/*--------------------- Static Classes ----------------------------*/ - -/*--------------------- Static Variables --------------------------*/ - -/*--------------------- Static Functions --------------------------*/ - -/*--------------------- Static Definitions -------------------------*/ -/* if packet size < 256 -> in-direct send - * vpacket size >= 256 -> direct send - */ -#define CRITICAL_PACKET_LEN 256 - -static const unsigned short time_stamp_off[2][MAX_RATE] = { - {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, /* Long Preamble */ - {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, /* Short Preamble */ -}; - -static const unsigned short fb_opt0[2][5] = { - {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, /* fallback_rate0 */ - {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, /* fallback_rate1 */ -}; - -static const unsigned short fb_opt1[2][5] = { - {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */ - {RATE_6M, RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */ -}; - -#define RTSDUR_BB 0 -#define RTSDUR_BA 1 -#define RTSDUR_AA 2 -#define CTSDUR_BA 3 -#define RTSDUR_BA_F0 4 -#define RTSDUR_AA_F0 5 -#define RTSDUR_BA_F1 6 -#define RTSDUR_AA_F1 7 -#define CTSDUR_BA_F0 8 -#define CTSDUR_BA_F1 9 -#define DATADUR_B 10 -#define DATADUR_A 11 -#define DATADUR_A_F0 12 -#define DATADUR_A_F1 13 - -/*--------------------- Static Functions --------------------------*/ -static -void -s_vFillRTSHead( - struct vnt_private *pDevice, - unsigned char byPktType, - void *pvRTS, - unsigned int cbFrameLength, - bool bNeedAck, - bool bDisCRC, - struct ieee80211_hdr *hdr, - unsigned short wCurrentRate, - unsigned char byFBOption -); - -static -void -s_vGenerateTxParameter( - struct vnt_private *pDevice, - unsigned char byPktType, - struct vnt_tx_fifo_head *, - void *pvRrvTime, - void *pvRTS, - void *pvCTS, - unsigned int cbFrameSize, - bool bNeedACK, - unsigned int uDMAIdx, - void *psEthHeader, - unsigned short wCurrentRate -); - -static unsigned int -s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, - unsigned char *pbyTxBufferAddr, - unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD, - unsigned int uNodeIndex); - -static -__le16 -s_uFillDataHead( - struct vnt_private *pDevice, - unsigned char byPktType, - void *pTxDataHead, - unsigned int cbFrameLength, - unsigned int uDMAIdx, - bool bNeedAck, - unsigned int uFragIdx, - unsigned int cbLastFragmentSize, - unsigned int uMACfragNum, - unsigned char byFBOption, - unsigned short wCurrentRate, - bool is_pspoll -); - -/*--------------------- Export Variables --------------------------*/ - -static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate) -{ - return cpu_to_le16(time_stamp_off[priv->preamble_type % 2] - [rate % MAX_RATE]); -} - -/* byPktType : PK_TYPE_11A 0 - * PK_TYPE_11B 1 - * PK_TYPE_11GB 2 - * PK_TYPE_11GA 3 - */ -static -unsigned int -s_uGetTxRsvTime( - struct vnt_private *pDevice, - unsigned char byPktType, - unsigned int cbFrameLength, - unsigned short wRate, - bool bNeedAck -) -{ - unsigned int uDataTime, uAckTime; - - uDataTime = bb_get_frame_time(pDevice->preamble_type, byPktType, cbFrameLength, wRate); - - if (!bNeedAck) - return uDataTime; - - /* - * CCK mode - 11b - * OFDM mode - 11g 2.4G & 11a 5G - */ - uAckTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, - byPktType == PK_TYPE_11B ? - pDevice->byTopCCKBasicRate : - pDevice->byTopOFDMBasicRate); - - return uDataTime + pDevice->uSIFS + uAckTime; -} - -static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type, - u32 frame_length, u16 rate, bool need_ack) -{ - return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type, - frame_length, rate, need_ack)); -} - -/* byFreqType: 0=>5GHZ 1=>2.4GHZ */ -static __le16 get_rtscts_time(struct vnt_private *priv, - unsigned char rts_rsvtype, - unsigned char pkt_type, - unsigned int frame_length, - unsigned short current_rate) -{ - unsigned int rrv_time = 0; - unsigned int rts_time = 0; - unsigned int cts_time = 0; - unsigned int ack_time = 0; - unsigned int data_time = 0; - - data_time = bb_get_frame_time(priv->preamble_type, pkt_type, frame_length, current_rate); - if (rts_rsvtype == 0) { /* RTSTxRrvTime_bb */ - rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate); - ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate); - cts_time = ack_time; - } else if (rts_rsvtype == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */ - rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate); - cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate); - ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate); - } else if (rts_rsvtype == 2) { /* RTSTxRrvTime_aa */ - rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopOFDMBasicRate); - ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate); - cts_time = ack_time; - } else if (rts_rsvtype == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */ - cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate); - ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate); - rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS; - return cpu_to_le16((u16)rrv_time); - } - - /* RTSRrvTime */ - rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS; - return cpu_to_le16((u16)rrv_time); -} - -/* byFreqType 0: 5GHz, 1:2.4Ghz */ -static -unsigned int -s_uGetDataDuration( - struct vnt_private *pDevice, - unsigned char byDurType, - unsigned int cbFrameLength, - unsigned char byPktType, - unsigned short wRate, - bool bNeedAck, - unsigned int uFragIdx, - unsigned int cbLastFragmentSize, - unsigned int uMACfragNum, - unsigned char byFBOption -) -{ - bool bLastFrag = false; - unsigned int uAckTime = 0, uNextPktTime = 0, len; - - if (uFragIdx == (uMACfragNum - 1)) - bLastFrag = true; - - if (uFragIdx == (uMACfragNum - 2)) - len = cbLastFragmentSize; - else - len = cbFrameLength; - - switch (byDurType) { - case DATADUR_B: /* DATADUR_B */ - if (bNeedAck) { - uAckTime = bb_get_frame_time(pDevice->preamble_type, - byPktType, 14, - pDevice->byTopCCKBasicRate); - } - /* Non Frag or Last Frag */ - if ((uMACfragNum == 1) || bLastFrag) { - if (!bNeedAck) - return 0; - } else { - /* First Frag or Mid Frag */ - uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, - len, wRate, bNeedAck); - } - - return pDevice->uSIFS + uAckTime + uNextPktTime; - - case DATADUR_A: /* DATADUR_A */ - if (bNeedAck) { - uAckTime = bb_get_frame_time(pDevice->preamble_type, - byPktType, 14, - pDevice->byTopOFDMBasicRate); - } - /* Non Frag or Last Frag */ - if ((uMACfragNum == 1) || bLastFrag) { - if (!bNeedAck) - return 0; - } else { - /* First Frag or Mid Frag */ - uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, - len, wRate, bNeedAck); - } - - return pDevice->uSIFS + uAckTime + uNextPktTime; - - case DATADUR_A_F0: /* DATADUR_A_F0 */ - case DATADUR_A_F1: /* DATADUR_A_F1 */ - if (bNeedAck) { - uAckTime = bb_get_frame_time(pDevice->preamble_type, - byPktType, 14, - pDevice->byTopOFDMBasicRate); - } - /* Non Frag or Last Frag */ - if ((uMACfragNum == 1) || bLastFrag) { - if (!bNeedAck) - return 0; - } else { - /* First Frag or Mid Frag */ - if (wRate < RATE_18M) - wRate = RATE_18M; - else if (wRate > RATE_54M) - wRate = RATE_54M; - - wRate -= RATE_18M; - - if (byFBOption == AUTO_FB_0) - wRate = fb_opt0[FB_RATE0][wRate]; - else - wRate = fb_opt1[FB_RATE0][wRate]; - - uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType, - len, wRate, bNeedAck); - } - - return pDevice->uSIFS + uAckTime + uNextPktTime; - - default: - break; - } - - return 0; -} - -/* byFreqType: 0=>5GHZ 1=>2.4GHZ */ -static -__le16 -s_uGetRTSCTSDuration( - struct vnt_private *pDevice, - unsigned char byDurType, - unsigned int cbFrameLength, - unsigned char byPktType, - unsigned short wRate, - bool bNeedAck, - unsigned char byFBOption -) -{ - unsigned int uCTSTime = 0, uDurTime = 0; - - switch (byDurType) { - case RTSDUR_BB: /* RTSDuration_bb */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case RTSDUR_BA: /* RTSDuration_ba */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case RTSDUR_AA: /* RTSDuration_aa */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate); - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case CTSDUR_BA: /* CTSDuration_ba */ - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case RTSDUR_BA_F0: /* RTSDuration_ba_f0 */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck); - else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck); - - break; - - case RTSDUR_AA_F0: /* RTSDuration_aa_f0 */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck); - else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck); - - break; - - case RTSDUR_BA_F1: /* RTSDuration_ba_f1 */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck); - else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck); - - break; - - case RTSDUR_AA_F1: /* RTSDuration_aa_f1 */ - uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck); - else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck); - - break; - - case CTSDUR_BA_F0: /* CTSDuration_ba_f0 */ - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck); - else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck); - - break; - - case CTSDUR_BA_F1: /* CTSDuration_ba_f1 */ - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck); - else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M)) - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck); - - break; - - default: - break; - } - - return cpu_to_le16((u16)uDurTime); -} - -static -__le16 -s_uFillDataHead( - struct vnt_private *pDevice, - unsigned char byPktType, - void *pTxDataHead, - unsigned int cbFrameLength, - unsigned int uDMAIdx, - bool bNeedAck, - unsigned int uFragIdx, - unsigned int cbLastFragmentSize, - unsigned int uMACfragNum, - unsigned char byFBOption, - unsigned short wCurrentRate, - bool is_pspoll -) -{ - struct vnt_tx_datahead_ab *buf = pTxDataHead; - - if (!pTxDataHead) - return 0; - - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - /* Auto Fallback */ - struct vnt_tx_datahead_g_fb *buf = pTxDataHead; - - if (byFBOption == AUTO_FB_NONE) { - struct vnt_tx_datahead_g *buf = pTxDataHead; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, - byPktType, &buf->a); - - vnt_get_phy_field(pDevice, cbFrameLength, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->b); - - if (is_pspoll) { - __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15)); - - buf->duration_a = dur; - buf->duration_b = dur; - } else { - /* Get Duration and TimeStamp */ - buf->duration_a = - cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, - byPktType, wCurrentRate, bNeedAck, uFragIdx, - cbLastFragmentSize, uMACfragNum, - byFBOption)); - buf->duration_b = - cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, - PK_TYPE_11B, pDevice->byTopCCKBasicRate, - bNeedAck, uFragIdx, cbLastFragmentSize, - uMACfragNum, byFBOption)); - } - - buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate); - buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate); - - return buf->duration_a; - } - - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, - byPktType, &buf->a); - - vnt_get_phy_field(pDevice, cbFrameLength, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->b); - /* Get Duration and TimeStamp */ - buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B, - pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - buf->duration_a_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - buf->duration_a_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - - buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate); - buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate); - - return buf->duration_a; - /* if (byFBOption == AUTO_FB_NONE) */ - } else if (byPktType == PK_TYPE_11A) { - struct vnt_tx_datahead_ab *buf = pTxDataHead; - - if (byFBOption != AUTO_FB_NONE) { - /* Auto Fallback */ - struct vnt_tx_datahead_a_fb *buf = pTxDataHead; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, - byPktType, &buf->a); - - /* Get Duration and TimeStampOff */ - buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - buf->duration_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - buf->duration_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption)); - buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate); - return buf->duration; - } - - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, - byPktType, &buf->ab); - - if (is_pspoll) { - __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15)); - - buf->duration = dur; - } else { - /* Get Duration and TimeStampOff */ - buf->duration = - cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, - cbLastFragmentSize, uMACfragNum, - byFBOption)); - } - - buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate); - return buf->duration; - } - - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate, - byPktType, &buf->ab); - - if (is_pspoll) { - __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15)); - - buf->duration = dur; - } else { - /* Get Duration and TimeStampOff */ - buf->duration = - cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType, - wCurrentRate, bNeedAck, uFragIdx, - cbLastFragmentSize, uMACfragNum, - byFBOption)); - } - - buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate); - return buf->duration; -} - -static -void -s_vFillRTSHead( - struct vnt_private *pDevice, - unsigned char byPktType, - void *pvRTS, - unsigned int cbFrameLength, - bool bNeedAck, - bool bDisCRC, - struct ieee80211_hdr *hdr, - unsigned short wCurrentRate, - unsigned char byFBOption -) -{ - unsigned int uRTSFrameLen = 20; - - if (!pvRTS) - return; - - if (bDisCRC) { - /* When CRCDIS bit is on, H/W forgot to generate FCS for - * RTS frame, in this case we need to decrease its length by 4. - */ - uRTSFrameLen -= 4; - } - - /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, - * so we don't need to take them into account. - * Otherwise, we need to modify codes for them. - */ - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - if (byFBOption == AUTO_FB_NONE) { - struct vnt_rts_g *buf = pvRTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->b); - - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopOFDMBasicRate, - byPktType, &buf->a); - /* Get Duration */ - buf->duration_bb = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, - cbFrameLength, PK_TYPE_11B, - pDevice->byTopCCKBasicRate, - bNeedAck, byFBOption); - buf->duration_aa = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->duration_ba = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - - buf->data.duration = buf->duration_aa; - /* Get RTS Frame body */ - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_RTS); - - ether_addr_copy(buf->data.ra, hdr->addr1); - ether_addr_copy(buf->data.ta, hdr->addr2); - } else { - struct vnt_rts_g_fb *buf = pvRTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->b); - - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopOFDMBasicRate, - byPktType, &buf->a); - /* Get Duration */ - buf->duration_bb = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, - cbFrameLength, PK_TYPE_11B, - pDevice->byTopCCKBasicRate, - bNeedAck, byFBOption); - buf->duration_aa = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->duration_ba = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->rts_duration_ba_f0 = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->rts_duration_aa_f0 = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->rts_duration_ba_f1 = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->rts_duration_aa_f1 = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->data.duration = buf->duration_aa; - /* Get RTS Frame body */ - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_RTS); - - ether_addr_copy(buf->data.ra, hdr->addr1); - ether_addr_copy(buf->data.ta, hdr->addr2); - } /* if (byFBOption == AUTO_FB_NONE) */ - } else if (byPktType == PK_TYPE_11A) { - if (byFBOption == AUTO_FB_NONE) { - struct vnt_rts_ab *buf = pvRTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopOFDMBasicRate, - byPktType, &buf->ab); - /* Get Duration */ - buf->duration = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->data.duration = buf->duration; - /* Get RTS Frame body */ - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_RTS); - - ether_addr_copy(buf->data.ra, hdr->addr1); - ether_addr_copy(buf->data.ta, hdr->addr2); - } else { - struct vnt_rts_a_fb *buf = pvRTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopOFDMBasicRate, - byPktType, &buf->a); - /* Get Duration */ - buf->duration = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->rts_duration_f0 = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->rts_duration_f1 = - s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - buf->data.duration = buf->duration; - /* Get RTS Frame body */ - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_RTS); - - ether_addr_copy(buf->data.ra, hdr->addr1); - ether_addr_copy(buf->data.ta, hdr->addr2); - } - } else if (byPktType == PK_TYPE_11B) { - struct vnt_rts_ab *buf = pvRTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uRTSFrameLen, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->ab); - /* Get Duration */ - buf->duration = - s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength, - byPktType, wCurrentRate, bNeedAck, - byFBOption); - - buf->data.duration = buf->duration; - /* Get RTS Frame body */ - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); - - ether_addr_copy(buf->data.ra, hdr->addr1); - ether_addr_copy(buf->data.ta, hdr->addr2); - } -} - -static -void -s_vFillCTSHead( - struct vnt_private *pDevice, - unsigned int uDMAIdx, - unsigned char byPktType, - void *pvCTS, - unsigned int cbFrameLength, - bool bNeedAck, - bool bDisCRC, - unsigned short wCurrentRate, - unsigned char byFBOption -) -{ - unsigned int uCTSFrameLen = 14; - - if (!pvCTS) - return; - - if (bDisCRC) { - /* When CRCDIS bit is on, H/W forgot to generate FCS for - * CTS frame, in this case we need to decrease its length by 4. - */ - uCTSFrameLen -= 4; - } - - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) { - /* Auto Fall back */ - struct vnt_cts_fb *buf = pvCTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uCTSFrameLen, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->b); - - buf->duration_ba = - s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - - /* Get CTSDuration_ba_f0 */ - buf->cts_duration_ba_f0 = - s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - - /* Get CTSDuration_ba_f1 */ - buf->cts_duration_ba_f1 = - s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - - /* Get CTS Frame body */ - buf->data.duration = buf->duration_ba; - - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_CTS); - - buf->reserved2 = 0x0; - - ether_addr_copy(buf->data.ra, - pDevice->abyCurrentNetAddr); - } else { /* if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) */ - struct vnt_cts *buf = pvCTS; - /* Get SignalField, ServiceField & Length */ - vnt_get_phy_field(pDevice, uCTSFrameLen, - pDevice->byTopCCKBasicRate, - PK_TYPE_11B, &buf->b); - - /* Get CTSDuration_ba */ - buf->duration_ba = - s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, - cbFrameLength, byPktType, - wCurrentRate, bNeedAck, - byFBOption); - - /* Get CTS Frame body */ - buf->data.duration = buf->duration_ba; - - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_CTS); - - buf->reserved2 = 0x0; - ether_addr_copy(buf->data.ra, - pDevice->abyCurrentNetAddr); - } - } -} - -/* - * - * Description: - * Generate FIFO control for MAC & Baseband controller - * - * Parameters: - * In: - * pDevice - Pointer to adapter - * pTxDataHead - Transmit Data Buffer - * pTxBufHead - pTxBufHead - * pvRrvTime - pvRrvTime - * pvRTS - RTS Buffer - * pCTS - CTS Buffer - * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS) - * bNeedACK - If need ACK - * uDescIdx - Desc Index - * Out: - * none - * - * Return Value: none - * - - - * unsigned int cbFrameSize, Hdr+Payload+FCS - */ -static -void -s_vGenerateTxParameter( - struct vnt_private *pDevice, - unsigned char byPktType, - struct vnt_tx_fifo_head *tx_buffer_head, - void *pvRrvTime, - void *pvRTS, - void *pvCTS, - unsigned int cbFrameSize, - bool bNeedACK, - unsigned int uDMAIdx, - void *psEthHeader, - unsigned short wCurrentRate -) -{ - u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl); - bool bDisCRC = false; - unsigned char byFBOption = AUTO_FB_NONE; - - tx_buffer_head->current_rate = cpu_to_le16(wCurrentRate); - - if (fifo_ctl & FIFOCTL_CRCDIS) - bDisCRC = true; - - if (fifo_ctl & FIFOCTL_AUTO_FB_0) - byFBOption = AUTO_FB_0; - else if (fifo_ctl & FIFOCTL_AUTO_FB_1) - byFBOption = AUTO_FB_1; - - if (!pvRrvTime) - return; - - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - if (pvRTS) { /* RTS_need */ - /* Fill RsvTime */ - struct vnt_rrv_time_rts *buf = pvRrvTime; - - buf->rts_rrv_time_aa = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); - buf->rts_rrv_time_ba = get_rtscts_time(pDevice, 1, byPktType, cbFrameSize, wCurrentRate); - buf->rts_rrv_time_bb = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); - buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); - buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK); - - s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); - } else {/* RTS_needless, PCF mode */ - struct vnt_rrv_time_cts *buf = pvRrvTime; - - buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); - buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK); - buf->cts_rrv_time_ba = get_rtscts_time(pDevice, 3, byPktType, cbFrameSize, wCurrentRate); - - /* Fill CTS */ - s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption); - } - } else if (byPktType == PK_TYPE_11A) { - if (pvRTS) {/* RTS_need, non PCF mode */ - struct vnt_rrv_time_ab *buf = pvRrvTime; - - buf->rts_rrv_time = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); - buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK); - - /* Fill RTS */ - s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); - } else if (!pvRTS) {/* RTS_needless, non PCF mode */ - struct vnt_rrv_time_ab *buf = pvRrvTime; - - buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK); - } - } else if (byPktType == PK_TYPE_11B) { - if (pvRTS) {/* RTS_need, non PCF mode */ - struct vnt_rrv_time_ab *buf = pvRrvTime; - - buf->rts_rrv_time = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); - buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK); - - /* Fill RTS */ - s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption); - } else { /* RTS_needless, non PCF mode */ - struct vnt_rrv_time_ab *buf = pvRrvTime; - - buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK); - } - } -} - -static unsigned int -s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, - unsigned char *pbyTxBufferAddr, - unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD, - unsigned int is_pspoll) -{ - struct vnt_td_info *td_info = pHeadTD->td_info; - struct sk_buff *skb = td_info->skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct vnt_tx_fifo_head *tx_buffer_head = - (struct vnt_tx_fifo_head *)td_info->buf; - u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl); - unsigned int cbFrameSize; - __le16 uDuration; - unsigned char *pbyBuffer; - unsigned int uLength = 0; - unsigned int cbMICHDR = 0; - unsigned int uMACfragNum = 1; - unsigned int uPadding = 0; - unsigned int cbReqCount = 0; - bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK); - bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS); - struct vnt_tx_desc *ptdCurr; - unsigned int cbHeaderLength = 0; - void *pvRrvTime = NULL; - struct vnt_mic_hdr *pMICHDR = NULL; - void *pvRTS = NULL; - void *pvCTS = NULL; - void *pvTxDataHd = NULL; - unsigned short wTxBufSize; /* FFinfo size */ - unsigned char byFBOption = AUTO_FB_NONE; - - cbFrameSize = skb->len + 4; - - if (info->control.hw_key) { - switch (info->control.hw_key->cipher) { - case WLAN_CIPHER_SUITE_CCMP: - cbMICHDR = sizeof(struct vnt_mic_hdr); - break; - default: - break; - } - - cbFrameSize += info->control.hw_key->icv_len; - - if (pDevice->local_id > REV_ID_VT3253_A1) { - /* MAC Header should be padding 0 to DW alignment. */ - uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4); - uPadding %= 4; - } - } - - /* - * Use for AUTO FALL BACK - */ - if (fifo_ctl & FIFOCTL_AUTO_FB_0) - byFBOption = AUTO_FB_0; - else if (fifo_ctl & FIFOCTL_AUTO_FB_1) - byFBOption = AUTO_FB_1; - - /* Set RrvTime/RTS/CTS Buffer */ - wTxBufSize = sizeof(struct vnt_tx_fifo_head); - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */ - - if (byFBOption == AUTO_FB_NONE) { - if (bRTS) {/* RTS_need */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts)); - pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR); - pvCTS = NULL; - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + - cbMICHDR + sizeof(struct vnt_rts_g)); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) + - cbMICHDR + sizeof(struct vnt_rts_g) + - sizeof(struct vnt_tx_datahead_g); - } else { /* RTS_needless */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts)); - pvRTS = NULL; - pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR); - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + - sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts)); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + - cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g); - } - } else { - /* Auto Fall Back */ - if (bRTS) {/* RTS_need */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts)); - pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR); - pvCTS = NULL; - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + - cbMICHDR + sizeof(struct vnt_rts_g_fb)); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) + - cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb); - } else { /* RTS_needless */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts)); - pvRTS = NULL; - pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR); - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + - cbMICHDR + sizeof(struct vnt_cts_fb)); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + - cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb); - } - } /* Auto Fall Back */ - } else {/* 802.11a/b packet */ - - if (byFBOption == AUTO_FB_NONE) { - if (bRTS) { - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); - pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); - pvCTS = NULL; - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + - sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab)); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + - cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab); - } else { /* RTS_needless, need MICHDR */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); - pvRTS = NULL; - pvCTS = NULL; - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + - cbMICHDR + sizeof(struct vnt_tx_datahead_ab); - } - } else { - /* Auto Fall Back */ - if (bRTS) { /* RTS_need */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); - pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); - pvCTS = NULL; - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + - sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb)); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + - cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb); - } else { /* RTS_needless */ - pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); - pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); - pvRTS = NULL; - pvCTS = NULL; - pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); - cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + - cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb); - } - } /* Auto Fall Back */ - } - - td_info->mic_hdr = pMICHDR; - - memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize)); - - /* Fill FIFO,RrvTime,RTS,and CTS */ - s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS, - cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate); - /* Fill DataHead */ - uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, - 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate, is_pspoll); - - hdr->duration_id = uDuration; - - cbReqCount = cbHeaderLength + uPadding + skb->len; - pbyBuffer = (unsigned char *)pHeadTD->td_info->buf; - uLength = cbHeaderLength + uPadding; - - /* Copy the Packet into a tx Buffer */ - memcpy((pbyBuffer + uLength), skb->data, skb->len); - - ptdCurr = pHeadTD; - - ptdCurr->td_info->req_count = (u16)cbReqCount; - - return cbHeaderLength; -} - -static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer, - struct ieee80211_key_conf *tx_key, - struct sk_buff *skb, u16 payload_len, - struct vnt_mic_hdr *mic_hdr) -{ - u64 pn64; - u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb)); - - /* strip header and icv len from payload */ - payload_len -= ieee80211_get_hdrlen_from_skb(skb); - payload_len -= tx_key->icv_len; - - switch (tx_key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - memcpy(key_buffer, iv, 3); - memcpy(key_buffer + 3, tx_key->key, tx_key->keylen); - - if (tx_key->keylen == WLAN_KEY_LEN_WEP40) { - memcpy(key_buffer + 8, iv, 3); - memcpy(key_buffer + 11, - tx_key->key, WLAN_KEY_LEN_WEP40); - } - - break; - case WLAN_CIPHER_SUITE_TKIP: - ieee80211_get_tkip_p2k(tx_key, skb, key_buffer); - - break; - case WLAN_CIPHER_SUITE_CCMP: - - if (!mic_hdr) - return; - - mic_hdr->id = 0x59; - mic_hdr->payload_len = cpu_to_be16(payload_len); - ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2); - - pn64 = atomic64_read(&tx_key->tx_pn); - mic_hdr->ccmp_pn[5] = pn64; - mic_hdr->ccmp_pn[4] = pn64 >> 8; - mic_hdr->ccmp_pn[3] = pn64 >> 16; - mic_hdr->ccmp_pn[2] = pn64 >> 24; - mic_hdr->ccmp_pn[1] = pn64 >> 32; - mic_hdr->ccmp_pn[0] = pn64 >> 40; - - if (ieee80211_has_a4(hdr->frame_control)) - mic_hdr->hlen = cpu_to_be16(28); - else - mic_hdr->hlen = cpu_to_be16(22); - - ether_addr_copy(mic_hdr->addr1, hdr->addr1); - ether_addr_copy(mic_hdr->addr2, hdr->addr2); - ether_addr_copy(mic_hdr->addr3, hdr->addr3); - - mic_hdr->frame_control = cpu_to_le16( - le16_to_cpu(hdr->frame_control) & 0xc78f); - mic_hdr->seq_ctrl = cpu_to_le16( - le16_to_cpu(hdr->seq_ctrl) & 0xf); - - if (ieee80211_has_a4(hdr->frame_control)) - ether_addr_copy(mic_hdr->addr4, hdr->addr4); - - memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP); - - break; - default: - break; - } -} - -int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, - struct vnt_tx_desc *head_td, struct sk_buff *skb) -{ - struct vnt_td_info *td_info = head_td->td_info; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *tx_rate = &info->control.rates[0]; - struct ieee80211_rate *rate; - struct ieee80211_key_conf *tx_key; - struct ieee80211_hdr *hdr; - struct vnt_tx_fifo_head *tx_buffer_head = - (struct vnt_tx_fifo_head *)td_info->buf; - u16 tx_body_size = skb->len, current_rate; - u8 pkt_type; - bool is_pspoll = false; - - memset(tx_buffer_head, 0, sizeof(*tx_buffer_head)); - - hdr = (struct ieee80211_hdr *)(skb->data); - - rate = ieee80211_get_tx_rate(priv->hw, info); - - current_rate = rate->hw_value; - if (priv->wCurrentRate != current_rate && - !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { - priv->wCurrentRate = current_rate; - - RFbSetPower(priv, priv->wCurrentRate, - priv->hw->conf.chandef.chan->hw_value); - } - - if (current_rate > RATE_11M) { - if (info->band == NL80211_BAND_5GHZ) { - pkt_type = PK_TYPE_11A; - } else { - if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - pkt_type = PK_TYPE_11GB; - else - pkt_type = PK_TYPE_11GA; - } - } else { - pkt_type = PK_TYPE_11B; - } - - /*Set fifo controls */ - if (pkt_type == PK_TYPE_11A) - tx_buffer_head->fifo_ctl = 0; - else if (pkt_type == PK_TYPE_11B) - tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B); - else if (pkt_type == PK_TYPE_11GB) - tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB); - else if (pkt_type == PK_TYPE_11GA) - tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA); - - /* generate interrupt */ - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT); - - if (!ieee80211_is_data(hdr->frame_control)) { - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN); - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0); - tx_buffer_head->time_stamp = - cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); - } else { - tx_buffer_head->time_stamp = - cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us); - } - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK); - - if (ieee80211_has_retry(hdr->frame_control)) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY); - - if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - priv->preamble_type = PREAMBLE_SHORT; - else - priv->preamble_type = PREAMBLE_LONG; - - if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS); - - if (ieee80211_has_a4(hdr->frame_control)) { - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD); - priv->bLongHeader = true; - } - - if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) - is_pspoll = true; - - tx_buffer_head->frag_ctl = - cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10); - - if (info->control.hw_key) { - switch (info->control.hw_key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY); - break; - case WLAN_CIPHER_SUITE_TKIP: - tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP); - break; - case WLAN_CIPHER_SUITE_CCMP: - tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES); - break; - default: - break; - } - } - - tx_buffer_head->current_rate = cpu_to_le16(current_rate); - - /* legacy rates TODO use ieee80211_tx_rate */ - if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) { - if (priv->byAutoFBCtrl == AUTO_FB_0) - tx_buffer_head->fifo_ctl |= - cpu_to_le16(FIFOCTL_AUTO_FB_0); - else if (priv->byAutoFBCtrl == AUTO_FB_1) - tx_buffer_head->fifo_ctl |= - cpu_to_le16(FIFOCTL_AUTO_FB_1); - } - - tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG); - - s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head, - dma_idx, head_td, is_pspoll); - - if (info->control.hw_key) { - tx_key = info->control.hw_key; - if (tx_key->keylen > 0) - vnt_fill_txkey(hdr, tx_buffer_head->tx_key, - tx_key, skb, tx_body_size, - td_info->mic_hdr); - } - - return 0; -} - -static int vnt_beacon_xmit(struct vnt_private *priv, - struct sk_buff *skb) -{ - struct vnt_tx_short_buf_head *short_head = - (struct vnt_tx_short_buf_head *)priv->tx_beacon_bufs; - struct ieee80211_mgmt *mgmt_hdr = (struct ieee80211_mgmt *) - (priv->tx_beacon_bufs + sizeof(*short_head)); - struct ieee80211_tx_info *info; - u32 frame_size = skb->len + 4; - u16 current_rate; - - memset(priv->tx_beacon_bufs, 0, sizeof(*short_head)); - - if (priv->byBBType == BB_TYPE_11A) { - current_rate = RATE_6M; - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, frame_size, current_rate, - PK_TYPE_11A, &short_head->ab); - - /* Get Duration and TimeStampOff */ - short_head->duration = - cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B, - frame_size, PK_TYPE_11A, current_rate, - false, 0, 0, 1, AUTO_FB_NONE)); - - short_head->time_stamp_off = - vnt_time_stamp_off(priv, current_rate); - } else { - current_rate = RATE_1M; - short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B); - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, frame_size, current_rate, - PK_TYPE_11B, &short_head->ab); - - /* Get Duration and TimeStampOff */ - short_head->duration = - cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B, - frame_size, PK_TYPE_11B, current_rate, - false, 0, 0, 1, AUTO_FB_NONE)); - - short_head->time_stamp_off = - vnt_time_stamp_off(priv, current_rate); - } - - short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT); - - /* Copy Beacon */ - memcpy(mgmt_hdr, skb->data, skb->len); - - /* time stamp always 0 */ - mgmt_hdr->u.beacon.timestamp = 0; - - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr; - - hdr->duration_id = 0; - hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4); - } - - priv->wSeqCounter++; - if (priv->wSeqCounter > 0x0fff) - priv->wSeqCounter = 0; - - priv->wBCNBufLen = sizeof(*short_head) + skb->len; - - iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR); - - iowrite16(priv->wBCNBufLen, priv->port_offset + MAC_REG_BCNDMACTL + 2); - /* Set auto Transmit on */ - vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX); - /* Poll Transmit the adapter */ - iowrite8(BEACON_READY, priv->port_offset + MAC_REG_BCNDMACTL); - - return 0; -} - -int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif) -{ - struct sk_buff *beacon; - - beacon = ieee80211_beacon_get(priv->hw, vif, 0); - if (!beacon) - return -ENOMEM; - - if (vnt_beacon_xmit(priv, beacon)) { - ieee80211_free_txskb(priv->hw, beacon); - return -ENODEV; - } - - return 0; -} - -int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf) -{ - iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL); - - iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL); - - CARDvSetFirstNextTBTT(priv, conf->beacon_int); - - card_set_beacon_period(priv, conf->beacon_int); - - return vnt_beacon_make(priv, vif); -} diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h deleted file mode 100644 index be1e5180d57b8c6b7462f2c9a12a8901927303e2..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/rxtx.h +++ /dev/null @@ -1,184 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: - * - * Author: Jerry Chen - * - * Date: Jun. 27, 2002 - * - */ - -#ifndef __RXTX_H__ -#define __RXTX_H__ - -#include "device.h" - -#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */ -#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */ - -/*--------------------- Export Definitions -------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ - -/* MIC HDR data header */ -struct vnt_mic_hdr { - u8 id; - u8 tx_priority; - u8 mic_addr2[ETH_ALEN]; - u8 ccmp_pn[IEEE80211_CCMP_PN_LEN]; - __be16 payload_len; - __be16 hlen; - __le16 frame_control; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctrl; - u8 addr4[ETH_ALEN]; - u16 packing; /* packing to 48 bytes */ -} __packed; - -/* RsvTime buffer header */ -struct vnt_rrv_time_rts { - __le16 rts_rrv_time_ba; - __le16 rts_rrv_time_aa; - __le16 rts_rrv_time_bb; - u16 reserved; - __le16 rrv_time_b; - __le16 rrv_time_a; -} __packed; - -struct vnt_rrv_time_cts { - __le16 cts_rrv_time_ba; - u16 reserved; - __le16 rrv_time_b; - __le16 rrv_time_a; -} __packed; - -struct vnt_rrv_time_ab { - __le16 rts_rrv_time; - __le16 rrv_time; -} __packed; - -/* TX data header */ -struct vnt_tx_datahead_g { - struct vnt_phy_field b; - struct vnt_phy_field a; - __le16 duration_b; - __le16 duration_a; - __le16 time_stamp_off_b; - __le16 time_stamp_off_a; -} __packed; - -struct vnt_tx_datahead_g_fb { - struct vnt_phy_field b; - struct vnt_phy_field a; - __le16 duration_b; - __le16 duration_a; - __le16 duration_a_f0; - __le16 duration_a_f1; - __le16 time_stamp_off_b; - __le16 time_stamp_off_a; -} __packed; - -struct vnt_tx_datahead_ab { - struct vnt_phy_field ab; - __le16 duration; - __le16 time_stamp_off; -} __packed; - -struct vnt_tx_datahead_a_fb { - struct vnt_phy_field a; - __le16 duration; - __le16 time_stamp_off; - __le16 duration_f0; - __le16 duration_f1; -} __packed; - -/* RTS buffer header */ -struct vnt_rts_g { - struct vnt_phy_field b; - struct vnt_phy_field a; - __le16 duration_ba; - __le16 duration_aa; - __le16 duration_bb; - u16 reserved; - struct ieee80211_rts data; -} __packed __aligned(2); - -struct vnt_rts_g_fb { - struct vnt_phy_field b; - struct vnt_phy_field a; - __le16 duration_ba; - __le16 duration_aa; - __le16 duration_bb; - u16 wReserved; - __le16 rts_duration_ba_f0; - __le16 rts_duration_aa_f0; - __le16 rts_duration_ba_f1; - __le16 rts_duration_aa_f1; - struct ieee80211_rts data; -} __packed __aligned(2); - -struct vnt_rts_ab { - struct vnt_phy_field ab; - __le16 duration; - u16 reserved; - struct ieee80211_rts data; -} __packed __aligned(2); - -struct vnt_rts_a_fb { - struct vnt_phy_field a; - __le16 duration; - u16 reserved; - __le16 rts_duration_f0; - __le16 rts_duration_f1; - struct ieee80211_rts data; -} __packed __aligned(2); - -/* CTS buffer header */ -struct vnt_cts { - struct vnt_phy_field b; - __le16 duration_ba; - u16 reserved; - struct ieee80211_cts data; - u16 reserved2; -} __packed __aligned(2); - -struct vnt_cts_fb { - struct vnt_phy_field b; - __le16 duration_ba; - u16 reserved; - __le16 cts_duration_ba_f0; - __le16 cts_duration_ba_f1; - struct ieee80211_cts data; - u16 reserved2; -} __packed __aligned(2); - -struct vnt_tx_fifo_head { - u8 tx_key[WLAN_KEY_LEN_CCMP]; - __le16 fifo_ctl; - __le16 time_stamp; - __le16 frag_ctl; - __le16 current_rate; -} __packed; - -struct vnt_tx_short_buf_head { - __le16 fifo_ctl; - u16 time_stamp; - struct vnt_phy_field ab; - __le16 duration; - __le16 time_stamp_off; -} __packed; - -int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, - struct vnt_tx_desc *head_td, struct sk_buff *skb); -int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif); -int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf); - -#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c deleted file mode 100644 index e80556509c58dde01addf6750044405fd3c960d8..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/srom.c +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose:Implement functions to access eeprom - * - * Author: Jerry Chen - * - * Date: Jan 29, 2003 - * - * Functions: - * SROMbyReadEmbedded - Embedded read eeprom via MAC - * SROMbWriteEmbedded - Embedded write eeprom via MAC - * SROMvRegBitsOn - Set Bits On in eeprom - * SROMvRegBitsOff - Clear Bits Off in eeprom - * SROMbIsRegBitsOn - Test if Bits On in eeprom - * SROMbIsRegBitsOff - Test if Bits Off in eeprom - * SROMvReadAllContents - Read all contents in eeprom - * SROMvWriteAllContents - Write all contents in eeprom - * SROMvReadEtherAddress - Read Ethernet Address in eeprom - * SROMvWriteEtherAddress - Write Ethernet Address in eeprom - * SROMvReadSubSysVenId - Read Sub_VID and Sub_SysId in eeprom - * SROMbAutoLoad - Auto Load eeprom to MAC register - * - * Revision History: - * - */ - -#include "device.h" -#include "mac.h" -#include "srom.h" - -/*--------------------- Static Definitions -------------------------*/ - -/*--------------------- Static Classes ----------------------------*/ - -/*--------------------- Static Variables --------------------------*/ - -/*--------------------- Static Functions --------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ - -/* - * Description: Read a byte from EEPROM, by MAC I2C - * - * Parameters: - * In: - * iobase - I/O base address - * contnt_offset - address of EEPROM - * Out: - * none - * - * Return Value: data read - * - */ -unsigned char SROMbyReadEmbedded(void __iomem *iobase, - unsigned char contnt_offset) -{ - unsigned short wDelay, wNoACK; - unsigned char byWait; - unsigned char byData; - unsigned char byOrg; - - byOrg = ioread8(iobase + MAC_REG_I2MCFG); - /* turn off hardware retry for getting NACK */ - iowrite8(byOrg & (~I2MCFG_NORETRY), iobase + MAC_REG_I2MCFG); - for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) { - iowrite8(EEP_I2C_DEV_ID, iobase + MAC_REG_I2MTGID); - iowrite8(contnt_offset, iobase + MAC_REG_I2MTGAD); - - /* issue read command */ - iowrite8(I2MCSR_EEMR, iobase + MAC_REG_I2MCSR); - /* wait DONE be set */ - for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) { - byWait = ioread8(iobase + MAC_REG_I2MCSR); - if (byWait & (I2MCSR_DONE | I2MCSR_NACK)) - break; - udelay(CB_DELAY_LOOP_WAIT); - } - if ((wDelay < W_MAX_TIMEOUT) && - (!(byWait & I2MCSR_NACK))) { - break; - } - } - byData = ioread8(iobase + MAC_REG_I2MDIPT); - iowrite8(byOrg, iobase + MAC_REG_I2MCFG); - return byData; -} - -/* - * Description: Read all contents of eeprom to buffer - * - * Parameters: - * In: - * iobase - I/O base address - * Out: - * pbyEepromRegs - EEPROM content Buffer - * - * Return Value: none - * - */ -void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs) -{ - int ii; - - /* ii = Rom Address */ - for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) { - *pbyEepromRegs = SROMbyReadEmbedded(iobase, - (unsigned char)ii); - pbyEepromRegs++; - } -} - -/* - * Description: Read Ethernet Address from eeprom to buffer - * - * Parameters: - * In: - * iobase - I/O base address - * Out: - * pbyEtherAddress - Ethernet Address buffer - * - * Return Value: none - * - */ -void SROMvReadEtherAddress(void __iomem *iobase, - unsigned char *pbyEtherAddress) -{ - unsigned char ii; - - /* ii = Rom Address */ - for (ii = 0; ii < ETH_ALEN; ii++) { - *pbyEtherAddress = SROMbyReadEmbedded(iobase, ii); - pbyEtherAddress++; - } -} diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h deleted file mode 100644 index b03073ffa18a2e07776b127ef91f2f1e94d64e56..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/srom.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions to access eeprom - * - * Author: Jerry Chen - * - * Date: Jan 29, 2003 - */ - -#ifndef __SROM_H__ -#define __SROM_H__ - -/*--------------------- Export Definitions -------------------------*/ - -#define EEP_MAX_CONTEXT_SIZE 256 - -#define CB_EEPROM_READBYTE_WAIT 900 /* us */ - -#define W_MAX_I2CRETRY 0x0fff - -/* Contents in the EEPROM */ -#define EEP_OFS_PAR 0x00 /* physical address */ -#define EEP_OFS_ANTENNA 0x16 -#define EEP_OFS_RADIOCTL 0x17 -#define EEP_OFS_RFTYPE 0x1B /* for select RF */ -#define EEP_OFS_MINCHANNEL 0x1C /* Min Channel # */ -#define EEP_OFS_MAXCHANNEL 0x1D /* Max Channel # */ -#define EEP_OFS_SIGNATURE 0x1E -#define EEP_OFS_ZONETYPE 0x1F -#define EEP_OFS_RFTABLE 0x20 /* RF POWER TABLE */ -#define EEP_OFS_PWR_CCK 0x20 -#define EEP_OFS_SETPT_CCK 0x21 -#define EEP_OFS_PWR_OFDMG 0x23 -#define EEP_OFS_SETPT_OFDMG 0x24 -#define EEP_OFS_PWR_FORMULA_OST 0x26 -#define EEP_OFS_MAJOR_VER 0x2E -#define EEP_OFS_MINOR_VER 0x2F -#define EEP_OFS_CCK_PWR_TBL 0x30 -#define EEP_OFS_CCK_PWR_dBm 0x3F -#define EEP_OFS_OFDM_PWR_TBL 0x40 -#define EEP_OFS_OFDM_PWR_dBm 0x4F -/*{{ RobertYu: 20041124 */ -#define EEP_OFS_SETPT_OFDMA 0x4E -#define EEP_OFS_OFDMA_PWR_TBL 0x50 -/*}}*/ -#define EEP_OFS_OFDMA_PWR_dBm 0xD2 - -/*----------need to remove --------------------*/ -#define EEP_OFS_BBTAB_LEN 0x70 /* BB Table Length */ -#define EEP_OFS_BBTAB_ADR 0x71 /* BB Table Offset */ -#define EEP_OFS_CHECKSUM 0xFF /* reserved area for baseband 28h~78h */ - -#define EEP_I2C_DEV_ID 0x50 /* EEPROM device address on I2C bus */ - -/* Bits in EEP_OFS_ANTENNA */ -#define EEP_ANTENNA_MAIN 0x01 -#define EEP_ANTENNA_AUX 0x02 -#define EEP_ANTINV 0x04 - -/* Bits in EEP_OFS_RADIOCTL */ -#define EEP_RADIOCTL_ENABLE 0x80 -#define EEP_RADIOCTL_INV 0x01 - -/*--------------------- Export Types ------------------------------*/ - -/*--------------------- Export Macros ------------------------------*/ - -/*--------------------- Export Classes ----------------------------*/ - -/*--------------------- Export Variables --------------------------*/ - -/*--------------------- Export Functions --------------------------*/ - -unsigned char SROMbyReadEmbedded(void __iomem *iobase, - unsigned char byContntOffset); - -void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs); - -void SROMvReadEtherAddress(void __iomem *iobase, - unsigned char *pbyEtherAddress); - -#endif /* __EEPROM_H__*/ diff --git a/drivers/staging/vt6655/test b/drivers/staging/vt6655/test deleted file mode 100644 index ba6dec774478e9d57321d07983ad1884bb29078e..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6655/test +++ /dev/null @@ -1,9 +0,0 @@ -KSP := /lib/modules/$(shell uname -r)/build \ - /usr/src/linux-$(shell uname -r) \ - /usr/src/linux-$(shell uname -r | sed 's/-.*//') \ -# /usr/src/kernel-headers-$(shell uname -r) \ -# /usr/src/kernel-source-$(shell uname -r) \ -# /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \ -# /usr/src/linux /home/plice -test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir)) -KSP := $(foreach dir, $(KSP), $(test_dir)) diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig deleted file mode 100644 index f52a3f1d9a2ee294cb5a511b788bbf58d6117ca9..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config VT6656 - tristate "VIA Technologies VT6656 support" - depends on MAC80211 && USB && WLAN && m - select FW_LOADER - help - This is a vendor-written driver for VIA VT6656. diff --git a/drivers/staging/vt6656/Makefile b/drivers/staging/vt6656/Makefile deleted file mode 100644 index f696a9d7a143d42dfa4821c42d6b6bfff523e1f7..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -vt6656_stage-y += main_usb.o \ - card.o \ - mac.o \ - baseband.o \ - wcmd.o\ - rxtx.o \ - power.o \ - key.o \ - rf.o \ - usbpipe.o \ - channel.o - -obj-$(CONFIG_VT6656) += vt6656_stage.o diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO deleted file mode 100644 index cca78d2d3cfeb5bbf46ffb548336b51c89175639..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/TODO +++ /dev/null @@ -1,17 +0,0 @@ -TODO: -- remove __cplusplus ifdefs -- done -- remove kernel version compatibility wrappers -- remove support for older wireless extensions -- prepare for merge with vt6655 driver: - - remove PRINT_K() macro - - split rf.c - - abstract VT3184 chipset specific code -- add common vt665x infrastructure -- kill ttype.h -- done -- switch to use MAC80211 -- use kernel coding style -- sparse fixes -- integrate with drivers/net/wireless - -Please send any patches to Greg Kroah-Hartman <greg@kroah.com> -and Forest Bond <forest@alittletooquiet.net>. diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c deleted file mode 100644 index ad7b963f0d981afd6a6926089f567feb16392ca4..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/baseband.c +++ /dev/null @@ -1,455 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions to access baseband - * - * Author: Jerry Chen - * - * Date: Jun. 5, 2002 - * - * Functions: - * vnt_get_frame_time - Calculate data frame transmitting time - * vnt_get_phy_field - Calculate PhyLength, PhyService and Phy - * Signal parameter for baseband Tx - * vnt_vt3184_init - VIA VT3184 baseband chip init code - * - * Revision History: - * - * - */ - -#include <linux/bits.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include "device.h" -#include "mac.h" -#include "baseband.h" -#include "rf.h" -#include "usbpipe.h" - -static const u8 vnt_vt3184_agc[] = { - 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06, - 0x08, 0x08, 0x0a, 0x0a, 0x0c, 0x0c, 0x0e, 0x0e, /* 0x0f */ - 0x10, 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, - 0x18, 0x18, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x1e, /* 0x1f */ - 0x20, 0x20, 0x22, 0x22, 0x24, 0x24, 0x26, 0x26, - 0x28, 0x28, 0x2a, 0x2a, 0x2c, 0x2c, 0x2e, 0x2e, /* 0x2f */ - 0x30, 0x30, 0x32, 0x32, 0x34, 0x34, 0x36, 0x36, - 0x38, 0x38, 0x3a, 0x3a, 0x3c, 0x3c, 0x3e, 0x3e /* 0x3f */ -}; - -static u8 vnt_vt3184_al2230[] = { - 0x31, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x70, 0x45, 0x2a, 0x76, 0x00, 0x00, 0x80, 0x00, /* 0x0f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8e, 0x0a, 0x00, 0x00, 0x00, /* 0x1f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x0c, /* 0x2f */ - 0x26, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, - 0xff, 0xff, 0x79, 0x00, 0x00, 0x0b, 0x48, 0x04, /* 0x3f */ - 0x00, 0x08, 0x00, 0x08, 0x08, 0x14, 0x05, 0x09, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x73, 0x00, 0xc5, /* 0x4f */ - 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f */ - 0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* 0x6f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7f */ - 0x8c, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x1f, 0xb7, 0x88, 0x47, 0xaa, 0x00, /* 0x8f */ - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x18, /* 0xaf */ - 0x38, 0x30, 0x00, 0x00, 0xff, 0x0f, 0xe4, 0xe2, - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, /* 0xbf */ - 0x18, 0x20, 0x07, 0x18, 0xff, 0xff, 0x0e, 0x0a, - 0x0e, 0x00, 0x82, 0xa7, 0x3c, 0x10, 0x30, 0x05, /* 0xcf */ - 0x40, 0x12, 0x00, 0x00, 0x10, 0x28, 0x80, 0x2a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf */ - 0x00, 0xf3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x12, - 0x00, 0xf4, 0x00, 0xff, 0x79, 0x20, 0x30, 0x05, /* 0xef */ - 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xff */ -}; - -/* {{RobertYu:20060515, new BB setting for VT3226D0 */ -static const u8 vnt_vt3184_vt3226d0[] = { - 0x31, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x70, 0x45, 0x2a, 0x76, 0x00, 0x00, 0x80, 0x00, /* 0x0f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8e, 0x0a, 0x00, 0x00, 0x00, /* 0x1f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x0c, /* 0x2f */ - 0x26, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, - 0xff, 0xff, 0x79, 0x00, 0x00, 0x0b, 0x48, 0x04, /* 0x3f */ - 0x00, 0x08, 0x00, 0x08, 0x08, 0x14, 0x05, 0x09, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x73, 0x00, 0xc5, /* 0x4f */ - 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f */ - 0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* 0x6f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7f */ - 0x8c, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x1f, 0xb7, 0x88, 0x47, 0xaa, 0x00, /* 0x8f */ - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, /* 0xaf */ - 0x38, 0x30, 0x00, 0x00, 0xff, 0x0f, 0xe4, 0xe2, - 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, /* 0xbf */ - 0x18, 0x20, 0x07, 0x18, 0xff, 0xff, 0x10, 0x0a, - 0x0e, 0x00, 0x84, 0xa7, 0x3c, 0x10, 0x24, 0x05, /* 0xcf */ - 0x40, 0x12, 0x00, 0x00, 0x10, 0x28, 0x80, 0x2a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf */ - 0x00, 0xf3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, - 0x00, 0xf4, 0x00, 0xff, 0x79, 0x20, 0x30, 0x08, /* 0xef */ - 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xff */ -}; - -struct vnt_threshold { - u8 bb_pre_ed_rssi; - u8 cr_201; - u8 cr_206; -}; - -static const struct vnt_threshold al2230_vnt_threshold[] = { - {0, 0x00, 0x30}, /* Max sensitivity */ - {68, 0x00, 0x36}, - {67, 0x00, 0x43}, - {66, 0x00, 0x51}, - {65, 0x00, 0x62}, - {64, 0x00, 0x79}, - {63, 0x00, 0x93}, - {62, 0x00, 0xb9}, - {61, 0x00, 0xe3}, - {60, 0x01, 0x18}, - {59, 0x01, 0x54}, - {58, 0x01, 0xa0}, - {57, 0x02, 0x20}, - {56, 0x02, 0xa0}, - {55, 0x03, 0x00}, - {53, 0x06, 0x00}, - {51, 0x09, 0x00}, - {49, 0x0e, 0x00}, - {47, 0x15, 0x00}, - {46, 0x1a, 0x00}, - {45, 0xff, 0x00} -}; - -static const struct vnt_threshold vt3226_vnt_threshold[] = { - {0, 0x00, 0x24}, /* Max sensitivity */ - {68, 0x00, 0x2d}, - {67, 0x00, 0x36}, - {66, 0x00, 0x43}, - {65, 0x00, 0x52}, - {64, 0x00, 0x68}, - {63, 0x00, 0x80}, - {62, 0x00, 0x9c}, - {61, 0x00, 0xc0}, - {60, 0x00, 0xea}, - {59, 0x01, 0x30}, - {58, 0x01, 0x70}, - {57, 0x01, 0xb0}, - {56, 0x02, 0x30}, - {55, 0x02, 0xc0}, - {53, 0x04, 0x00}, - {51, 0x07, 0x00}, - {49, 0x0a, 0x00}, - {47, 0x11, 0x00}, - {45, 0x18, 0x00}, - {43, 0x26, 0x00}, - {42, 0x36, 0x00}, - {41, 0xff, 0x00} -}; - -/* - * Description: Set Antenna mode - * - * Parameters: - * In: - * priv - Device Structure - * antenna_mode - Antenna Mode - * Out: - * none - * - * Return Value: none - * - */ -int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode) -{ - switch (antenna_mode) { - case ANT_TXA: - case ANT_TXB: - break; - case ANT_RXA: - priv->bb_rx_conf &= 0xFC; - break; - case ANT_RXB: - priv->bb_rx_conf &= 0xFE; - priv->bb_rx_conf |= 0x02; - break; - } - - return vnt_control_out(priv, MESSAGE_TYPE_SET_ANTMD, - (u16)antenna_mode, 0, 0, NULL); -} - -/* - * Description: Set Antenna mode - * - * Parameters: - * In: - * pDevice - Device Structure - * byAntennaMode - Antenna Mode - * Out: - * none - * - * Return Value: none - * - */ - -int vnt_vt3184_init(struct vnt_private *priv) -{ - int ret; - u16 length; - u8 *addr = NULL; - const u8 *c_addr; - u8 data; - - ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0, MESSAGE_REQUEST_EEPROM, - EEP_MAX_CONTEXT_SIZE, priv->eeprom); - if (ret) - goto end; - - priv->rf_type = priv->eeprom[EEP_OFS_RFTYPE]; - - dev_dbg(&priv->usb->dev, "RF Type %d\n", priv->rf_type); - - if ((priv->rf_type == RF_AL2230) || - (priv->rf_type == RF_AL2230S)) { - priv->bb_rx_conf = vnt_vt3184_al2230[10]; - length = sizeof(vnt_vt3184_al2230); - addr = vnt_vt3184_al2230; - - priv->bb_vga[0] = 0x1c; - priv->bb_vga[1] = 0x10; - priv->bb_vga[2] = 0x0; - priv->bb_vga[3] = 0x0; - - } else if ((priv->rf_type == RF_VT3226) || - (priv->rf_type == RF_VT3226D0)) { - priv->bb_rx_conf = vnt_vt3184_vt3226d0[10]; - length = sizeof(vnt_vt3184_vt3226d0); - c_addr = vnt_vt3184_vt3226d0; - - priv->bb_vga[0] = 0x20; - priv->bb_vga[1] = 0x10; - priv->bb_vga[2] = 0x0; - priv->bb_vga[3] = 0x0; - - /* Fix VT3226 DFC system timing issue */ - ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2, - SOFTPWRCTL_RFLEOPT); - if (ret) - goto end; - } else { - goto end; - } - - if (addr) - c_addr = addr; - - ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, - MESSAGE_REQUEST_BBREG, length, c_addr); - if (ret) - goto end; - - ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0, - MESSAGE_REQUEST_BBAGC, - sizeof(vnt_vt3184_agc), vnt_vt3184_agc); - if (ret) - goto end; - - if ((priv->rf_type == RF_VT3226) || - (priv->rf_type == RF_VT3226D0)) { - data = (priv->rf_type == RF_VT3226D0) ? 0x11 : 0x23; - - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, - MAC_REG_ITRTMSET, data); - if (ret) - goto end; - - ret = vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, BIT(0)); - if (ret) - goto end; - } - - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x04, 0x7f); - if (ret) - goto end; - - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01); - if (ret) - goto end; - - ret = vnt_rf_table_download(priv); - if (ret) - goto end; - - /* Fix for TX USB resets from vendors driver */ - ret = vnt_control_in(priv, MESSAGE_TYPE_READ, USB_REG4, - MESSAGE_REQUEST_MEM, sizeof(data), &data); - if (ret) - goto end; - - data |= 0x2; - - ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, USB_REG4, - MESSAGE_REQUEST_MEM, sizeof(data), &data); - -end: - return ret; -} - -/* - * Description: Set ShortSlotTime mode - * - * Parameters: - * In: - * priv - Device Structure - * Out: - * none - * - * Return Value: none - * - */ -int vnt_set_short_slot_time(struct vnt_private *priv) -{ - int ret = 0; - u8 bb_vga = 0; - - if (priv->short_slot_time) - priv->bb_rx_conf &= 0xdf; - else - priv->bb_rx_conf |= 0x20; - - ret = vnt_control_in_u8(priv, MESSAGE_REQUEST_BBREG, 0xe7, &bb_vga); - if (ret) - return ret; - - if (bb_vga == priv->bb_vga[0]) - priv->bb_rx_conf |= 0x20; - - return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a, - priv->bb_rx_conf); -} - -int vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data) -{ - int ret; - - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xE7, data); - if (ret) - return ret; - - /* patch for 3253B0 Baseband with Cardbus module */ - if (priv->short_slot_time) - priv->bb_rx_conf &= 0xdf; /* 1101 1111 */ - else - priv->bb_rx_conf |= 0x20; /* 0010 0000 */ - - return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a, - priv->bb_rx_conf); -} - -/* - * Description: vnt_set_deep_sleep - * - * Parameters: - * In: - * priv - Device Structure - * Out: - * none - * - * Return Value: none - * - */ -int vnt_set_deep_sleep(struct vnt_private *priv) -{ - int ret = 0; - - /* CR12 */ - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x17); - if (ret) - return ret; - - /* CR13 */ - return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0xB9); -} - -int vnt_exit_deep_sleep(struct vnt_private *priv) -{ - int ret = 0; - - /* CR12 */ - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x00); - if (ret) - return ret; - - /* CR13 */ - return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01); -} - -int vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning) -{ - const struct vnt_threshold *threshold = NULL; - u8 length; - u8 cr_201, cr_206; - u8 ed_inx; - int ret; - - switch (priv->rf_type) { - case RF_AL2230: - case RF_AL2230S: - threshold = al2230_vnt_threshold; - length = ARRAY_SIZE(al2230_vnt_threshold); - break; - - case RF_VT3226: - case RF_VT3226D0: - threshold = vt3226_vnt_threshold; - length = ARRAY_SIZE(vt3226_vnt_threshold); - break; - } - - if (!threshold) - return -EINVAL; - - for (ed_inx = scanning ? 0 : length - 1; ed_inx > 0; ed_inx--) { - if (priv->bb_pre_ed_rssi <= threshold[ed_inx].bb_pre_ed_rssi) - break; - } - - cr_201 = threshold[ed_inx].cr_201; - cr_206 = threshold[ed_inx].cr_206; - - if (ed_inx == priv->bb_pre_ed_index && !scanning) - return 0; - - priv->bb_pre_ed_index = ed_inx; - - dev_dbg(&priv->usb->dev, "%s bb_pre_ed_rssi %d\n", - __func__, priv->bb_pre_ed_rssi); - - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xc9, cr_201); - if (ret) - return ret; - - return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xce, cr_206); -} - diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h deleted file mode 100644 index dce50a311f24387409ebc7178042a4d31a7861d4..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/baseband.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions to access baseband - * - * Author: Jerry Chen - * - * Date: Jun. 5, 2002 - * - * Revision History: - * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-26-2003 Kyle Hsu : Add defines of packet type and TX rate. - */ - -#ifndef __BASEBAND_H__ -#define __BASEBAND_H__ - -#include "device.h" - -#define PREAMBLE_LONG 0 -#define PREAMBLE_SHORT 1 - -/* - * Registers in the BASEBAND - */ -#define BB_MAX_CONTEXT_SIZE 256 - -#define C_SIFS_A 16 /* usec */ -#define C_SIFS_BG 10 - -#define C_EIFS 80 /* usec */ - -#define C_SLOT_SHORT 9 /* usec */ -#define C_SLOT_LONG 20 - -#define C_CWMIN_A 15 /* slot time */ -#define C_CWMIN_B 31 - -#define C_CWMAX 1023 /* slot time */ - -/* 0:11A 1:11B 2:11G */ -#define BB_TYPE_11A 0 -#define BB_TYPE_11B 1 -#define BB_TYPE_11G 2 - -/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */ -#define PK_TYPE_11A 0 -#define PK_TYPE_11B 1 -#define PK_TYPE_11GB 2 -#define PK_TYPE_11GA 3 - -#define TOP_RATE_54M 0x80000000 -#define TOP_RATE_48M 0x40000000 -#define TOP_RATE_36M 0x20000000 -#define TOP_RATE_24M 0x10000000 -#define TOP_RATE_18M 0x08000000 -#define TOP_RATE_12M 0x04000000 -#define TOP_RATE_11M 0x02000000 -#define TOP_RATE_9M 0x01000000 -#define TOP_RATE_6M 0x00800000 -#define TOP_RATE_55M 0x00400000 -#define TOP_RATE_2M 0x00200000 -#define TOP_RATE_1M 0x00100000 - -int vnt_set_short_slot_time(struct vnt_private *priv); -int vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data); -int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode); -int vnt_vt3184_init(struct vnt_private *priv); -int vnt_set_deep_sleep(struct vnt_private *priv); -int vnt_exit_deep_sleep(struct vnt_private *priv); -int vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning); - -#endif /* __BASEBAND_H__ */ diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c deleted file mode 100644 index b9dc0d13c00c85234302ffb231c522883872f9e4..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/card.c +++ /dev/null @@ -1,456 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Provide functions to setup NIC operation mode - * Functions: - * vnt_set_rspinf - Set RSPINF - * vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS - * vnt_update_top_rates - Update BasicTopRate - * vnt_add_basic_rate - Add to BasicRateSet - * vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet - * vnt_get_tsf_offset - Calculate TSFOffset - * vnt_get_next_tbtt - Calculate Next Beacon TSF counter - * vnt_reset_next_tbtt - Set NIC Beacon time - * vnt_update_next_tbtt - Sync. NIC Beacon time - * vnt_radio_power_off - Turn Off NIC Radio Power - * vnt_radio_power_on - Turn On NIC Radio Power - * - * Revision History: - * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase. - * 09-01-2003 Bryan YC Fan: Add vnt_update_ifs(). - * - */ - -#include <linux/bitops.h> -#include <linux/errno.h> -#include "device.h" -#include "card.h" -#include "baseband.h" -#include "mac.h" -#include "desc.h" -#include "rf.h" -#include "power.h" -#include "key.h" -#include "usbpipe.h" - -/* const u16 cw_rxbcntsf_off[MAX_RATE] = - * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3}; - */ - -static const u16 cw_rxbcntsf_off[MAX_RATE] = { - 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3 -}; - -int vnt_set_channel(struct vnt_private *priv, u32 connection_channel) -{ - int ret; - - if (connection_channel > CB_MAX_CHANNEL || !connection_channel) - return -EINVAL; - - /* clear NAV */ - vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV); - - /* Set Channel[7] = 0 to tell H/W channel is changing now. */ - vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, - (BIT(7) | BIT(5) | BIT(4))); - - ret = vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, - connection_channel, 0, 0, NULL); - if (ret) - return ret; - - return vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, - (u8)(connection_channel | 0x80)); -} - -static const u8 vnt_rspinf_b_short_table[] = { - 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x09, 0x00, - 0x15, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x80 -}; - -static const u8 vnt_rspinf_b_long_table[] = { - 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00, - 0x15, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x80 -}; - -static const u8 vnt_rspinf_a_table[] = { - 0x9b, 0x18, 0x9f, 0x10, 0x9a, 0x0a, 0x9e, 0x08, 0x99, - 0x08, 0x9d, 0x04, 0x98, 0x04, 0x9c, 0x04, 0x9c, 0x04 -}; - -static const u8 vnt_rspinf_gb_table[] = { - 0x8b, 0x1e, 0x8f, 0x16, 0x8a, 0x12, 0x8e, 0x0e, 0x89, - 0x0e, 0x8d, 0x0a, 0x88, 0x0a, 0x8c, 0x0a, 0x8c, 0x0a -}; - -int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type) -{ - const u8 *data; - u16 len; - int ret; - - if (priv->preamble_type) { - data = vnt_rspinf_b_short_table; - len = ARRAY_SIZE(vnt_rspinf_b_short_table); - } else { - data = vnt_rspinf_b_long_table; - len = ARRAY_SIZE(vnt_rspinf_b_long_table); - } - - /* RSPINF_b_1 to RSPINF_b_11 */ - ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1, - MESSAGE_REQUEST_MACREG, len, data); - if (ret) - return ret; - - if (bb_type == BB_TYPE_11A) { - data = vnt_rspinf_a_table; - len = ARRAY_SIZE(vnt_rspinf_a_table); - } else { - data = vnt_rspinf_gb_table; - len = ARRAY_SIZE(vnt_rspinf_gb_table); - } - - /* RSPINF_a_6 to RSPINF_a_72 */ - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_A_6, - MESSAGE_REQUEST_MACREG, len, data); -} - -int vnt_update_ifs(struct vnt_private *priv) -{ - u8 max_min = 0; - u8 data[4]; - int ret; - - if (priv->packet_type == PK_TYPE_11A) { - priv->slot = C_SLOT_SHORT; - priv->sifs = C_SIFS_A; - priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT; - max_min = 4; - } else { - priv->sifs = C_SIFS_BG; - - if (priv->short_slot_time) { - priv->slot = C_SLOT_SHORT; - max_min = 4; - } else { - priv->slot = C_SLOT_LONG; - max_min = 5; - } - - priv->difs = C_SIFS_BG + 2 * priv->slot; - } - - priv->eifs = C_EIFS; - - data[0] = (u8)priv->sifs; - data[1] = (u8)priv->difs; - data[2] = (u8)priv->eifs; - data[3] = (u8)priv->slot; - - ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS, - MESSAGE_REQUEST_MACREG, 4, &data[0]); - if (ret) - return ret; - - max_min |= 0xa0; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0, - MESSAGE_REQUEST_MACREG, 1, &max_min); -} - -void vnt_update_top_rates(struct vnt_private *priv) -{ - int pos; - - pos = fls(priv->basic_rates & GENMASK(RATE_54M, RATE_6M)); - priv->top_ofdm_basic_rate = pos ? (pos - 1) : RATE_24M; - - pos = fls(priv->basic_rates & GENMASK(RATE_11M, RATE_1M)); - priv->top_cck_basic_rate = pos ? (pos - 1) : RATE_1M; -} - -bool vnt_ofdm_min_rate(struct vnt_private *priv) -{ - return priv->basic_rates & GENMASK(RATE_54M, RATE_6M) ? true : false; -} - -u8 vnt_get_pkt_type(struct vnt_private *priv) -{ - if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B) - return (u8)priv->bb_type; - else if (vnt_ofdm_min_rate(priv)) - return PK_TYPE_11GA; - return PK_TYPE_11GB; -} - -/* - * Description: Calculate TSF offset of two TSF input - * Get TSF Offset from RxBCN's TSF and local TSF - * - * Parameters: - * In: - * rx_rate - rx rate. - * tsf1 - Rx BCN's TSF - * tsf2 - Local TSF - * Out: - * none - * - * Return Value: TSF Offset value - * - */ -u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2) -{ - return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE]; -} - -int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, - u64 time_stamp, u64 local_tsf) -{ - u64 tsf_offset = 0; - u8 data[8]; - - tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf); - - data[0] = (u8)tsf_offset; - data[1] = (u8)(tsf_offset >> 8); - data[2] = (u8)(tsf_offset >> 16); - data[3] = (u8)(tsf_offset >> 24); - data[4] = (u8)(tsf_offset >> 32); - data[5] = (u8)(tsf_offset >> 40); - data[6] = (u8)(tsf_offset >> 48); - data[7] = (u8)(tsf_offset >> 56); - - return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TSF, 0, 8, data); -} - -/* - * Description: Clear NIC TSF counter - * Clear local TSF counter - * - * Parameters: - * In: - * priv - The adapter to be read - * - * Return Value: true if success; otherwise false - * - */ -bool vnt_clear_current_tsf(struct vnt_private *priv) -{ - vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); - - priv->current_tsf = 0; - - return true; -} - -/* - * Description: Read NIC TSF counter - * Get NEXTTBTT from adjusted TSF and Beacon Interval - * - * Parameters: - * In: - * tsf - Current TSF counter - * beacon_interval - Beacon Interval - * Out: - * tsf - Current TSF counter - * - * Return Value: TSF value of next Beacon - * - */ -u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval) -{ - u32 beacon_int; - - beacon_int = beacon_interval * 1024; - - /* Next TBTT = - * ((local_current_TSF / beacon_interval) + 1) * beacon_interval - */ - if (beacon_int) { - do_div(tsf, beacon_int); - tsf += 1; - tsf *= beacon_int; - } - - return tsf; -} - -int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval) -{ - u64 next_tbtt = 0; - u8 data[8]; - - vnt_clear_current_tsf(priv); - - next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval); - - data[0] = (u8)next_tbtt; - data[1] = (u8)(next_tbtt >> 8); - data[2] = (u8)(next_tbtt >> 16); - data[3] = (u8)(next_tbtt >> 24); - data[4] = (u8)(next_tbtt >> 32); - data[5] = (u8)(next_tbtt >> 40); - data[6] = (u8)(next_tbtt >> 48); - data[7] = (u8)(next_tbtt >> 56); - - return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TBTT, 0, 8, data); -} - -int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, - u16 beacon_interval) -{ - u8 data[8]; - int ret; - - tsf = vnt_get_next_tbtt(tsf, beacon_interval); - - data[0] = (u8)tsf; - data[1] = (u8)(tsf >> 8); - data[2] = (u8)(tsf >> 16); - data[3] = (u8)(tsf >> 24); - data[4] = (u8)(tsf >> 32); - data[5] = (u8)(tsf >> 40); - data[6] = (u8)(tsf >> 48); - data[7] = (u8)(tsf >> 56); - - ret = vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT, - MESSAGE_REQUEST_TBTT, 0, 8, data); - if (ret) - return ret; - - dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf); - return 0; -} - -/* - * Description: Turn off Radio power - * - * Parameters: - * In: - * priv - The adapter to be turned off - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -int vnt_radio_power_off(struct vnt_private *priv) -{ - int ret = 0; - - switch (priv->rf_type) { - case RF_AL2230: - case RF_AL2230S: - case RF_VT3226: - case RF_VT3226D0: - ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPE2 | - SOFTPWRCTL_SWPE3)); - break; - } - - if (ret) - goto end; - - ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON); - if (ret) - goto end; - - ret = vnt_set_deep_sleep(priv); - if (ret) - goto end; - - ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); - -end: - return ret; -} - -/* - * Description: Turn on Radio power - * - * Parameters: - * In: - * priv - The adapter to be turned on - * Out: - * none - * - * Return Value: true if success; otherwise false - * - */ -int vnt_radio_power_on(struct vnt_private *priv) -{ - int ret = 0; - - ret = vnt_exit_deep_sleep(priv); - if (ret) - return ret; - - ret = vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON); - if (ret) - return ret; - - switch (priv->rf_type) { - case RF_AL2230: - case RF_AL2230S: - case RF_VT3226: - case RF_VT3226D0: - ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL, - (SOFTPWRCTL_SWPE2 | - SOFTPWRCTL_SWPE3)); - if (ret) - return ret; - } - - return vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD); -} - -int vnt_set_bss_mode(struct vnt_private *priv) -{ - int ret; - unsigned char type = priv->bb_type; - unsigned char data = 0; - unsigned char bb_vga_2_3 = 0x00; - - ret = vnt_mac_set_bb_type(priv, type); - if (ret) - return ret; - - priv->packet_type = vnt_get_pkt_type(priv); - - if (priv->bb_type == BB_TYPE_11A) { - data = 0x03; - bb_vga_2_3 = 0x10; - } else if (priv->bb_type == BB_TYPE_11B) { - data = 0x02; - } else if (priv->bb_type == BB_TYPE_11G) { - data = 0x08; - } - - if (data) { - ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, - 0x88, data); - if (ret) - return ret; - } - - ret = vnt_update_ifs(priv); - if (ret) - return ret; - - ret = vnt_set_rspinf(priv, priv->bb_type); - if (ret) - return ret; - - priv->bb_vga[2] = bb_vga_2_3; - priv->bb_vga[3] = bb_vga_2_3; - - return vnt_set_vga_gain_offset(priv, priv->bb_vga[0]); -} diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h deleted file mode 100644 index eb01f7cc871f40076d46ce64b58e3762eb1b53f2..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/card.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Provide functions to setup NIC operation mode - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - */ - -#ifndef __CARD_H__ -#define __CARD_H__ -#include "device.h" - -/* init card type */ - -#define CB_MAX_CHANNEL_24G 14 -#define CB_MAX_CHANNEL_5G 42 /* add channel9(5045MHz), 41==>42 */ -#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G) - -struct vnt_private; - -int vnt_set_channel(struct vnt_private *priv, u32 connection_channel); -int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type); -int vnt_update_ifs(struct vnt_private *priv); -void vnt_update_top_rates(struct vnt_private *priv); -bool vnt_ofdm_min_rate(struct vnt_private *priv); -int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate, - u64 time_stamp, u64 local_tsf); -bool vnt_clear_current_tsf(struct vnt_private *priv); -int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval); -int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf, - u16 beacon_interval); -u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval); -u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2); -int vnt_radio_power_off(struct vnt_private *priv); -int vnt_radio_power_on(struct vnt_private *priv); -u8 vnt_get_pkt_type(struct vnt_private *priv); -int vnt_set_bss_mode(struct vnt_private *priv); - -#endif /* __CARD_H__ */ diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c deleted file mode 100644 index 413e2fc4a50dcacedbdd37a25ced88f14c8bf2aa..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/channel.c +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Channel number mapping - * - * Author: Lucas Lin - * - * Date: Dec 24, 2004 - * - * - * - * Revision History: - * 01-18-2005 RobertYu: remove the for loop searching in - * ChannelValid, change ChannelRuleTab - * to lookup-type, reorder table items. - * - * - */ - -#include "device.h" -#include "channel.h" -#include "rf.h" - -static struct ieee80211_rate vnt_rates_bg[] = { - { .bitrate = 10, .hw_value = RATE_1M }, - { .bitrate = 20, .hw_value = RATE_2M }, - { .bitrate = 55, .hw_value = RATE_5M }, - { .bitrate = 110, .hw_value = RATE_11M }, - { .bitrate = 60, .hw_value = RATE_6M }, - { .bitrate = 90, .hw_value = RATE_9M }, - { .bitrate = 120, .hw_value = RATE_12M }, - { .bitrate = 180, .hw_value = RATE_18M }, - { .bitrate = 240, .hw_value = RATE_24M }, - { .bitrate = 360, .hw_value = RATE_36M }, - { .bitrate = 480, .hw_value = RATE_48M }, - { .bitrate = 540, .hw_value = RATE_54M }, -}; - -static struct ieee80211_channel vnt_channels_2ghz[] = { - { .center_freq = 2412, .hw_value = 1 }, - { .center_freq = 2417, .hw_value = 2 }, - { .center_freq = 2422, .hw_value = 3 }, - { .center_freq = 2427, .hw_value = 4 }, - { .center_freq = 2432, .hw_value = 5 }, - { .center_freq = 2437, .hw_value = 6 }, - { .center_freq = 2442, .hw_value = 7 }, - { .center_freq = 2447, .hw_value = 8 }, - { .center_freq = 2452, .hw_value = 9 }, - { .center_freq = 2457, .hw_value = 10 }, - { .center_freq = 2462, .hw_value = 11 }, - { .center_freq = 2467, .hw_value = 12 }, - { .center_freq = 2472, .hw_value = 13 }, - { .center_freq = 2484, .hw_value = 14 } -}; - -static struct ieee80211_supported_band vnt_supported_2ghz_band = { - .channels = vnt_channels_2ghz, - .n_channels = ARRAY_SIZE(vnt_channels_2ghz), - .bitrates = vnt_rates_bg, - .n_bitrates = ARRAY_SIZE(vnt_rates_bg), -}; - -void vnt_init_bands(struct vnt_private *priv) -{ - struct ieee80211_channel *ch; - int i; - - ch = vnt_channels_2ghz; - for (i = 0; i < ARRAY_SIZE(vnt_channels_2ghz); i++) { - ch[i].max_power = VNT_RF_MAX_POWER; - ch[i].flags = IEEE80211_CHAN_NO_HT40; - } - priv->hw->wiphy->bands[NL80211_BAND_2GHZ] = - &vnt_supported_2ghz_band; -} diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h deleted file mode 100644 index 723660e40310a60f5d80261897b1c956d7ed0818..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/channel.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Country Regulation Rules header file - * - * Author: Lucas Lin - * - * Date: Dec 23, 2004 - * - */ - -#ifndef _CHANNEL_H_ -#define _CHANNEL_H_ - -#include "device.h" - -void vnt_init_bands(struct vnt_private *priv); - -#endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h deleted file mode 100644 index c13561e528db37b3fa0aa40da48100039dce8c92..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/desc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose:The header file of descriptor - * - * Revision History: - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - */ - -#ifndef __DESC_H__ -#define __DESC_H__ - -#include <linux/bits.h> -#include <linux/types.h> -#include <linux/mm.h> - -/* max transmit or receive buffer size */ -#define CB_MAX_BUF_SIZE 2900U /* NOTE: must be multiple of 4 */ - -#define MAX_TOTAL_SIZE_WITH_ALL_HEADERS CB_MAX_BUF_SIZE - -#define MAX_INTERRUPT_SIZE 32 - -#define CB_MAX_RX_DESC 128 /* max # of descriptors */ -#define CB_MIN_RX_DESC 16 /* min # of RX descriptors */ -#define CB_MAX_TX_DESC 128 /* max # of descriptors */ -#define CB_MIN_TX_DESC 16 /* min # of TX descriptors */ - -/* - * bits in the RSR register - */ -#define RSR_ADDRBROAD BIT(7) -#define RSR_ADDRMULTI BIT(6) -#define RSR_ADDRUNI 0x00 -#define RSR_IVLDTYP BIT(5) /* invalid packet type */ -#define RSR_IVLDLEN BIT(4) /* invalid len (> 2312 byte) */ -#define RSR_BSSIDOK BIT(3) -#define RSR_CRCOK BIT(2) -#define RSR_BCNSSIDOK BIT(1) -#define RSR_ADDROK BIT(0) - -/* - * bits in the new RSR register - */ -#define NEWRSR_DECRYPTOK BIT(4) -#define NEWRSR_CFPIND BIT(3) -#define NEWRSR_HWUTSF BIT(2) -#define NEWRSR_BCNHITAID BIT(1) -#define NEWRSR_BCNHITAID0 BIT(0) - -/* - * bits in the TSR register - */ -#define TSR_RETRYTMO BIT(3) -#define TSR_TMO BIT(2) -#define TSR_ACKDATA BIT(1) -#define TSR_VALID BIT(0) - -#define FIFOCTL_AUTO_FB_1 0x1000 -#define FIFOCTL_AUTO_FB_0 0x0800 -#define FIFOCTL_GRPACK 0x0400 -#define FIFOCTL_11GA 0x0300 -#define FIFOCTL_11GB 0x0200 -#define FIFOCTL_11B 0x0100 -#define FIFOCTL_11A 0x0000 -#define FIFOCTL_RTS 0x0080 -#define FIFOCTL_ISDMA0 0x0040 -#define FIFOCTL_GENINT 0x0020 -#define FIFOCTL_TMOEN 0x0010 -#define FIFOCTL_LRETRY 0x0008 -#define FIFOCTL_CRCDIS 0x0004 -#define FIFOCTL_NEEDACK 0x0002 -#define FIFOCTL_LHEAD 0x0001 - -/* WMAC definition Frag Control */ -#define FRAGCTL_AES 0x0300 -#define FRAGCTL_TKIP 0x0200 -#define FRAGCTL_LEGACY 0x0100 -#define FRAGCTL_NONENCRYPT 0x0000 -#define FRAGCTL_ENDFRAG 0x0003 -#define FRAGCTL_MIDFRAG 0x0002 -#define FRAGCTL_STAFRAG 0x0001 -#define FRAGCTL_NONFRAG 0x0000 - -#endif /* __DESC_H__ */ diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h deleted file mode 100644 index ca974d61d3f443dc17215523920d56fe8487febd..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/device.h +++ /dev/null @@ -1,386 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: MAC Data structure - * - * Author: Tevin Chen - * - * Date: Mar 17, 1997 - * - */ - -#ifndef __DEVICE_H__ -#define __DEVICE_H__ - -#include <linux/bits.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/firmware.h> -#include <linux/suspend.h> -#include <linux/if_arp.h> -#include <linux/wireless.h> -#include <linux/timer.h> -#include <linux/usb.h> -#include <linux/crc32.h> -#include <net/mac80211.h> - -#ifdef SIOCETHTOOL -#define DEVICE_ETHTOOL_IOCTL_SUPPORT -#include <linux/ethtool.h> -#else -#undef DEVICE_ETHTOOL_IOCTL_SUPPORT -#endif - -#define RATE_1M 0 -#define RATE_2M 1 -#define RATE_5M 2 -#define RATE_11M 3 -#define RATE_6M 4 -#define RATE_9M 5 -#define RATE_12M 6 -#define RATE_18M 7 -#define RATE_24M 8 -#define RATE_36M 9 -#define RATE_48M 10 -#define RATE_54M 11 -#define RATE_AUTO 12 - -#define MAX_RATE 12 -#define VNT_B_RATES (BIT(RATE_1M) | BIT(RATE_2M) |\ - BIT(RATE_5M) | BIT(RATE_11M)) - -/* - * device specific - */ - -#include "wcmd.h" -#include "desc.h" -#include "key.h" -#include "card.h" - -#define VNT_USB_VENDOR_ID 0x160a -#define VNT_USB_PRODUCT_ID 0x3184 - -#define DEVICE_NAME "vt6656" -#define DEVICE_FULL_DRV_NAM "VIA Networking Wireless LAN USB Driver" - -#define DEVICE_VERSION "mac80211" - -#define FIRMWARE_VERSION 0x133 /* version 1.51 */ -#define FIRMWARE_NAME "vntwusb.fw" -#define FIRMWARE_CHUNK_SIZE 0x400 - -#define MAX_UINTS 8 -#define OPTION_DEFAULT { [0 ... MAX_UINTS - 1] = -1} - -#define DUPLICATE_RX_CACHE_LENGTH 5 - -#define AUTO_FB_NONE 0 -#define AUTO_FB_0 1 -#define AUTO_FB_1 2 - -#define FB_RATE0 0 -#define FB_RATE1 1 - -/* Antenna Mode */ -#define ANT_A 0 -#define ANT_B 1 -#define ANT_DIVERSITY 2 -#define ANT_RXD_TXA 3 -#define ANT_RXD_TXB 4 -#define ANT_UNKNOWN 0xFF -#define ANT_TXA 0 -#define ANT_TXB 1 -#define ANT_RXA 2 -#define ANT_RXB 3 - -#define BB_VGA_LEVEL 4 -#define BB_VGA_CHANGE_THRESHOLD 3 - -#define EEP_MAX_CONTEXT_SIZE 256 - -/* Contents in the EEPROM */ -#define EEP_OFS_PAR 0x0 -#define EEP_OFS_ANTENNA 0x17 -#define EEP_OFS_RADIOCTL 0x18 -#define EEP_OFS_RFTYPE 0x1b -#define EEP_OFS_MINCHANNEL 0x1c -#define EEP_OFS_MAXCHANNEL 0x1d -#define EEP_OFS_SIGNATURE 0x1e -#define EEP_OFS_ZONETYPE 0x1f -#define EEP_OFS_RFTABLE 0x20 -#define EEP_OFS_PWR_CCK 0x20 -#define EEP_OFS_SETPT_CCK 0x21 -#define EEP_OFS_PWR_OFDMG 0x23 - -#define EEP_OFS_CALIB_TX_IQ 0x24 -#define EEP_OFS_CALIB_TX_DC 0x25 -#define EEP_OFS_CALIB_RX_IQ 0x26 - -#define EEP_OFS_MAJOR_VER 0x2e -#define EEP_OFS_MINOR_VER 0x2f - -#define EEP_OFS_CCK_PWR_TBL 0x30 -#define EEP_OFS_OFDM_PWR_TBL 0x40 -#define EEP_OFS_OFDMA_PWR_TBL 0x50 - -/* Bits in EEP_OFS_ANTENNA */ -#define EEP_ANTENNA_MAIN BIT(0) -#define EEP_ANTENNA_AUX BIT(1) -#define EEP_ANTINV BIT(2) - -/* Bits in EEP_OFS_RADIOCTL */ -#define EEP_RADIOCTL_ENABLE BIT(7) - -/* control commands */ -#define MESSAGE_TYPE_READ 0x1 -#define MESSAGE_TYPE_WRITE 0x0 -#define MESSAGE_TYPE_LOCK_OR 0x2 -#define MESSAGE_TYPE_LOCK_AND 0x3 -#define MESSAGE_TYPE_WRITE_MASK 0x4 -#define MESSAGE_TYPE_CARDINIT 0x5 -#define MESSAGE_TYPE_INIT_RSP 0x6 -#define MESSAGE_TYPE_MACSHUTDOWN 0x7 -#define MESSAGE_TYPE_SETKEY 0x8 -#define MESSAGE_TYPE_CLRKEYENTRY 0x9 -#define MESSAGE_TYPE_WRITE_MISCFF 0xa -#define MESSAGE_TYPE_SET_ANTMD 0xb -#define MESSAGE_TYPE_SELECT_CHANNEL 0xc -#define MESSAGE_TYPE_SET_TSFTBTT 0xd -#define MESSAGE_TYPE_SET_SSTIFS 0xe -#define MESSAGE_TYPE_CHANGE_BBTYPE 0xf -#define MESSAGE_TYPE_DISABLE_PS 0x10 -#define MESSAGE_TYPE_WRITE_IFRF 0x11 - -/* command read/write(index) */ -#define MESSAGE_REQUEST_MEM 0x1 -#define MESSAGE_REQUEST_BBREG 0x2 -#define MESSAGE_REQUEST_MACREG 0x3 -#define MESSAGE_REQUEST_EEPROM 0x4 -#define MESSAGE_REQUEST_TSF 0x5 -#define MESSAGE_REQUEST_TBTT 0x6 -#define MESSAGE_REQUEST_BBAGC 0x7 -#define MESSAGE_REQUEST_VERSION 0x8 -#define MESSAGE_REQUEST_RF_INIT 0x9 -#define MESSAGE_REQUEST_RF_INIT2 0xa -#define MESSAGE_REQUEST_RF_CH0 0xb -#define MESSAGE_REQUEST_RF_CH1 0xc -#define MESSAGE_REQUEST_RF_CH2 0xd - -/* USB registers */ -#define USB_REG4 0x604 - -#define DEVICE_INIT_COLD 0x0 /* cold init */ -#define DEVICE_INIT_RESET 0x1 /* reset init or Dx to D0 power remain */ -#define DEVICE_INIT_DXPL 0x2 /* Dx to D0 power lost init */ - -/* Device init */ -struct vnt_cmd_card_init { - u8 init_class; - u8 exist_sw_net_addr; - u8 sw_net_addr[6]; - u8 short_retry_limit; - u8 long_retry_limit; -}; - -struct vnt_rsp_card_init { - u8 status; - u8 net_addr[6]; - u8 rf_type; - u8 min_channel; - u8 max_channel; -}; - -/* USB */ - -/* - * Enum of context types for SendPacket - */ -enum { - CONTEXT_DATA_PACKET = 0, - CONTEXT_BEACON_PACKET -}; - -struct vnt_rx_header { - u32 wbk_status; - u8 rx_sts; - u8 rx_rate; - u16 pay_load_len; -} __packed; - -struct vnt_rx_tail { - __le64 tsf_time; - u8 sq; - u8 new_rsr; - u8 rssi; - u8 rsr; - u8 sq_3; -} __packed; - -/* RCB (Receive Control Block) */ -struct vnt_rcb { - void *priv; - struct urb *urb; - struct sk_buff *skb; -}; - -/* used to track bulk out irps */ -struct vnt_usb_send_context { - void *priv; - struct sk_buff *skb; - void *tx_buffer; - u32 frame_len; - u16 tx_hdr_size; - u16 tx_rate; - u8 type; - u8 pkt_no; - u8 pkt_type; - bool in_use; -}; - -/* - * Structure to keep track of USB interrupt packets - */ -struct vnt_interrupt_buffer { - u8 *data_buf; -}; - -/* flags for options */ -#define DEVICE_FLAGS_UNPLUG 0 -#define DEVICE_FLAGS_DISCONNECTED 1 - -struct vnt_private { - /* mac80211 */ - struct ieee80211_hw *hw; - struct ieee80211_vif *vif; - u8 mac_hw; - /* netdev */ - struct usb_device *usb; - struct usb_interface *intf; - - u64 tsf_time; - - u32 rx_buf_sz; - int mc_list_count; - - spinlock_t lock; /* prepare tx USB URB */ - struct mutex usb_lock; /* USB control messages */ - - unsigned long flags; - - /* USB */ - struct urb *interrupt_urb; - u32 int_interval; - - /* Variables to track resources for the BULK In Pipe */ - struct vnt_rcb *rcb[CB_MAX_RX_DESC]; - u32 num_rcb; - - /* Variables to track resources for the BULK Out Pipe */ - struct vnt_usb_send_context *tx_context[CB_MAX_TX_DESC]; - struct usb_anchor tx_submitted; - u32 num_tx_context; - - /* Variables to track resources for the Interrupt In Pipe */ - struct vnt_interrupt_buffer int_buf; - - /* Version control */ - u16 firmware_version; - u8 local_id; - u8 rf_type; - u8 bb_rx_conf; - - struct vnt_cmd_card_init init_command; - struct vnt_rsp_card_init init_response; - u8 current_net_addr[ETH_ALEN] __aligned(2); - u8 permanent_net_addr[ETH_ALEN] __aligned(2); - - u8 exist_sw_net_addr; - - u64 current_tsf; - - /* 802.11 MAC specific */ - u32 current_rssi; - - /* Antenna Diversity */ - int tx_rx_ant_inv; - u32 rx_antenna_sel; - u8 rx_antenna_mode; - u8 tx_antenna_mode; - u8 radio_ctl; - - /* IFS & Cw */ - u32 sifs; /* Current SIFS */ - u32 difs; /* Current DIFS */ - u32 eifs; /* Current EIFS */ - u32 slot; /* Current SlotTime */ - - /* Rate */ - u8 bb_type; /* 0: 11A, 1:11B, 2:11G */ - u8 packet_type; /* 0:11a 1:11b 2:11gb 3:11ga */ - u32 basic_rates; - u8 top_ofdm_basic_rate; - u8 top_cck_basic_rate; - - u8 eeprom[EEP_MAX_CONTEXT_SIZE]; /*u32 alignment */ - - u8 preamble_type; - - /* For RF Power table */ - u8 cck_pwr; - u8 ofdm_pwr_g; - u8 ofdm_pwr_a; - u8 power; - u8 cck_pwr_tbl[14]; - u8 ofdm_pwr_tbl[14]; - u8 ofdm_a_pwr_tbl[42]; - - u16 tx_rate_fb0; - u16 tx_rate_fb1; - - enum nl80211_iftype op_mode; - - int short_slot_time; - - /* Power save */ - u16 current_aid; - - /* Beacon related */ - u16 seq_counter; - - enum vnt_cmd_state command_state; - - enum vnt_cmd command; - - /* 802.11 counter */ - - enum vnt_cmd cmd_queue[CMD_Q_SIZE]; - u32 cmd_dequeue_idx; - u32 cmd_enqueue_idx; - u32 free_cmd_queue; - int cmd_running; - - unsigned long key_entry_inuse; - - u8 auto_fb_ctrl; - - /* For Update BaseBand VGA Gain Offset */ - u8 bb_vga[BB_VGA_LEVEL]; - - u8 bb_pre_ed_rssi; - u8 bb_pre_ed_index; - - /* command timer */ - struct delayed_work run_command_work; - - struct ieee80211_low_level_stats low_stats; -}; - -int vnt_init(struct vnt_private *priv); - -#endif diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c deleted file mode 100644 index bdc5f30c4f9d2951a6f80feaa9fac54c5a7c3f65..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/key.c +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions for 802.11i Key management - * - * Author: Jerry Chen - * - * Date: May 29, 2003 - * - * Functions: - * - * Revision History: - * - */ - -#include "mac.h" -#include "key.h" -#include "usbpipe.h" - -int vnt_key_init_table(struct vnt_private *priv) -{ - u8 i; - u8 data[MAX_KEY_TABLE]; - - for (i = 0; i < MAX_KEY_TABLE; i++) - data[i] = i; - - return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY, - 0, 0, ARRAY_SIZE(data), data); -} - -static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, - struct ieee80211_key_conf *key, u32 key_type, - u32 mode) -{ - struct vnt_private *priv = hw->priv; - u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u16 key_mode = 0; - u32 entry = 0; - u8 *bssid; - u8 key_inx = key->keyidx; - u8 i; - - if (mac_addr) - bssid = mac_addr; - else - bssid = &broadcast[0]; - - if (key_type != VNT_KEY_DEFAULTKEY) { - for (i = 0; i < (MAX_KEY_TABLE - 1); i++) { - if (!test_bit(i, &priv->key_entry_inuse)) { - set_bit(i, &priv->key_entry_inuse); - - key->hw_key_idx = i; - entry = key->hw_key_idx; - break; - } - } - } - - switch (key_type) { - case VNT_KEY_DEFAULTKEY: - /* default key last entry */ - entry = MAX_KEY_TABLE - 1; - key->hw_key_idx = entry; - fallthrough; - case VNT_KEY_GROUP_ADDRESS: - key_mode = mode | (mode << 4); - break; - case VNT_KEY_GROUP: - key_mode = mode << 4; - break; - case VNT_KEY_PAIRWISE: - key_mode |= mode; - key_inx = 4; - break; - default: - return -EINVAL; - } - - key_mode |= key_type; - - if (mode == KEY_CTL_WEP) { - if (key->keylen == WLAN_KEY_LEN_WEP40) - key->key[15] &= 0x7f; - if (key->keylen == WLAN_KEY_LEN_WEP104) - key->key[15] |= 0x80; - } - - return vnt_mac_set_keyentry(priv, key_mode, entry, - key_inx, bssid, key->key); -} - -int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - struct ieee80211_vif *vif, struct ieee80211_key_conf *key) -{ - struct vnt_private *priv = hw->priv; - u8 *mac_addr = NULL; - u8 key_dec_mode = 0; - - if (sta) - mac_addr = &sta->addr[0]; - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, - KEY_CTL_WEP); - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - - return vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, - KEY_CTL_WEP); - - case WLAN_CIPHER_SUITE_TKIP: - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - - key_dec_mode = KEY_CTL_TKIP; - - break; - case WLAN_CIPHER_SUITE_CCMP: - if (priv->local_id <= MAC_REVISION_A1) - return -EOPNOTSUPP; - - key_dec_mode = KEY_CTL_CCMP; - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - break; - default: - return -EOPNOTSUPP; - } - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) - return vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE, - key_dec_mode); - - return vnt_set_keymode(hw, mac_addr, key, - VNT_KEY_GROUP_ADDRESS, key_dec_mode); -} diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h deleted file mode 100644 index 6f1d5b4f6da7894d82e01c6aa293db35c8248eb7..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/key.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Implement functions for 802.11i Key management - * - * Author: Jerry Chen - * - * Date: May 29, 2003 - * - */ - -#ifndef __KEY_H__ -#define __KEY_H__ - -#include "device.h" - -#define MAX_KEY_TABLE 11 - -#define KEY_CTL_WEP 0x00 -#define KEY_CTL_NONE 0x01 -#define KEY_CTL_TKIP 0x02 -#define KEY_CTL_CCMP 0x03 - -#define VNT_KEY_ONFLY_ALL 0x4000 -#define VNT_KEY_ONFLY 0x8000 -#define VNT_KEY_ALLGROUP 0x04 -#define VNT_KEY_GROUP 0x40 -#define VNT_KEY_PAIRWISE VNT_KEY_ONFLY -#define VNT_KEY_GROUP_ADDRESS (VNT_KEY_ALLGROUP | VNT_KEY_GROUP) -#define VNT_KEY_DEFAULTKEY (VNT_KEY_GROUP_ADDRESS | VNT_KEY_ONFLY |\ - VNT_KEY_ONFLY_ALL) - -int vnt_key_init_table(struct vnt_private *priv); - -int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - struct ieee80211_vif *vif, struct ieee80211_key_conf *key); - -#endif /* __KEY_H__ */ diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c deleted file mode 100644 index 49430c0a99b8dd7b1abd3bb38cfb15d1b9e5f579..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/mac.c +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: MAC routines - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - * Functions: - * - * Revision History: - */ - -#include <linux/etherdevice.h> - -#include "desc.h" -#include "mac.h" -#include "usbpipe.h" - -int vnt_mac_set_filter(struct vnt_private *priv, u64 mc_filter) -{ - __le64 le_mc = cpu_to_le64(mc_filter); - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_MAR0, - MESSAGE_REQUEST_MACREG, sizeof(le_mc), - (u8 *)&le_mc); -} - -int vnt_mac_shutdown(struct vnt_private *priv) -{ - return vnt_control_out(priv, MESSAGE_TYPE_MACSHUTDOWN, 0, 0, 0, NULL); -} - -int vnt_mac_set_bb_type(struct vnt_private *priv, u8 type) -{ - u8 data[2]; - - data[0] = type; - data[1] = EN_CFG_BB_TYPE_MASK; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), - data); -} - -int vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx) -{ - return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY, 0, 0, - sizeof(entry_idx), &entry_idx); -} - -int vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx, - u32 key_idx, u8 *addr, u8 *key) -{ - struct vnt_mac_set_key set_key; - u16 offset; - - offset = MISCFIFO_KEYETRY0; - offset += entry_idx * MISCFIFO_KEYENTRYSIZE; - - set_key.u.write.key_ctl = cpu_to_le16(key_ctl); - ether_addr_copy(set_key.u.write.addr, addr); - - /* swap over swap[0] and swap[1] to get correct write order */ - swap(set_key.u.swap[0], set_key.u.swap[1]); - - memcpy(set_key.key, key, WLAN_KEY_LEN_CCMP); - - dev_dbg(&priv->usb->dev, "offset %d key ctl %d set key %24ph\n", - offset, key_ctl, (u8 *)&set_key); - - return vnt_control_out(priv, MESSAGE_TYPE_SETKEY, offset, - (u16)key_idx, sizeof(struct vnt_mac_set_key), - (u8 *)&set_key); -} - -int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits) -{ - u8 data[2]; - - data[0] = 0; - data[1] = bits; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits) -{ - u8 data[2]; - - data[0] = bits; - data[1] = bits; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word) -{ - u8 data[2]; - - data[0] = (u8)(word & 0xff); - data[1] = (u8)(word >> 8); - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, reg_ofs, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr) -{ - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_BSSID0, - MESSAGE_REQUEST_MACREG, ETH_ALEN, addr); -} - -int vnt_mac_enable_protect_mode(struct vnt_private *priv) -{ - u8 data[2]; - - data[0] = EN_CFG_PROTECT_MD; - data[1] = EN_CFG_PROTECT_MD; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_disable_protect_mode(struct vnt_private *priv) -{ - u8 data[2]; - - data[0] = 0; - data[1] = EN_CFG_PROTECT_MD; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv) -{ - u8 data[2]; - - data[0] = EN_CFG_BARKER_PREAM; - data[1] = EN_CFG_BARKER_PREAM; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG2, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv) -{ - u8 data[2]; - - data[0] = 0; - data[1] = EN_CFG_BARKER_PREAM; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG2, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval) -{ - u8 data[2]; - - data[0] = (u8)(interval & 0xff); - data[1] = (u8)(interval >> 8); - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_BI, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} - -int vnt_mac_set_led(struct vnt_private *priv, u8 state, u8 led) -{ - u8 data[2]; - - data[0] = led; - data[1] = state; - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_PAPEDELAY, - MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data); -} diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h deleted file mode 100644 index 0ac845bd3c5ad832a9b881ac433de9ae4bd2260e..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/mac.h +++ /dev/null @@ -1,373 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: MAC routines - * - * Author: Tevin Chen - * - * Date: May 21, 1996 - * - * Revision History: - * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec. - * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53. - * 09-03-2003 Bryan YC Fan: Add MACvDisableProtectMD & MACvEnableProtectMD - */ - -#ifndef __MAC_H__ -#define __MAC_H__ - -#include <linux/bits.h> -#include "device.h" - -#define REV_ID_VT3253_A0 0x00 -#define REV_ID_VT3253_A1 0x01 -#define REV_ID_VT3253_B0 0x08 -#define REV_ID_VT3253_B1 0x09 - -/* Registers in the MAC */ -#define MAC_REG_BISTCMD 0x04 -#define MAC_REG_BISTSR0 0x05 -#define MAC_REG_BISTSR1 0x06 -#define MAC_REG_BISTSR2 0x07 -#define MAC_REG_I2MCSR 0x08 -#define MAC_REG_I2MTGID 0x09 -#define MAC_REG_I2MTGAD 0x0a -#define MAC_REG_I2MCFG 0x0b -#define MAC_REG_I2MDIPT 0x0c -#define MAC_REG_I2MDOPT 0x0e -#define MAC_REG_USBSUS 0x0f - -#define MAC_REG_LOCALID 0x14 -#define MAC_REG_TESTCFG 0x15 -#define MAC_REG_JUMPER0 0x16 -#define MAC_REG_JUMPER1 0x17 -#define MAC_REG_TMCTL 0x18 -#define MAC_REG_TMDATA0 0x1c -#define MAC_REG_TMDATA1 0x1d -#define MAC_REG_TMDATA2 0x1e -#define MAC_REG_TMDATA3 0x1f - -/* MAC Parameter related */ -#define MAC_REG_LRT 0x20 -#define MAC_REG_SRT 0x21 -#define MAC_REG_SIFS 0x22 -#define MAC_REG_DIFS 0x23 -#define MAC_REG_EIFS 0x24 -#define MAC_REG_SLOT 0x25 -#define MAC_REG_BI 0x26 -#define MAC_REG_CWMAXMIN0 0x28 -#define MAC_REG_LINKOFFTOTM 0x2a -#define MAC_REG_SWTMOT 0x2b -#define MAC_REG_RTSOKCNT 0x2c -#define MAC_REG_RTSFAILCNT 0x2d -#define MAC_REG_ACKFAILCNT 0x2e -#define MAC_REG_FCSERRCNT 0x2f - -/* TSF Related */ -#define MAC_REG_TSFCNTR 0x30 -#define MAC_REG_NEXTTBTT 0x38 -#define MAC_REG_TSFOFST 0x40 -#define MAC_REG_TFTCTL 0x48 - -/* WMAC Control/Status Related */ -#define MAC_REG_ENCFG0 0x4c -#define MAC_REG_ENCFG1 0x4d -#define MAC_REG_ENCFG2 0x4e - -#define MAC_REG_CFG 0x50 -#define MAC_REG_TEST 0x52 -#define MAC_REG_HOSTCR 0x54 -#define MAC_REG_MACCR 0x55 -#define MAC_REG_RCR 0x56 -#define MAC_REG_TCR 0x57 -#define MAC_REG_IMR 0x58 -#define MAC_REG_ISR 0x5c -#define MAC_REG_ISR1 0x5d - -/* Power Saving Related */ -#define MAC_REG_PSCFG 0x60 -#define MAC_REG_PSCTL 0x61 -#define MAC_REG_PSPWRSIG 0x62 -#define MAC_REG_BBCR13 0x63 -#define MAC_REG_AIDATIM 0x64 -#define MAC_REG_PWBT 0x66 -#define MAC_REG_WAKEOKTMR 0x68 -#define MAC_REG_CALTMR 0x69 -#define MAC_REG_SYNSPACCNT 0x6a -#define MAC_REG_WAKSYNOPT 0x6b - -/* Baseband/IF Control Group */ -#define MAC_REG_BBREGCTL 0x6c -#define MAC_REG_CHANNEL 0x6d -#define MAC_REG_BBREGADR 0x6e -#define MAC_REG_BBREGDATA 0x6f -#define MAC_REG_IFREGCTL 0x70 -#define MAC_REG_IFDATA 0x71 -#define MAC_REG_ITRTMSET 0x74 -#define MAC_REG_PAPEDELAY 0x77 -#define MAC_REG_SOFTPWRCTL 0x78 -#define MAC_REG_SOFTPWRCTL2 0x79 -#define MAC_REG_GPIOCTL0 0x7a -#define MAC_REG_GPIOCTL1 0x7b - -/* MiscFF PIO related */ -#define MAC_REG_MISCFFNDEX 0xbc -#define MAC_REG_MISCFFCTL 0xbe -#define MAC_REG_MISCFFDATA 0xc0 - -/* MAC Configuration Group */ -#define MAC_REG_PAR0 0xc4 -#define MAC_REG_PAR4 0xc8 -#define MAC_REG_BSSID0 0xcc -#define MAC_REG_BSSID4 0xd0 -#define MAC_REG_MAR0 0xd4 -#define MAC_REG_MAR4 0xd8 - -/* MAC RSPPKT INFO Group */ -#define MAC_REG_RSPINF_B_1 0xdC -#define MAC_REG_RSPINF_B_2 0xe0 -#define MAC_REG_RSPINF_B_5 0xe4 -#define MAC_REG_RSPINF_B_11 0xe8 -#define MAC_REG_RSPINF_A_6 0xec -#define MAC_REG_RSPINF_A_9 0xee -#define MAC_REG_RSPINF_A_12 0xf0 -#define MAC_REG_RSPINF_A_18 0xf2 -#define MAC_REG_RSPINF_A_24 0xf4 -#define MAC_REG_RSPINF_A_36 0xf6 -#define MAC_REG_RSPINF_A_48 0xf8 -#define MAC_REG_RSPINF_A_54 0xfa -#define MAC_REG_RSPINF_A_72 0xfc - -/* Bits in the I2MCFG EEPROM register */ -#define I2MCFG_BOUNDCTL BIT(7) -#define I2MCFG_WAITCTL BIT(5) -#define I2MCFG_SCLOECTL BIT(4) -#define I2MCFG_WBUSYCTL BIT(3) -#define I2MCFG_NORETRY BIT(2) -#define I2MCFG_I2MLDSEQ BIT(1) -#define I2MCFG_I2CMFAST BIT(0) - -/* Bits in the I2MCSR EEPROM register */ -#define I2MCSR_EEMW BIT(7) -#define I2MCSR_EEMR BIT(6) -#define I2MCSR_AUTOLD BIT(3) -#define I2MCSR_NACK BIT(1) -#define I2MCSR_DONE BIT(0) - -/* Bits in the TMCTL register */ -#define TMCTL_TSUSP BIT(2) -#define TMCTL_TMD BIT(1) -#define TMCTL_TE BIT(0) - -/* Bits in the TFTCTL register */ -#define TFTCTL_HWUTSF BIT(7) -#define TFTCTL_TBTTSYNC BIT(6) -#define TFTCTL_HWUTSFEN BIT(5) -#define TFTCTL_TSFCNTRRD BIT(4) -#define TFTCTL_TBTTSYNCEN BIT(3) -#define TFTCTL_TSFSYNCEN BIT(2) -#define TFTCTL_TSFCNTRST BIT(1) -#define TFTCTL_TSFCNTREN BIT(0) - -/* Bits in the EnhanceCFG_0 register */ -#define EN_CFG_BB_TYPE_A 0x00 -#define EN_CFG_BB_TYPE_B BIT(0) -#define EN_CFG_BB_TYPE_G BIT(1) -#define EN_CFG_BB_TYPE_MASK (EN_CFG_BB_TYPE_B | EN_CFG_BB_TYPE_G) -#define EN_CFG_PROTECT_MD BIT(5) - -/* Bits in the EnhanceCFG_1 register */ -#define EN_CFG_BCN_SUS_IND BIT(0) -#define EN_CFG_BCN_SUS_CLR BIT(1) - -/* Bits in the EnhanceCFG_2 register */ -#define EN_CFG_NXTBTTCFPSTR BIT(0) -#define EN_CFG_BARKER_PREAM BIT(1) -#define EN_CFG_PKT_BURST_MD BIT(2) - -/* Bits in the CFG register */ -#define CFG_TKIPOPT BIT(7) -#define CFG_RXDMAOPT BIT(6) -#define CFG_TMOT_SW BIT(5) -#define CFG_TMOT_HWLONG BIT(4) -#define CFG_TMOT_HW 0x00 -#define CFG_CFPENDOPT BIT(3) -#define CFG_BCNSUSEN BIT(2) -#define CFG_NOTXTIMEOUT BIT(1) -#define CFG_NOBUFOPT BIT(0) - -/* Bits in the TEST register */ -#define TEST_LBEXT BIT(7) -#define TEST_LBINT BIT(6) -#define TEST_LBNONE 0x00 -#define TEST_SOFTINT BIT(5) -#define TEST_CONTTX BIT(4) -#define TEST_TXPE BIT(3) -#define TEST_NAVDIS BIT(2) -#define TEST_NOCTS BIT(1) -#define TEST_NOACK BIT(0) - -/* Bits in the HOSTCR register */ -#define HOSTCR_TXONST BIT(7) -#define HOSTCR_RXONST BIT(6) -#define HOSTCR_ADHOC BIT(5) -#define HOSTCR_AP BIT(4) -#define HOSTCR_TXON BIT(3) -#define HOSTCR_RXON BIT(2) -#define HOSTCR_MACEN BIT(1) -#define HOSTCR_SOFTRST BIT(0) - -/* Bits in the MACCR register */ -#define MACCR_SYNCFLUSHOK BIT(2) -#define MACCR_SYNCFLUSH BIT(1) -#define MACCR_CLRNAV BIT(0) - -/* Bits in the RCR register */ -#define RCR_SSID BIT(7) -#define RCR_RXALLTYPE BIT(6) -#define RCR_UNICAST BIT(5) -#define RCR_BROADCAST BIT(4) -#define RCR_MULTICAST BIT(3) -#define RCR_WPAERR BIT(2) -#define RCR_ERRCRC BIT(1) -#define RCR_BSSID BIT(0) - -/* Bits in the TCR register */ -#define TCR_SYNCDCFOPT BIT(1) -#define TCR_AUTOBCNTX BIT(0) - -/* ISR1 */ -#define ISR_GPIO3 BIT(6) -#define ISR_RXNOBUF BIT(3) -#define ISR_MIBNEARFULL BIT(2) -#define ISR_SOFTINT BIT(1) -#define ISR_FETALERR BIT(0) - -#define LEDSTS_STS 0x06 -#define LEDSTS_TMLEN 0x78 -#define LEDSTS_OFF 0x00 -#define LEDSTS_ON 0x02 -#define LEDSTS_SLOW 0x04 -#define LEDSTS_INTER 0x06 - -/* ISR0 */ -#define ISR_WATCHDOG BIT(7) -#define ISR_SOFTTIMER BIT(6) -#define ISR_GPIO0 BIT(5) -#define ISR_TBTT BIT(4) -#define ISR_RXDMA0 BIT(3) -#define ISR_BNTX BIT(2) -#define ISR_ACTX BIT(0) - -/* Bits in the PSCFG register */ -#define PSCFG_PHILIPMD BIT(6) -#define PSCFG_WAKECALEN BIT(5) -#define PSCFG_WAKETMREN BIT(4) -#define PSCFG_BBPSPROG BIT(3) -#define PSCFG_WAKESYN BIT(2) -#define PSCFG_SLEEPSYN BIT(1) -#define PSCFG_AUTOSLEEP BIT(0) - -/* Bits in the PSCTL register */ -#define PSCTL_WAKEDONE BIT(5) -#define PSCTL_PS BIT(4) -#define PSCTL_GO2DOZE BIT(3) -#define PSCTL_LNBCN BIT(2) -#define PSCTL_ALBCN BIT(1) -#define PSCTL_PSEN BIT(0) - -/* Bits in the PSPWSIG register */ -#define PSSIG_WPE3 BIT(7) -#define PSSIG_WPE2 BIT(6) -#define PSSIG_WPE1 BIT(5) -#define PSSIG_WRADIOPE BIT(4) -#define PSSIG_SPE3 BIT(3) -#define PSSIG_SPE2 BIT(2) -#define PSSIG_SPE1 BIT(1) -#define PSSIG_SRADIOPE BIT(0) - -/* Bits in the BBREGCTL register */ -#define BBREGCTL_DONE BIT(2) -#define BBREGCTL_REGR BIT(1) -#define BBREGCTL_REGW BIT(0) - -/* Bits in the IFREGCTL register */ -#define IFREGCTL_DONE BIT(2) -#define IFREGCTL_IFRF BIT(1) -#define IFREGCTL_REGW BIT(0) - -/* Bits in the SOFTPWRCTL register */ -#define SOFTPWRCTL_RFLEOPT BIT(3) -#define SOFTPWRCTL_TXPEINV BIT(1) -#define SOFTPWRCTL_SWPECTI BIT(0) -#define SOFTPWRCTL_SWPAPE BIT(5) -#define SOFTPWRCTL_SWCALEN BIT(4) -#define SOFTPWRCTL_SWRADIO_PE BIT(3) -#define SOFTPWRCTL_SWPE2 BIT(2) -#define SOFTPWRCTL_SWPE1 BIT(1) -#define SOFTPWRCTL_SWPE3 BIT(0) - -/* Bits in the GPIOCTL1 register */ -#define GPIO3_MD BIT(5) -#define GPIO3_DATA BIT(6) -#define GPIO3_INTMD BIT(7) - -/* Bits in the MISCFFCTL register */ -#define MISCFFCTL_WRITE BIT(0) - -/* Loopback mode */ -#define MAC_LB_EXT BIT(1) -#define MAC_LB_INTERNAL BIT(0) -#define MAC_LB_NONE 0x00 - -/* Ethernet address filter type */ -#define PKT_TYPE_NONE 0x00 /* turn off receiver */ -#define PKT_TYPE_ALL_MULTICAST BIT(7) -#define PKT_TYPE_PROMISCUOUS BIT(6) -#define PKT_TYPE_DIRECTED BIT(5) /* obselete */ -#define PKT_TYPE_BROADCAST BIT(4) -#define PKT_TYPE_MULTICAST BIT(3) -#define PKT_TYPE_ERROR_WPA BIT(2) -#define PKT_TYPE_ERROR_CRC BIT(1) -#define PKT_TYPE_BSSID BIT(0) - -#define DEFAULT_BI 0x200 - -/* MiscFIFO Offset */ -#define MISCFIFO_KEYETRY0 32 -#define MISCFIFO_KEYENTRYSIZE 22 - -#define MAC_REVISION_A0 0x00 -#define MAC_REVISION_A1 0x01 - -struct vnt_mac_set_key { - union { - struct { - u8 addr[ETH_ALEN]; - __le16 key_ctl; - } write __packed; - u32 swap[2]; - } u; - u8 key[WLAN_KEY_LEN_CCMP]; -} __packed; - -int vnt_mac_set_filter(struct vnt_private *priv, u64 mc_filter); -int vnt_mac_shutdown(struct vnt_private *priv); -int vnt_mac_set_bb_type(struct vnt_private *priv, u8 type); -int vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx); -int vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx, - u32 key_idx, u8 *addr, u8 *key); -int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits); -int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits); -int vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word); -int vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr); -int vnt_mac_enable_protect_mode(struct vnt_private *priv); -int vnt_mac_disable_protect_mode(struct vnt_private *priv); -int vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv); -int vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv); -int vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval); -int vnt_mac_set_led(struct vnt_private *privpriv, u8 state, u8 led); - -#endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c deleted file mode 100644 index 4f09e733e7a81e19b5d7a6d99d8cc68fe5041a1d..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/main_usb.c +++ /dev/null @@ -1,1121 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: driver entry for initial, open, close, tx and rx. - * - * Author: Lyndon Chen - * - * Date: Dec 8, 2005 - * - * Functions: - * - * vt6656_probe - module initial (insmod) driver entry - * vnt_free_tx_bufs - free tx buffer function - * vnt_init_registers- initial MAC & BBP & RF internal registers. - * - * Revision History: - */ -#undef __NO_VERSION__ - -#include <linux/bits.h> -#include <linux/etherdevice.h> -#include <linux/file.h> -#include <linux/kernel.h> -#include "device.h" -#include "card.h" -#include "baseband.h" -#include "mac.h" -#include "power.h" -#include "wcmd.h" -#include "rxtx.h" -#include "rf.h" -#include "usbpipe.h" -#include "channel.h" - -/* - * define module options - */ - -/* version information */ -#define DRIVER_AUTHOR \ - "VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>" -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM); - -#define RX_DESC_DEF0 64 -static int vnt_rx_buffers = RX_DESC_DEF0; -module_param_named(rx_buffers, vnt_rx_buffers, int, 0644); -MODULE_PARM_DESC(rx_buffers, "Number of receive usb rx buffers"); - -#define TX_DESC_DEF0 64 -static int vnt_tx_buffers = TX_DESC_DEF0; -module_param_named(tx_buffers, vnt_tx_buffers, int, 0644); -MODULE_PARM_DESC(tx_buffers, "Number of receive usb tx buffers"); - -#define RTS_THRESH_DEF 2347 -#define FRAG_THRESH_DEF 2346 - -/* BasebandType[] baseband type selected - * 0: indicate 802.11a type - * 1: indicate 802.11b type - * 2: indicate 802.11g type - */ - -#define BBP_TYPE_DEF 2 - -/* - * Static vars definitions - */ - -static const struct usb_device_id vt6656_table[] = { - {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, - {} -}; - -static void vnt_set_options(struct vnt_private *priv) -{ - /* Set number of TX buffers */ - if (vnt_tx_buffers < CB_MIN_TX_DESC || vnt_tx_buffers > CB_MAX_TX_DESC) - priv->num_tx_context = TX_DESC_DEF0; - else - priv->num_tx_context = vnt_tx_buffers; - - /* Set number of RX buffers */ - if (vnt_rx_buffers < CB_MIN_RX_DESC || vnt_rx_buffers > CB_MAX_RX_DESC) - priv->num_rcb = RX_DESC_DEF0; - else - priv->num_rcb = vnt_rx_buffers; - - priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; - priv->bb_type = BBP_TYPE_DEF; - priv->packet_type = priv->bb_type; - priv->preamble_type = PREAMBLE_LONG; - priv->exist_sw_net_addr = false; -} - -static int vnt_download_firmware(struct vnt_private *priv) -{ - struct device *dev = &priv->usb->dev; - const struct firmware *fw; - u16 length; - int ii; - int ret = 0; - - dev_dbg(dev, "---->Download firmware\n"); - - ret = request_firmware(&fw, FIRMWARE_NAME, dev); - if (ret) { - dev_err(dev, "firmware file %s request failed (%d)\n", - FIRMWARE_NAME, ret); - goto end; - } - - for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) { - length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE); - - ret = vnt_control_out(priv, 0, 0x1200 + ii, 0x0000, length, - fw->data + ii); - if (ret) - goto free_fw; - - dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size); - } - -free_fw: - release_firmware(fw); -end: - return ret; -} - -static int vnt_firmware_branch_to_sram(struct vnt_private *priv) -{ - dev_dbg(&priv->usb->dev, "---->Branch to Sram\n"); - - return vnt_control_out(priv, 1, 0x1200, 0x0000, 0, NULL); -} - -static int vnt_check_firmware_version(struct vnt_private *priv) -{ - int ret = 0; - - ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0, - MESSAGE_REQUEST_VERSION, 2, - (u8 *)&priv->firmware_version); - if (ret) { - dev_dbg(&priv->usb->dev, - "Could not get firmware version: %d.\n", ret); - goto end; - } - - dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n", - priv->firmware_version); - - if (priv->firmware_version == 0xFFFF) { - dev_dbg(&priv->usb->dev, "In Loader.\n"); - ret = -EINVAL; - goto end; - } - - if (priv->firmware_version < FIRMWARE_VERSION) { - /* branch to loader for download new firmware */ - ret = vnt_firmware_branch_to_sram(priv); - if (ret) { - dev_dbg(&priv->usb->dev, - "Could not branch to SRAM: %d.\n", ret); - } else { - ret = -EINVAL; - } - } - -end: - return ret; -} - -/* - * initialization of MAC & BBP registers - */ -static int vnt_init_registers(struct vnt_private *priv) -{ - int ret; - struct vnt_cmd_card_init *init_cmd = &priv->init_command; - struct vnt_rsp_card_init *init_rsp = &priv->init_response; - u8 antenna; - int ii; - u8 tmp; - u8 calib_tx_iq = 0, calib_tx_dc = 0, calib_rx_iq = 0; - - dev_dbg(&priv->usb->dev, "---->INIbInitAdapter. [%d][%d]\n", - DEVICE_INIT_COLD, priv->packet_type); - - ret = vnt_check_firmware_version(priv); - if (ret) { - ret = vnt_download_firmware(priv); - if (ret) { - dev_dbg(&priv->usb->dev, - "Could not download firmware: %d.\n", ret); - goto end; - } - - ret = vnt_firmware_branch_to_sram(priv); - if (ret) { - dev_dbg(&priv->usb->dev, - "Could not branch to SRAM: %d.\n", ret); - goto end; - } - } - - ret = vnt_vt3184_init(priv); - if (ret) { - dev_dbg(&priv->usb->dev, "vnt_vt3184_init fail\n"); - goto end; - } - - init_cmd->init_class = DEVICE_INIT_COLD; - init_cmd->exist_sw_net_addr = priv->exist_sw_net_addr; - for (ii = 0; ii < ARRAY_SIZE(init_cmd->sw_net_addr); ii++) - init_cmd->sw_net_addr[ii] = priv->current_net_addr[ii]; - init_cmd->short_retry_limit = priv->hw->wiphy->retry_short; - init_cmd->long_retry_limit = priv->hw->wiphy->retry_long; - - /* issue card_init command to device */ - ret = vnt_control_out(priv, MESSAGE_TYPE_CARDINIT, 0, 0, - sizeof(struct vnt_cmd_card_init), - (u8 *)init_cmd); - if (ret) { - dev_dbg(&priv->usb->dev, "Issue Card init fail\n"); - goto end; - } - - ret = vnt_control_in(priv, MESSAGE_TYPE_INIT_RSP, 0, 0, - sizeof(struct vnt_rsp_card_init), - (u8 *)init_rsp); - if (ret) { - dev_dbg(&priv->usb->dev, "Cardinit request in status fail!\n"); - goto end; - } - - /* local ID for AES functions */ - ret = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_LOCALID, - MESSAGE_REQUEST_MACREG, 1, &priv->local_id); - if (ret) - goto end; - - /* do MACbSoftwareReset in MACvInitialize */ - - priv->top_ofdm_basic_rate = RATE_24M; - priv->top_cck_basic_rate = RATE_1M; - - /* target to IF pin while programming to RF chip */ - priv->power = 0xFF; - - priv->cck_pwr = priv->eeprom[EEP_OFS_PWR_CCK]; - priv->ofdm_pwr_g = priv->eeprom[EEP_OFS_PWR_OFDMG]; - /* load power table */ - for (ii = 0; ii < ARRAY_SIZE(priv->cck_pwr_tbl); ii++) { - priv->cck_pwr_tbl[ii] = - priv->eeprom[ii + EEP_OFS_CCK_PWR_TBL]; - if (priv->cck_pwr_tbl[ii] == 0) - priv->cck_pwr_tbl[ii] = priv->cck_pwr; - - priv->ofdm_pwr_tbl[ii] = - priv->eeprom[ii + EEP_OFS_OFDM_PWR_TBL]; - if (priv->ofdm_pwr_tbl[ii] == 0) - priv->ofdm_pwr_tbl[ii] = priv->ofdm_pwr_g; - } - - /* - * original zonetype is USA, but custom zonetype is Europe, - * then need to recover 12, 13, 14 channels with 11 channel - */ - for (ii = 11; ii < ARRAY_SIZE(priv->cck_pwr_tbl); ii++) { - priv->cck_pwr_tbl[ii] = priv->cck_pwr_tbl[10]; - priv->ofdm_pwr_tbl[ii] = priv->ofdm_pwr_tbl[10]; - } - - priv->ofdm_pwr_a = 0x34; /* same as RFbMA2829SelectChannel */ - - /* load OFDM A power table */ - for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { - priv->ofdm_a_pwr_tbl[ii] = - priv->eeprom[ii + EEP_OFS_OFDMA_PWR_TBL]; - - if (priv->ofdm_a_pwr_tbl[ii] == 0) - priv->ofdm_a_pwr_tbl[ii] = priv->ofdm_pwr_a; - } - - antenna = priv->eeprom[EEP_OFS_ANTENNA]; - - if (antenna & EEP_ANTINV) - priv->tx_rx_ant_inv = true; - else - priv->tx_rx_ant_inv = false; - - antenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - - if (antenna == 0) /* if not set default is both */ - antenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - - if (antenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { - priv->tx_antenna_mode = ANT_B; - priv->rx_antenna_sel = 1; - - if (priv->tx_rx_ant_inv) - priv->rx_antenna_mode = ANT_A; - else - priv->rx_antenna_mode = ANT_B; - } else { - priv->rx_antenna_sel = 0; - - if (antenna & EEP_ANTENNA_AUX) { - priv->tx_antenna_mode = ANT_A; - - if (priv->tx_rx_ant_inv) - priv->rx_antenna_mode = ANT_B; - else - priv->rx_antenna_mode = ANT_A; - } else { - priv->tx_antenna_mode = ANT_B; - - if (priv->tx_rx_ant_inv) - priv->rx_antenna_mode = ANT_A; - else - priv->rx_antenna_mode = ANT_B; - } - } - - /* Set initial antenna mode */ - ret = vnt_set_antenna_mode(priv, priv->rx_antenna_mode); - if (ret) - goto end; - - /* default Auto Mode */ - priv->bb_type = BB_TYPE_11G; - - /* get RFType */ - priv->rf_type = init_rsp->rf_type; - - /* load vt3266 calibration parameters in EEPROM */ - if (priv->rf_type == RF_VT3226D0) { - if ((priv->eeprom[EEP_OFS_MAJOR_VER] == 0x1) && - (priv->eeprom[EEP_OFS_MINOR_VER] >= 0x4)) { - calib_tx_iq = priv->eeprom[EEP_OFS_CALIB_TX_IQ]; - calib_tx_dc = priv->eeprom[EEP_OFS_CALIB_TX_DC]; - calib_rx_iq = priv->eeprom[EEP_OFS_CALIB_RX_IQ]; - if (calib_tx_iq || calib_tx_dc || calib_rx_iq) { - /* CR255, enable TX/RX IQ and - * DC compensation mode - */ - ret = vnt_control_out_u8(priv, - MESSAGE_REQUEST_BBREG, - 0xff, 0x03); - if (ret) - goto end; - - /* CR251, TX I/Q Imbalance Calibration */ - ret = vnt_control_out_u8(priv, - MESSAGE_REQUEST_BBREG, - 0xfb, calib_tx_iq); - if (ret) - goto end; - - /* CR252, TX DC-Offset Calibration */ - ret = vnt_control_out_u8(priv, - MESSAGE_REQUEST_BBREG, - 0xfC, calib_tx_dc); - if (ret) - goto end; - - /* CR253, RX I/Q Imbalance Calibration */ - ret = vnt_control_out_u8(priv, - MESSAGE_REQUEST_BBREG, - 0xfd, calib_rx_iq); - if (ret) - goto end; - } else { - /* CR255, turn off - * BB Calibration compensation - */ - ret = vnt_control_out_u8(priv, - MESSAGE_REQUEST_BBREG, - 0xff, 0x0); - if (ret) - goto end; - } - } - } - - /* get permanent network address */ - memcpy(priv->permanent_net_addr, init_rsp->net_addr, 6); - ether_addr_copy(priv->current_net_addr, priv->permanent_net_addr); - - /* if exist SW network address, use it */ - dev_dbg(&priv->usb->dev, "Network address = %pM\n", - priv->current_net_addr); - - priv->radio_ctl = priv->eeprom[EEP_OFS_RADIOCTL]; - - if ((priv->radio_ctl & EEP_RADIOCTL_ENABLE) != 0) { - ret = vnt_control_in(priv, MESSAGE_TYPE_READ, - MAC_REG_GPIOCTL1, MESSAGE_REQUEST_MACREG, - 1, &tmp); - if (ret) - goto end; - - if ((tmp & GPIO3_DATA) == 0) { - ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, - GPIO3_INTMD); - } else { - ret = vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, - GPIO3_INTMD); - } - - if (ret) - goto end; - } - - ret = vnt_mac_set_led(priv, LEDSTS_TMLEN, 0x38); - if (ret) - goto end; - - ret = vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW); - if (ret) - goto end; - - ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL0, BIT(0)); - if (ret) - goto end; - - ret = vnt_radio_power_on(priv); - if (ret) - goto end; - - dev_dbg(&priv->usb->dev, "<----INIbInitAdapter Exit\n"); - -end: - return ret; -} - -static void vnt_free_tx_bufs(struct vnt_private *priv) -{ - struct vnt_usb_send_context *tx_context; - int ii; - - usb_kill_anchored_urbs(&priv->tx_submitted); - - for (ii = 0; ii < priv->num_tx_context; ii++) { - tx_context = priv->tx_context[ii]; - if (!tx_context) - continue; - - kfree(tx_context); - } -} - -static void vnt_free_rx_bufs(struct vnt_private *priv) -{ - struct vnt_rcb *rcb; - int ii; - - for (ii = 0; ii < priv->num_rcb; ii++) { - rcb = priv->rcb[ii]; - if (!rcb) - continue; - - /* deallocate URBs */ - if (rcb->urb) { - usb_kill_urb(rcb->urb); - usb_free_urb(rcb->urb); - } - - /* deallocate skb */ - if (rcb->skb) - dev_kfree_skb(rcb->skb); - - kfree(rcb); - } -} - -static void vnt_free_int_bufs(struct vnt_private *priv) -{ - kfree(priv->int_buf.data_buf); -} - -static int vnt_alloc_bufs(struct vnt_private *priv) -{ - int ret; - struct vnt_usb_send_context *tx_context; - struct vnt_rcb *rcb; - int ii; - - init_usb_anchor(&priv->tx_submitted); - - for (ii = 0; ii < priv->num_tx_context; ii++) { - tx_context = kmalloc(sizeof(*tx_context), GFP_KERNEL); - if (!tx_context) { - ret = -ENOMEM; - goto free_tx; - } - - priv->tx_context[ii] = tx_context; - tx_context->priv = priv; - tx_context->pkt_no = ii; - tx_context->in_use = false; - } - - for (ii = 0; ii < priv->num_rcb; ii++) { - priv->rcb[ii] = kzalloc(sizeof(*priv->rcb[ii]), GFP_KERNEL); - if (!priv->rcb[ii]) { - ret = -ENOMEM; - goto free_rx_tx; - } - - rcb = priv->rcb[ii]; - - rcb->priv = priv; - - /* allocate URBs */ - rcb->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rcb->urb) { - ret = -ENOMEM; - goto free_rx_tx; - } - - rcb->skb = dev_alloc_skb(priv->rx_buf_sz); - if (!rcb->skb) { - ret = -ENOMEM; - goto free_rx_tx; - } - /* submit rx urb */ - ret = vnt_submit_rx_urb(priv, rcb); - if (ret) - goto free_rx_tx; - } - - priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!priv->interrupt_urb) { - ret = -ENOMEM; - goto free_rx_tx; - } - - priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL); - if (!priv->int_buf.data_buf) { - ret = -ENOMEM; - goto free_rx_tx_urb; - } - - return 0; - -free_rx_tx_urb: - usb_free_urb(priv->interrupt_urb); -free_rx_tx: - vnt_free_rx_bufs(priv); -free_tx: - vnt_free_tx_bufs(priv); - return ret; -} - -static void vnt_tx_80211(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct vnt_private *priv = hw->priv; - - if (vnt_tx_packet(priv, skb)) - ieee80211_free_txskb(hw, skb); -} - -static int vnt_start(struct ieee80211_hw *hw) -{ - int ret; - struct vnt_private *priv = hw->priv; - - priv->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS; - - ret = vnt_alloc_bufs(priv); - if (ret) { - dev_dbg(&priv->usb->dev, "vnt_alloc_bufs fail...\n"); - goto err; - } - - clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags); - - ret = vnt_init_registers(priv); - if (ret) { - dev_dbg(&priv->usb->dev, " init register fail\n"); - goto free_all; - } - - ret = vnt_key_init_table(priv); - if (ret) - goto free_all; - - priv->int_interval = 1; /* bInterval is set to 1 */ - - ret = vnt_start_interrupt_urb(priv); - if (ret) - goto free_all; - - ieee80211_wake_queues(hw); - - return 0; - -free_all: - vnt_free_rx_bufs(priv); - vnt_free_tx_bufs(priv); - vnt_free_int_bufs(priv); - - usb_kill_urb(priv->interrupt_urb); - usb_free_urb(priv->interrupt_urb); -err: - return ret; -} - -static void vnt_stop(struct ieee80211_hw *hw, bool suspend) -{ - struct vnt_private *priv = hw->priv; - int i; - - if (!priv) - return; - - for (i = 0; i < MAX_KEY_TABLE; i++) - vnt_mac_disable_keyentry(priv, i); - - /* clear all keys */ - priv->key_entry_inuse = 0; - - if (!test_bit(DEVICE_FLAGS_UNPLUG, &priv->flags)) - vnt_mac_shutdown(priv); - - ieee80211_stop_queues(hw); - - set_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags); - - cancel_delayed_work_sync(&priv->run_command_work); - - priv->cmd_running = false; - - vnt_free_tx_bufs(priv); - vnt_free_rx_bufs(priv); - vnt_free_int_bufs(priv); - - usb_kill_urb(priv->interrupt_urb); - usb_free_urb(priv->interrupt_urb); -} - -static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - priv->vif = vif; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_ADHOC: - vnt_mac_reg_bits_off(priv, MAC_REG_RCR, RCR_UNICAST); - - vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_ADHOC); - - break; - case NL80211_IFTYPE_AP: - vnt_mac_reg_bits_off(priv, MAC_REG_RCR, RCR_UNICAST); - - vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_AP); - - break; - default: - return -EOPNOTSUPP; - } - - priv->op_mode = vif->type; - - /* LED blink on TX */ - vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_INTER); - - return 0; -} - -static void vnt_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - break; - case NL80211_IFTYPE_ADHOC: - vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX); - vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_ADHOC); - break; - case NL80211_IFTYPE_AP: - vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX); - vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_AP); - break; - default: - break; - } - - vnt_radio_power_off(priv); - - priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; - - /* LED slow blink */ - vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW); -} - -static int vnt_config(struct ieee80211_hw *hw, u32 changed) -{ - struct vnt_private *priv = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) - vnt_enable_power_saving(priv, conf->listen_interval); - else - vnt_disable_power_saving(priv); - } - - if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || - (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { - vnt_set_channel(priv, conf->chandef.chan->hw_value); - - if (conf->chandef.chan->band == NL80211_BAND_5GHZ) - priv->bb_type = BB_TYPE_11A; - else - priv->bb_type = BB_TYPE_11G; - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) - vnt_rf_setpower(priv, conf->chandef.chan); - - if (conf->flags & (IEEE80211_CONF_OFFCHANNEL | IEEE80211_CONF_IDLE)) - /* Set max sensitivity*/ - vnt_update_pre_ed_threshold(priv, true); - else - vnt_update_pre_ed_threshold(priv, false); - - return 0; -} - -static void vnt_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, u64 changed) -{ - struct vnt_private *priv = hw->priv; - - priv->current_aid = vif->cfg.aid; - - if (changed & BSS_CHANGED_BSSID && conf->bssid) - vnt_mac_set_bssid_addr(priv, (u8 *)conf->bssid); - - if (changed & BSS_CHANGED_BASIC_RATES) { - priv->basic_rates = conf->basic_rates; - - vnt_update_top_rates(priv); - - dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates); - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - if (conf->use_short_preamble) { - vnt_mac_enable_barker_preamble_mode(priv); - priv->preamble_type = PREAMBLE_SHORT; - } else { - vnt_mac_disable_barker_preamble_mode(priv); - priv->preamble_type = PREAMBLE_LONG; - } - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - if (conf->use_cts_prot) - vnt_mac_enable_protect_mode(priv); - else - vnt_mac_disable_protect_mode(priv); - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - if (conf->use_short_slot) - priv->short_slot_time = true; - else - priv->short_slot_time = false; - - vnt_set_short_slot_time(priv); - vnt_set_vga_gain_offset(priv, priv->bb_vga[0]); - } - - if (changed & (BSS_CHANGED_BASIC_RATES | BSS_CHANGED_ERP_PREAMBLE | - BSS_CHANGED_ERP_SLOT)) - vnt_set_bss_mode(priv); - - if (changed & (BSS_CHANGED_TXPOWER | BSS_CHANGED_BANDWIDTH)) - vnt_rf_setpower(priv, conf->chanreq.oper.chan); - - if (changed & BSS_CHANGED_BEACON_ENABLED) { - dev_dbg(&priv->usb->dev, - "Beacon enable %d\n", conf->enable_beacon); - - if (conf->enable_beacon) { - vnt_beacon_enable(priv, vif, conf); - - vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX); - } else { - vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX); - } - } - - if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) && - priv->op_mode != NL80211_IFTYPE_AP) { - if (vif->cfg.assoc && conf->beacon_rate) { - u16 ps_beacon_int = conf->beacon_int; - - if (conf->dtim_period) - ps_beacon_int *= conf->dtim_period; - else if (hw->conf.listen_interval) - ps_beacon_int *= hw->conf.listen_interval; - - vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, - TFTCTL_TSFCNTREN); - - vnt_mac_set_beacon_interval(priv, ps_beacon_int); - - vnt_reset_next_tbtt(priv, conf->beacon_int); - - vnt_adjust_tsf(priv, conf->beacon_rate->hw_value, - conf->sync_tsf, priv->current_tsf); - - vnt_update_next_tbtt(priv, - conf->sync_tsf, ps_beacon_int); - } else { - vnt_clear_current_tsf(priv); - - vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, - TFTCTL_TSFCNTREN); - } - } -} - -static u64 vnt_prepare_multicast(struct ieee80211_hw *hw, - struct netdev_hw_addr_list *mc_list) -{ - struct vnt_private *priv = hw->priv; - struct netdev_hw_addr *ha; - u64 mc_filter = 0; - u32 bit_nr; - - netdev_hw_addr_list_for_each(ha, mc_list) { - bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter |= BIT_ULL(bit_nr); - } - - priv->mc_list_count = mc_list->count; - - return mc_filter; -} - -static void vnt_configure(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast) -{ - struct vnt_private *priv = hw->priv; - u8 rx_mode = 0; - - *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC; - - vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR, - MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode); - - dev_dbg(&priv->usb->dev, "rx mode in = %x\n", rx_mode); - - if (changed_flags & FIF_ALLMULTI) { - if (*total_flags & FIF_ALLMULTI) { - if (priv->mc_list_count > 2) - vnt_mac_set_filter(priv, ~0); - else - vnt_mac_set_filter(priv, multicast); - - rx_mode |= RCR_MULTICAST | RCR_BROADCAST; - } else { - rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); - } - } - - if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) { - if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) - rx_mode &= ~RCR_BSSID; - else - rx_mode |= RCR_BSSID; - } - - vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_RCR, rx_mode); - - dev_dbg(&priv->usb->dev, "rx mode out= %x\n", rx_mode); -} - -static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct vnt_private *priv = hw->priv; - - switch (cmd) { - case SET_KEY: - return vnt_set_keys(hw, sta, vif, key); - case DISABLE_KEY: - if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) { - clear_bit(key->hw_key_idx, &priv->key_entry_inuse); - - vnt_mac_disable_keyentry(priv, key->hw_key_idx); - } - break; - - default: - break; - } - - return 0; -} - -static int vnt_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct vnt_private *priv = hw->priv; - - memcpy(stats, &priv->low_stats, sizeof(*stats)); - - return 0; -} - -static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - return priv->current_tsf; -} - -static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 tsf) -{ - struct vnt_private *priv = hw->priv; - - vnt_update_next_tbtt(priv, tsf, vif->bss_conf.beacon_int); -} - -static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct vnt_private *priv = hw->priv; - - vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - - vnt_clear_current_tsf(priv); -} - -static const struct ieee80211_ops vnt_mac_ops = { - .add_chanctx = ieee80211_emulate_add_chanctx, - .remove_chanctx = ieee80211_emulate_remove_chanctx, - .change_chanctx = ieee80211_emulate_change_chanctx, - .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, - .tx = vnt_tx_80211, - .wake_tx_queue = ieee80211_handle_wake_tx_queue, - .start = vnt_start, - .stop = vnt_stop, - .add_interface = vnt_add_interface, - .remove_interface = vnt_remove_interface, - .config = vnt_config, - .bss_info_changed = vnt_bss_info_changed, - .prepare_multicast = vnt_prepare_multicast, - .configure_filter = vnt_configure, - .set_key = vnt_set_key, - .get_stats = vnt_get_stats, - .get_tsf = vnt_get_tsf, - .set_tsf = vnt_set_tsf, - .reset_tsf = vnt_reset_tsf, -}; - -int vnt_init(struct vnt_private *priv) -{ - if (vnt_init_registers(priv)) - return -EAGAIN; - - SET_IEEE80211_PERM_ADDR(priv->hw, priv->permanent_net_addr); - - vnt_init_bands(priv); - - if (ieee80211_register_hw(priv->hw)) - return -ENODEV; - - priv->mac_hw = true; - - vnt_radio_power_off(priv); - - return 0; -} - -static int -vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *udev; - struct vnt_private *priv; - struct ieee80211_hw *hw; - struct wiphy *wiphy; - int rc; - - udev = usb_get_dev(interface_to_usbdev(intf)); - - dev_notice(&udev->dev, "%s Ver. %s\n", - DEVICE_FULL_DRV_NAM, DEVICE_VERSION); - dev_notice(&udev->dev, - "Copyright (c) 2004 VIA Networking Technologies, Inc.\n"); - - hw = ieee80211_alloc_hw(sizeof(struct vnt_private), &vnt_mac_ops); - if (!hw) { - dev_err(&udev->dev, "could not register ieee80211_hw\n"); - rc = -ENOMEM; - goto err_nomem; - } - - priv = hw->priv; - priv->hw = hw; - priv->usb = udev; - priv->intf = intf; - - vnt_set_options(priv); - - spin_lock_init(&priv->lock); - mutex_init(&priv->usb_lock); - - INIT_DELAYED_WORK(&priv->run_command_work, vnt_run_command); - - usb_set_intfdata(intf, priv); - - wiphy = priv->hw->wiphy; - - wiphy->frag_threshold = FRAG_THRESH_DEF; - wiphy->rts_threshold = RTS_THRESH_DEF; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); - - ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY); - ieee80211_hw_set(priv->hw, SIGNAL_DBM); - ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); - ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(priv->hw, SUPPORTS_PS); - ieee80211_hw_set(priv->hw, PS_NULLFUNC_STACK); - - priv->hw->extra_tx_headroom = - sizeof(struct vnt_tx_buffer) + sizeof(struct vnt_tx_usb_header); - priv->hw->max_signal = 100; - - SET_IEEE80211_DEV(priv->hw, &intf->dev); - - rc = usb_reset_device(priv->usb); - if (rc) - dev_warn(&priv->usb->dev, - "%s reset fail status=%d\n", __func__, rc); - - clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags); - vnt_reset_command_timer(priv); - - vnt_schedule_command(priv, WLAN_CMD_INIT_MAC80211); - - return 0; - -err_nomem: - usb_put_dev(udev); - - return rc; -} - -static void vt6656_disconnect(struct usb_interface *intf) -{ - struct vnt_private *priv = usb_get_intfdata(intf); - - if (!priv) - return; - - if (priv->mac_hw) - ieee80211_unregister_hw(priv->hw); - - usb_set_intfdata(intf, NULL); - usb_put_dev(interface_to_usbdev(intf)); - - set_bit(DEVICE_FLAGS_UNPLUG, &priv->flags); - - ieee80211_free_hw(priv->hw); -} - -#ifdef CONFIG_PM - -static int vt6656_suspend(struct usb_interface *intf, pm_message_t message) -{ - return 0; -} - -static int vt6656_resume(struct usb_interface *intf) -{ - return 0; -} - -#endif /* CONFIG_PM */ - -MODULE_DEVICE_TABLE(usb, vt6656_table); - -static struct usb_driver vt6656_driver = { - .name = DEVICE_NAME, - .probe = vt6656_probe, - .disconnect = vt6656_disconnect, - .id_table = vt6656_table, -#ifdef CONFIG_PM - .suspend = vt6656_suspend, - .resume = vt6656_resume, -#endif /* CONFIG_PM */ -}; - -module_usb_driver(vt6656_driver); - -MODULE_FIRMWARE(FIRMWARE_NAME); diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c deleted file mode 100644 index e5411f6284c765fc997eb71615a393206ae41edf..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/power.c +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handles 802.11 power management functions - * - * Author: Lyndon Chen - * - * Date: July 17, 2002 - * - * Functions: - * vnt_enable_power_saving - Enable Power Saving Mode - * PSvDiasblePowerSaving - Disable Power Saving Mode - * vnt_next_tbtt_wakeup - Decide if we need to wake up at next Beacon - * - * Revision History: - * - */ - -#include "mac.h" -#include "device.h" -#include "power.h" -#include "wcmd.h" -#include "rxtx.h" -#include "card.h" -#include "usbpipe.h" - -/* - * - * Routine Description: - * Enable hw power saving functions - * - * Return Value: - * None. - * - */ - -void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval) -{ - u16 aid = priv->current_aid | BIT(14) | BIT(15); - - /* set period of power up before TBTT */ - vnt_mac_write_word(priv, MAC_REG_PWBT, C_PWBT); - - if (priv->op_mode != NL80211_IFTYPE_ADHOC) - /* set AID */ - vnt_mac_write_word(priv, MAC_REG_AIDATIM, aid); - - /* Warren:06-18-2004,the sequence must follow - * PSEN->AUTOSLEEP->GO2DOZE - */ - /* enable power saving hw function */ - vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_PSEN); - - /* Set AutoSleep */ - vnt_mac_reg_bits_on(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - - /* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the - * AUTOSLEEP doesn't work - */ - vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_GO2DOZE); - - /* always listen beacon */ - vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN); - - dev_dbg(&priv->usb->dev, "PS:Power Saving Mode Enable...\n"); -} - -int vnt_disable_power_saving(struct vnt_private *priv) -{ - int ret; - - /* disable power saving hw function */ - ret = vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0, - 0, 0, NULL); - if (ret) - return ret; - - /* clear AutoSleep */ - vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - - /* set always listen beacon */ - vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN); - - return 0; -} - -/* - * - * Routine Description: - * Check if Next TBTT must wake up - * - * Return Value: - * None. - * - */ - -int vnt_next_tbtt_wakeup(struct vnt_private *priv) -{ - struct ieee80211_hw *hw = priv->hw; - struct ieee80211_conf *conf = &hw->conf; - int wake_up = false; - - if (conf->listen_interval > 1) { - /* Turn on wake up to listen next beacon */ - vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN); - wake_up = true; - } - - return wake_up; -} diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h deleted file mode 100644 index 9f9c7007293345b33eda3f41e632b001399ac498..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/power.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handles 802.11 power management functions - * - * Author: Lyndon Chen - * - * Date: July 17, 2002 - * - */ - -#ifndef __POWER_H__ -#define __POWER_H__ - -#define C_PWBT 1000 /* micro sec. power up before TBTT */ - -int vnt_disable_power_saving(struct vnt_private *priv); -void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval); -int vnt_next_tbtt_wakeup(struct vnt_private *priv); - -#endif /* __POWER_H__ */ diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c deleted file mode 100644 index 464602c747270d6a308dc915f9cbf970067e7303..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/rf.c +++ /dev/null @@ -1,443 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: rf function code - * - * Author: Jerry Chen - * - * Date: Feb. 19, 2004 - * - * Functions: - * vnt_rf_write_embedded - Embedded write RF register via MAC - * - * Revision History: - * RF_VT3226: RobertYu:20051111, VT3226C0 and before - * RF_VT3226D0: RobertYu:20051228 - * RF_VT3342A0: RobertYu:20060609 - * - */ - -#include <linux/errno.h> -#include "mac.h" -#include "rf.h" -#include "baseband.h" -#include "usbpipe.h" - -#define CB_AL2230_INIT_SEQ 15 -#define CB_AL7230_INIT_SEQ 16 -#define CB_VT3226_INIT_SEQ 11 -#define CB_VT3342_INIT_SEQ 13 - -static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = { - {0x03, 0xf7, 0x90}, - {0x03, 0x33, 0x31}, - {0x01, 0xb8, 0x02}, - {0x00, 0xff, 0xf3}, - {0x00, 0x05, 0xa4}, - {0x0f, 0x4d, 0xc5}, - {0x08, 0x05, 0xb6}, - {0x01, 0x47, 0xc7}, - {0x00, 0x06, 0x88}, - {0x04, 0x03, 0xb9}, - {0x00, 0xdb, 0xba}, - {0x00, 0x09, 0x9b}, - {0x0b, 0xdf, 0xfc}, - {0x00, 0x00, 0x0d}, - {0x00, 0x58, 0x0f} -}; - -static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = { - {0x03, 0xf7, 0x90}, - {0x03, 0xf7, 0x90}, - {0x03, 0xe7, 0x90}, - {0x03, 0xe7, 0x90}, - {0x03, 0xf7, 0xa0}, - {0x03, 0xf7, 0xa0}, - {0x03, 0xe7, 0xa0}, - {0x03, 0xe7, 0xa0}, - {0x03, 0xf7, 0xb0}, - {0x03, 0xf7, 0xb0}, - {0x03, 0xe7, 0xb0}, - {0x03, 0xe7, 0xb0}, - {0x03, 0xf7, 0xc0}, - {0x03, 0xe7, 0xc0} -}; - -static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = { - {0x03, 0x33, 0x31}, - {0x0b, 0x33, 0x31}, - {0x03, 0x33, 0x31}, - {0x0b, 0x33, 0x31}, - {0x03, 0x33, 0x31}, - {0x0b, 0x33, 0x31}, - {0x03, 0x33, 0x31}, - {0x0b, 0x33, 0x31}, - {0x03, 0x33, 0x31}, - {0x0b, 0x33, 0x31}, - {0x03, 0x33, 0x31}, - {0x0b, 0x33, 0x31}, - {0x03, 0x33, 0x31}, - {0x06, 0x66, 0x61} -}; - -static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = { - {0x03, 0xff, 0x80}, - {0x02, 0x82, 0xa1}, - {0x03, 0xc6, 0xa2}, - {0x01, 0x97, 0x93}, - {0x03, 0x66, 0x64}, - {0x00, 0x61, 0xa5}, - {0x01, 0x7b, 0xd6}, - {0x00, 0x80, 0x17}, - {0x03, 0xf8, 0x08}, - {0x00, 0x02, 0x39}, - {0x02, 0x00, 0x2a} -}; - -static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = { - {0x03, 0xff, 0x80}, - {0x03, 0x02, 0x21}, - {0x03, 0xc6, 0xa2}, - {0x01, 0x97, 0x93}, - {0x03, 0x66, 0x64}, - {0x00, 0x71, 0xa5}, - {0x01, 0x15, 0xc6}, - {0x01, 0x2e, 0x07}, - {0x00, 0x58, 0x08}, - {0x00, 0x02, 0x79}, - {0x02, 0x01, 0xaa} -}; - -static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = { - {0x01, 0x97, 0x83}, - {0x01, 0x97, 0x83}, - {0x01, 0x97, 0x93}, - {0x01, 0x97, 0x93}, - {0x01, 0x97, 0x93}, - {0x01, 0x97, 0x93}, - {0x01, 0x97, 0xa3}, - {0x01, 0x97, 0xa3}, - {0x01, 0x97, 0xa3}, - {0x01, 0x97, 0xa3}, - {0x01, 0x97, 0xb3}, - {0x01, 0x97, 0xb3}, - {0x01, 0x97, 0xb3}, - {0x03, 0x37, 0xc3} -}; - -static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = { - {0x02, 0x66, 0x64}, - {0x03, 0x66, 0x64}, - {0x00, 0x66, 0x64}, - {0x01, 0x66, 0x64}, - {0x02, 0x66, 0x64}, - {0x03, 0x66, 0x64}, - {0x00, 0x66, 0x64}, - {0x01, 0x66, 0x64}, - {0x02, 0x66, 0x64}, - {0x03, 0x66, 0x64}, - {0x00, 0x66, 0x64}, - {0x01, 0x66, 0x64}, - {0x02, 0x66, 0x64}, - {0x00, 0xcc, 0xc4} -}; - -static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = { - 0x0135c600, - 0x0135c600, - 0x0235c600, - 0x0235c600, - 0x0235c600, - 0x0335c600, - 0x0335c600, - 0x0335c600, - 0x0335c600, - 0x0335c600, - 0x0335c600, - 0x0335c600, - 0x0335c600, - 0x0135c600 -}; - -enum { - VNT_TABLE_INIT = 0, - VNT_TABLE_INIT_2 = 0, - VNT_TABLE_0 = 1, - VNT_TABLE_1 = 2, - VNT_TABLE_2 = 1 -}; - -struct vnt_table_info { - u8 *addr; - int length; -}; - -static const struct vnt_table_info vnt_table_seq[][3] = { - { /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */ - {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3}, - {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, - {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} - }, { /* RF_VT3226 init table, channel table 0 and 1 */ - {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3}, - {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, - {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} - }, { /* RF_VT3226D0 init table, channel table 0 and 1 */ - {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3}, - {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3}, - {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3} - } -}; - -/* - * Description: Write to IF/RF, by embedded programming - */ -int vnt_rf_write_embedded(struct vnt_private *priv, u32 data) -{ - u8 reg_data[4]; - - data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW; - - reg_data[0] = (u8)data; - reg_data[1] = (u8)(data >> 8); - reg_data[2] = (u8)(data >> 16); - reg_data[3] = (u8)(data >> 24); - - return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0, - ARRAY_SIZE(reg_data), reg_data); -} - -static u8 vnt_rf_addpower(struct vnt_private *priv) -{ - int base; - s32 rssi = -priv->current_rssi; - - if (!rssi) - return 7; - - if (priv->rf_type == RF_VT3226D0) - base = -60; - else - base = -70; - - if (rssi < base) - return ((rssi - base + 1) / -5) * 2 + 5; - - return 0; -} - -/* Set Tx power by power level and rate */ -static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power, - struct ieee80211_channel *ch) -{ - u32 power_setting = 0; - int ret = 0; - - power += vnt_rf_addpower(priv); - if (power > VNT_RF_MAX_POWER) - power = VNT_RF_MAX_POWER; - - if (priv->power == power) - return 0; - - priv->power = power; - - switch (priv->rf_type) { - case RF_AL2230: - power_setting = 0x0404090 | (power << 12); - - ret = vnt_rf_write_embedded(priv, power_setting); - if (ret) - return ret; - - if (ch->flags & IEEE80211_CHAN_NO_OFDM) - ret = vnt_rf_write_embedded(priv, 0x0001b400); - else - ret = vnt_rf_write_embedded(priv, 0x0005a400); - - break; - case RF_AL2230S: - power_setting = 0x0404090 | (power << 12); - - ret = vnt_rf_write_embedded(priv, power_setting); - if (ret) - return ret; - - if (ch->flags & IEEE80211_CHAN_NO_OFDM) { - ret = vnt_rf_write_embedded(priv, 0x040c1400); - if (ret) - return ret; - - ret = vnt_rf_write_embedded(priv, 0x00299b00); - } else { - ret = vnt_rf_write_embedded(priv, 0x0005a400); - if (ret) - return ret; - - ret = vnt_rf_write_embedded(priv, 0x00099b00); - } - - break; - - case RF_VT3226: - power_setting = ((0x3f - power) << 20) | (0x17 << 8); - - ret = vnt_rf_write_embedded(priv, power_setting); - break; - case RF_VT3226D0: - if (ch->flags & IEEE80211_CHAN_NO_OFDM) { - u16 hw_value = ch->hw_value; - - power_setting = ((0x3f - power) << 20) | (0xe07 << 8); - - ret = vnt_rf_write_embedded(priv, power_setting); - if (ret) - return ret; - - ret = vnt_rf_write_embedded(priv, 0x03c6a200); - if (ret) - return ret; - - dev_dbg(&priv->usb->dev, - "%s 11b channel [%d]\n", __func__, hw_value); - - hw_value--; - - if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) { - ret = vnt_rf_write_embedded(priv, - vt3226d0_lo_current_table[hw_value]); - if (ret) - return ret; - } - - ret = vnt_rf_write_embedded(priv, 0x015C0800); - } else { - dev_dbg(&priv->usb->dev, - "@@@@ %s> 11G mode\n", __func__); - - power_setting = ((0x3f - power) << 20) | (0x7 << 8); - - ret = vnt_rf_write_embedded(priv, power_setting); - if (ret) - return ret; - - ret = vnt_rf_write_embedded(priv, 0x00C6A200); - if (ret) - return ret; - - ret = vnt_rf_write_embedded(priv, 0x016BC600); - if (ret) - return ret; - - ret = vnt_rf_write_embedded(priv, 0x00900800); - } - - break; - - default: - break; - } - return ret; -} - -/* Set Tx power by channel number type */ -int vnt_rf_setpower(struct vnt_private *priv, - struct ieee80211_channel *ch) -{ - u16 channel; - u8 power = priv->cck_pwr; - - if (!ch) - return -EINVAL; - - /* set channel number to array number */ - channel = ch->hw_value - 1; - - if (ch->flags & IEEE80211_CHAN_NO_OFDM) { - if (channel < ARRAY_SIZE(priv->cck_pwr_tbl)) - power = priv->cck_pwr_tbl[channel]; - } else if (ch->band == NL80211_BAND_5GHZ) { - /* remove 14 channels to array size */ - channel -= 14; - - if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl)) - power = priv->ofdm_a_pwr_tbl[channel]; - } else { - if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl)) - power = priv->ofdm_pwr_tbl[channel]; - } - - return vnt_rf_set_txpower(priv, power, ch); -} - -/* Convert rssi to dbm */ -void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm) -{ - u8 idx = ((rssi & 0xc0) >> 6) & 0x03; - long b = rssi & 0x3f; - long a = 0; - u8 airoharf[4] = {0, 18, 0, 40}; - - switch (priv->rf_type) { - case RF_AL2230: - case RF_AL2230S: - case RF_VT3226: - case RF_VT3226D0: - a = airoharf[idx]; - break; - default: - break; - } - - *dbm = -1 * (a + b * 2); -} - -int vnt_rf_table_download(struct vnt_private *priv) -{ - int ret; - int idx = -1; - const struct vnt_table_info *table_seq; - - switch (priv->rf_type) { - case RF_AL2230: - case RF_AL2230S: - idx = 0; - break; - case RF_VT3226: - idx = 1; - break; - case RF_VT3226D0: - idx = 2; - break; - } - - if (idx < 0) - return 0; - - table_seq = &vnt_table_seq[idx][0]; - - /* Init Table */ - ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0, - MESSAGE_REQUEST_RF_INIT, - table_seq[VNT_TABLE_INIT].length, - table_seq[VNT_TABLE_INIT].addr); - if (ret) - return ret; - - /* Channel Table 0 */ - ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, - MESSAGE_REQUEST_RF_CH0, - table_seq[VNT_TABLE_0].length, - table_seq[VNT_TABLE_0].addr); - if (ret) - return ret; - - /* Channel Table 1 */ - ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE, - MESSAGE_REQUEST_RF_CH1, - table_seq[VNT_TABLE_1].length, - table_seq[VNT_TABLE_1].addr); - - return ret; -} diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h deleted file mode 100644 index b47e149875d1db68c887a3e54f85115a6ab9aba5..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/rf.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: - * - * Author: Jerry Chen - * - * Date: Feb. 19, 2004 - * - */ - -#ifndef __RF_H__ -#define __RF_H__ - -#include "device.h" - -/* Baseband RF pair definition in eeprom (Bits 6..0) */ -#define RF_RFMD2959 0x01 -#define RF_MAXIMAG 0x02 -#define RF_AL2230 0x03 -#define RF_GCT5103 0x04 -#define RF_UW2451 0x05 -#define RF_MAXIMG 0x06 -#define RF_MAXIM2829 0x07 -#define RF_UW2452 0x08 -#define RF_VT3226 0x09 -#define RF_AIROHA7230 0x0a -#define RF_UW2453 0x0b -#define RF_VT3226D0 0x0c /* RobertYu:20051114 */ -#define RF_VT3342A0 0x0d /* RobertYu:20060609 */ -#define RF_AL2230S 0x0e - -#define RF_EMU 0x80 -#define RF_MASK 0x7F - -#define VNT_RF_MAX_POWER 0x3f -#define VNT_RF_REG_LEN 0x17 /* 24 bit length */ - -int vnt_rf_write_embedded(struct vnt_private *priv, u32 data); -int vnt_rf_setpower(struct vnt_private *priv, struct ieee80211_channel *ch); -void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm); -int vnt_rf_table_download(struct vnt_private *priv); - -#endif /* __RF_H__ */ diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c deleted file mode 100644 index cd99091c6c28fc8ade305bebd3413546decf1110..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/rxtx.c +++ /dev/null @@ -1,730 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: handle WMAC/802.3/802.11 rx & tx functions - * - * Author: Lyndon Chen - * - * Date: May 20, 2003 - * - * Functions: - * vnt_generate_tx_parameter - Generate tx dma required parameter. - * vnt_get_rsvtime- get frame reserved time - * vnt_fill_cts_head- fulfill CTS ctl header - * - * Revision History: - * - */ - -#include <linux/etherdevice.h> -#include "device.h" -#include "rxtx.h" -#include "card.h" -#include "mac.h" -#include "rf.h" -#include "usbpipe.h" - -static const u16 vnt_time_stampoff[2][MAX_RATE] = { - /* Long Preamble */ - {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, - - /* Short Preamble */ - {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, -}; - -#define DATADUR_B 10 -#define DATADUR_A 11 - -static const u8 vnt_phy_signal[] = { - 0x00, /* RATE_1M */ - 0x01, /* RATE_2M */ - 0x02, /* RATE_5M */ - 0x03, /* RATE_11M */ - 0x8b, /* RATE_6M */ - 0x8f, /* RATE_9M */ - 0x8a, /* RATE_12M */ - 0x8e, /* RATE_18M */ - 0x89, /* RATE_24M */ - 0x8d, /* RATE_36M */ - 0x88, /* RATE_48M */ - 0x8c /* RATE_54M */ -}; - -static struct vnt_usb_send_context - *vnt_get_free_context(struct vnt_private *priv) -{ - struct vnt_usb_send_context *context = NULL; - int ii; - - for (ii = 0; ii < priv->num_tx_context; ii++) { - if (!priv->tx_context[ii]) - return NULL; - - context = priv->tx_context[ii]; - if (!context->in_use) { - context->in_use = true; - return context; - } - } - - if (ii == priv->num_tx_context) { - dev_dbg(&priv->usb->dev, "%s No Free Tx Context\n", __func__); - - ieee80211_stop_queues(priv->hw); - } - - return NULL; -} - -/* Get Length, Service, and Signal fields of Phy for Tx */ -static void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length, - u16 tx_rate, u8 pkt_type, - struct vnt_phy_field *phy) -{ - u32 bit_count; - u32 count = 0; - u32 tmp; - int ext_bit; - int i; - u8 mask = 0; - u8 preamble_type = priv->preamble_type; - - bit_count = frame_length * 8; - ext_bit = false; - - switch (tx_rate) { - case RATE_1M: - count = bit_count; - break; - case RATE_2M: - count = bit_count / 2; - break; - case RATE_5M: - count = DIV_ROUND_UP(bit_count * 10, 55); - break; - case RATE_11M: - count = bit_count / 11; - tmp = count * 11; - - if (tmp != bit_count) { - count++; - - if ((bit_count - tmp) <= 3) - ext_bit = true; - } - - break; - } - - if (tx_rate > RATE_11M) { - if (pkt_type == PK_TYPE_11A) - mask = BIT(4); - } else if (tx_rate > RATE_1M) { - if (preamble_type == PREAMBLE_SHORT) - mask = BIT(3); - } - - i = tx_rate > RATE_54M ? RATE_54M : tx_rate; - phy->signal = vnt_phy_signal[i] | mask; - phy->service = 0x00; - - if (pkt_type == PK_TYPE_11B) { - if (ext_bit) - phy->service |= 0x80; - phy->len = cpu_to_le16((u16)count); - } else { - phy->len = cpu_to_le16((u16)frame_length); - } -} - -static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate) -{ - return cpu_to_le16(vnt_time_stampoff[priv->preamble_type % 2] - [rate % MAX_RATE]); -} - -static __le16 vnt_rxtx_rsvtime_le16(struct vnt_usb_send_context *context) -{ - struct vnt_private *priv = context->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb); - struct ieee80211_rate *rate = ieee80211_get_tx_rate(priv->hw, info); - - return ieee80211_generic_frame_duration(priv->hw, - info->control.vif, info->band, - context->frame_len, - rate); -} - -static __le16 vnt_get_rts_duration(struct vnt_usb_send_context *context) -{ - struct vnt_private *priv = context->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb); - - return ieee80211_rts_duration(priv->hw, priv->vif, - context->frame_len, info); -} - -static __le16 vnt_get_cts_duration(struct vnt_usb_send_context *context) -{ - struct vnt_private *priv = context->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb); - - return ieee80211_ctstoself_duration(priv->hw, priv->vif, - context->frame_len, info); -} - -static void vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, - struct vnt_tx_datahead_g *buf) -{ - struct vnt_private *priv = tx_context->priv; - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *)tx_context->skb->data; - u32 frame_len = tx_context->frame_len; - u16 rate = tx_context->tx_rate; - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a); - vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate, - PK_TYPE_11B, &buf->b); - - /* Get Duration and TimeStamp */ - buf->duration_a = hdr->duration_id; - buf->duration_b = hdr->duration_id; - buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); - buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); -} - -static void vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context, - struct vnt_tx_datahead_ab *buf) -{ - struct vnt_private *priv = tx_context->priv; - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *)tx_context->skb->data; - u32 frame_len = tx_context->frame_len; - u16 rate = tx_context->tx_rate; - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, frame_len, rate, - tx_context->pkt_type, &buf->ab); - - /* Get Duration and TimeStampOff */ - buf->duration = hdr->duration_id; - buf->time_stamp_off = vnt_time_stamp_off(priv, rate); -} - -static void vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context, - struct ieee80211_rts *rts, __le16 duration) -{ - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *)tx_context->skb->data; - - rts->duration = duration; - rts->frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); - - ether_addr_copy(rts->ra, hdr->addr1); - ether_addr_copy(rts->ta, hdr->addr2); -} - -static void vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context, - struct vnt_rts_g *buf) -{ - struct vnt_private *priv = tx_context->priv; - u16 rts_frame_len = 20; - - vnt_get_phy_field(priv, rts_frame_len, priv->top_cck_basic_rate, - PK_TYPE_11B, &buf->b); - vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate, - tx_context->pkt_type, &buf->a); - - buf->duration_bb = vnt_get_rts_duration(tx_context); - buf->duration_aa = buf->duration_bb; - buf->duration_ba = buf->duration_bb; - - vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa); - - vnt_rxtx_datahead_g(tx_context, &buf->data_head); -} - -static void vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context, - struct vnt_rts_ab *buf) -{ - struct vnt_private *priv = tx_context->priv; - u16 rts_frame_len = 20; - - vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate, - tx_context->pkt_type, &buf->ab); - - buf->duration = vnt_get_rts_duration(tx_context); - - vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration); - - vnt_rxtx_datahead_ab(tx_context, &buf->data_head); -} - -static void vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, - union vnt_tx_data_head *head) -{ - struct vnt_private *priv = tx_context->priv; - struct vnt_cts *buf = &head->cts_g; - u32 cts_frame_len = 14; - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, - PK_TYPE_11B, &buf->b); - /* Get CTSDuration_ba */ - buf->duration_ba = vnt_get_cts_duration(tx_context); - /*Get CTS Frame body*/ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - - ether_addr_copy(buf->data.ra, priv->current_net_addr); - - vnt_rxtx_datahead_g(tx_context, &buf->data_head); -} - -/* returns true if mic_hdr is needed */ -static bool vnt_fill_txkey(struct vnt_tx_buffer *tx_buffer, struct sk_buff *skb) -{ - struct vnt_tx_fifo_head *fifo = &tx_buffer->fifo_head; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_key_conf *tx_key = info->control.hw_key; - struct vnt_mic_hdr *mic_hdr; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u64 pn64; - u16 payload_len = skb->len; - u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb)); - - /* strip header and icv len from payload */ - payload_len -= ieee80211_get_hdrlen_from_skb(skb); - payload_len -= tx_key->icv_len; - - switch (tx_key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - memcpy(fifo->tx_key, iv, 3); - memcpy(fifo->tx_key + 3, tx_key->key, tx_key->keylen); - - if (tx_key->keylen == WLAN_KEY_LEN_WEP40) { - memcpy(fifo->tx_key + 8, iv, 3); - memcpy(fifo->tx_key + 11, - tx_key->key, WLAN_KEY_LEN_WEP40); - } - - fifo->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY); - break; - case WLAN_CIPHER_SUITE_TKIP: - ieee80211_get_tkip_p2k(tx_key, skb, fifo->tx_key); - - fifo->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP); - break; - case WLAN_CIPHER_SUITE_CCMP: - if (info->control.use_cts_prot) { - if (info->control.use_rts) - mic_hdr = &tx_buffer->tx_head.tx_rts.tx.mic.hdr; - else - mic_hdr = &tx_buffer->tx_head.tx_cts.tx.mic.hdr; - } else { - mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; - } - - mic_hdr->id = 0x59; - mic_hdr->payload_len = cpu_to_be16(payload_len); - ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2); - - pn64 = atomic64_read(&tx_key->tx_pn); - mic_hdr->ccmp_pn[5] = pn64; - mic_hdr->ccmp_pn[4] = pn64 >> 8; - mic_hdr->ccmp_pn[3] = pn64 >> 16; - mic_hdr->ccmp_pn[2] = pn64 >> 24; - mic_hdr->ccmp_pn[1] = pn64 >> 32; - mic_hdr->ccmp_pn[0] = pn64 >> 40; - - if (ieee80211_has_a4(hdr->frame_control)) - mic_hdr->hlen = cpu_to_be16(28); - else - mic_hdr->hlen = cpu_to_be16(22); - - ether_addr_copy(mic_hdr->addr1, hdr->addr1); - ether_addr_copy(mic_hdr->addr2, hdr->addr2); - ether_addr_copy(mic_hdr->addr3, hdr->addr3); - - mic_hdr->frame_control = cpu_to_le16(le16_to_cpu(hdr->frame_control) & 0xc78f); - mic_hdr->seq_ctrl = cpu_to_le16(le16_to_cpu(hdr->seq_ctrl) & 0xf); - - if (ieee80211_has_a4(hdr->frame_control)) - ether_addr_copy(mic_hdr->addr4, hdr->addr4); - - memcpy(fifo->tx_key, tx_key->key, WLAN_KEY_LEN_CCMP); - - fifo->frag_ctl |= cpu_to_le16(FRAGCTL_AES); - return true; - default: - break; - } - - return false; -} - -static void vnt_rxtx_rts(struct vnt_usb_send_context *tx_context) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb); - struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer; - union vnt_tx_head *tx_head = &tx_buffer->tx_head; - struct vnt_rrv_time_rts *buf = &tx_head->tx_rts.rts; - union vnt_tx_data_head *head = &tx_head->tx_rts.tx.head; - - buf->rts_rrv_time_aa = vnt_get_rts_duration(tx_context); - buf->rts_rrv_time_ba = buf->rts_rrv_time_aa; - buf->rts_rrv_time_bb = buf->rts_rrv_time_aa; - - buf->rrv_time_a = vnt_rxtx_rsvtime_le16(tx_context); - buf->rrv_time_b = buf->rrv_time_a; - - if (info->control.hw_key) { - if (vnt_fill_txkey(tx_buffer, tx_context->skb)) - head = &tx_head->tx_rts.tx.mic.head; - } - - vnt_rxtx_rts_g_head(tx_context, &head->rts_g); -} - -static void vnt_rxtx_cts(struct vnt_usb_send_context *tx_context) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb); - struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer; - union vnt_tx_head *tx_head = &tx_buffer->tx_head; - struct vnt_rrv_time_cts *buf = &tx_head->tx_cts.cts; - union vnt_tx_data_head *head = &tx_head->tx_cts.tx.head; - - buf->rrv_time_a = vnt_rxtx_rsvtime_le16(tx_context); - buf->rrv_time_b = buf->rrv_time_a; - - buf->cts_rrv_time_ba = vnt_get_cts_duration(tx_context); - - if (info->control.hw_key) { - if (vnt_fill_txkey(tx_buffer, tx_context->skb)) - head = &tx_head->tx_cts.tx.mic.head; - } - - vnt_fill_cts_head(tx_context, head); -} - -static void vnt_rxtx_ab(struct vnt_usb_send_context *tx_context) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb); - struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer; - union vnt_tx_head *tx_head = &tx_buffer->tx_head; - struct vnt_rrv_time_ab *buf = &tx_head->tx_ab.ab; - union vnt_tx_data_head *head = &tx_head->tx_ab.tx.head; - - buf->rrv_time = vnt_rxtx_rsvtime_le16(tx_context); - - if (info->control.hw_key) { - if (vnt_fill_txkey(tx_buffer, tx_context->skb)) - head = &tx_head->tx_ab.tx.mic.head; - } - - if (info->control.use_rts) { - buf->rts_rrv_time = vnt_get_rts_duration(tx_context); - - vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab); - - return; - } - - vnt_rxtx_datahead_ab(tx_context, &head->data_head_ab); -} - -static void vnt_generate_tx_parameter(struct vnt_usb_send_context *tx_context) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb); - - if (info->control.use_cts_prot) { - if (info->control.use_rts) { - vnt_rxtx_rts(tx_context); - - return; - } - - vnt_rxtx_cts(tx_context); - - return; - } - - vnt_rxtx_ab(tx_context); -} - -static u16 vnt_get_hdr_size(struct ieee80211_tx_info *info) -{ - u16 size = sizeof(struct vnt_tx_datahead_ab); - - if (info->control.use_cts_prot) { - if (info->control.use_rts) - size = sizeof(struct vnt_rts_g); - else - size = sizeof(struct vnt_cts); - } else if (info->control.use_rts) { - size = sizeof(struct vnt_rts_ab); - } - - if (info->control.hw_key) { - if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP) - size += sizeof(struct vnt_mic_hdr); - } - - /* Get rrv_time header */ - if (info->control.use_cts_prot) { - if (info->control.use_rts) - size += sizeof(struct vnt_rrv_time_rts); - else - size += sizeof(struct vnt_rrv_time_cts); - } else { - size += sizeof(struct vnt_rrv_time_ab); - } - - size += sizeof(struct vnt_tx_fifo_head); - - return size; -} - -int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *tx_rate = &info->control.rates[0]; - struct ieee80211_rate *rate; - struct ieee80211_hdr *hdr; - struct vnt_tx_buffer *tx_buffer; - struct vnt_tx_fifo_head *tx_buffer_head; - struct vnt_usb_send_context *tx_context; - unsigned long flags; - u8 pkt_type; - - hdr = (struct ieee80211_hdr *)(skb->data); - - rate = ieee80211_get_tx_rate(priv->hw, info); - - if (rate->hw_value > RATE_11M) { - if (info->band == NL80211_BAND_5GHZ) { - pkt_type = PK_TYPE_11A; - } else { - if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - if (priv->basic_rates & VNT_B_RATES) - pkt_type = PK_TYPE_11GB; - else - pkt_type = PK_TYPE_11GA; - } else { - pkt_type = PK_TYPE_11A; - } - } - } else { - pkt_type = PK_TYPE_11B; - } - - spin_lock_irqsave(&priv->lock, flags); - - tx_context = vnt_get_free_context(priv); - if (!tx_context) { - dev_dbg(&priv->usb->dev, "%s No free context\n", __func__); - spin_unlock_irqrestore(&priv->lock, flags); - return -ENOMEM; - } - - tx_context->pkt_type = pkt_type; - tx_context->frame_len = skb->len + 4; - tx_context->tx_rate = rate->hw_value; - - spin_unlock_irqrestore(&priv->lock, flags); - - tx_context->skb = skb_clone(skb, GFP_ATOMIC); - if (!tx_context->skb) { - tx_context->in_use = false; - return -ENOMEM; - } - - tx_buffer = skb_push(skb, vnt_get_hdr_size(info)); - tx_context->tx_buffer = tx_buffer; - tx_buffer_head = &tx_buffer->fifo_head; - - tx_context->type = CONTEXT_DATA_PACKET; - - /*Set fifo controls */ - if (pkt_type == PK_TYPE_11A) - tx_buffer_head->fifo_ctl = 0; - else if (pkt_type == PK_TYPE_11B) - tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B); - else if (pkt_type == PK_TYPE_11GB) - tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB); - else if (pkt_type == PK_TYPE_11GA) - tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA); - - if (!ieee80211_is_data(hdr->frame_control)) { - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT | - FIFOCTL_ISDMA0); - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN); - - tx_buffer_head->time_stamp = - cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); - } else { - tx_buffer_head->time_stamp = - cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us); - } - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK); - - if (ieee80211_has_retry(hdr->frame_control)) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY); - - if (info->control.use_rts) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS); - - if (ieee80211_has_a4(hdr->frame_control)) - tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD); - - tx_buffer_head->frag_ctl = - cpu_to_le16(ieee80211_hdrlen(hdr->frame_control) << 10); - - if (info->control.hw_key) - tx_context->frame_len += info->control.hw_key->icv_len; - - tx_buffer_head->current_rate = cpu_to_le16(rate->hw_value); - - vnt_generate_tx_parameter(tx_context); - - tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG); - - priv->seq_counter = (le16_to_cpu(hdr->seq_ctrl) & - IEEE80211_SCTL_SEQ) >> 4; - - spin_lock_irqsave(&priv->lock, flags); - - if (vnt_tx_context(priv, tx_context, skb)) { - dev_kfree_skb(tx_context->skb); - spin_unlock_irqrestore(&priv->lock, flags); - return -EIO; - } - - dev_kfree_skb(skb); - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb) -{ - struct vnt_tx_short_buf_head *short_head; - struct ieee80211_tx_info *info; - struct vnt_usb_send_context *context; - struct ieee80211_mgmt *mgmt_hdr; - unsigned long flags; - u32 frame_size = skb->len + 4; - u16 current_rate; - - spin_lock_irqsave(&priv->lock, flags); - - context = vnt_get_free_context(priv); - if (!context) { - dev_dbg(&priv->usb->dev, "%s No free context!\n", __func__); - spin_unlock_irqrestore(&priv->lock, flags); - return -ENOMEM; - } - - context->skb = skb; - - spin_unlock_irqrestore(&priv->lock, flags); - - mgmt_hdr = (struct ieee80211_mgmt *)skb->data; - short_head = skb_push(skb, sizeof(*short_head)); - - if (priv->bb_type == BB_TYPE_11A) { - current_rate = RATE_6M; - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, frame_size, current_rate, - PK_TYPE_11A, &short_head->ab); - - /* Get TimeStampOff */ - short_head->time_stamp_off = - vnt_time_stamp_off(priv, current_rate); - } else { - current_rate = RATE_1M; - short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B); - - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, frame_size, current_rate, - PK_TYPE_11B, &short_head->ab); - - /* Get TimeStampOff */ - short_head->time_stamp_off = - vnt_time_stamp_off(priv, current_rate); - } - - /* Get Duration */ - short_head->duration = mgmt_hdr->duration; - - /* time stamp always 0 */ - mgmt_hdr->u.beacon.timestamp = 0; - - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr; - - hdr->duration_id = 0; - hdr->seq_ctrl = cpu_to_le16(priv->seq_counter << 4); - } - - priv->seq_counter++; - if (priv->seq_counter > 0x0fff) - priv->seq_counter = 0; - - context->type = CONTEXT_BEACON_PACKET; - - spin_lock_irqsave(&priv->lock, flags); - - if (vnt_tx_context(priv, context, skb)) - ieee80211_free_txskb(priv->hw, context->skb); - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif) -{ - struct sk_buff *beacon; - - beacon = ieee80211_beacon_get(priv->hw, vif, 0); - if (!beacon) - return -ENOMEM; - - if (vnt_beacon_xmit(priv, beacon)) { - ieee80211_free_txskb(priv->hw, beacon); - return -ENODEV; - } - - return 0; -} - -int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf) -{ - vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX); - - vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - - vnt_mac_set_beacon_interval(priv, conf->beacon_int); - - vnt_clear_current_tsf(priv); - - vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); - - vnt_reset_next_tbtt(priv, conf->beacon_int); - - return vnt_beacon_make(priv, vif); -} diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h deleted file mode 100644 index b9df0854b4b01153fd30947d1f79593a008a2f0a..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/rxtx.h +++ /dev/null @@ -1,178 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: - * - * Author: Jerry Chen - * - * Date: Jun. 27, 2002 - * - */ - -#ifndef __RXTX_H__ -#define __RXTX_H__ - -#include "device.h" -#include "wcmd.h" -#include "baseband.h" - -#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */ -#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 - -/* Length, Service, and Signal fields of Phy for Tx */ -struct vnt_phy_field { - u8 signal; - u8 service; - __le16 len; -} __packed; - -/* MIC HDR data header */ -struct vnt_mic_hdr { - u8 id; - u8 tx_priority; - u8 mic_addr2[6]; - u8 ccmp_pn[IEEE80211_CCMP_PN_LEN]; - __be16 payload_len; - __be16 hlen; - __le16 frame_control; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - __le16 seq_ctrl; - u8 addr4[6]; - u16 packing; /* packing to 48 bytes */ -} __packed; - -/* RsvTime buffer header */ -struct vnt_rrv_time_rts { - __le16 rts_rrv_time_ba; - __le16 rts_rrv_time_aa; - __le16 rts_rrv_time_bb; - u16 wReserved; - __le16 rrv_time_b; - __le16 rrv_time_a; -} __packed; - -struct vnt_rrv_time_cts { - __le16 cts_rrv_time_ba; - u16 wReserved; - __le16 rrv_time_b; - __le16 rrv_time_a; -} __packed; - -struct vnt_rrv_time_ab { - __le16 rts_rrv_time; - __le16 rrv_time; -} __packed; - -/* TX data header */ -struct vnt_tx_datahead_g { - struct vnt_phy_field b; - struct vnt_phy_field a; - __le16 duration_b; - __le16 duration_a; - __le16 time_stamp_off_b; - __le16 time_stamp_off_a; -} __packed; - -struct vnt_tx_datahead_ab { - struct vnt_phy_field ab; - __le16 duration; - __le16 time_stamp_off; -} __packed; - -/* RTS buffer header */ -struct vnt_rts_g { - struct vnt_phy_field b; - struct vnt_phy_field a; - __le16 duration_ba; - __le16 duration_aa; - __le16 duration_bb; - u16 wReserved; - struct ieee80211_rts data; - struct vnt_tx_datahead_g data_head; -} __packed __aligned(2); - -struct vnt_rts_ab { - struct vnt_phy_field ab; - __le16 duration; - u16 wReserved; - struct ieee80211_rts data; - struct vnt_tx_datahead_ab data_head; -} __packed __aligned(2); - -/* CTS buffer header */ -struct vnt_cts { - struct vnt_phy_field b; - __le16 duration_ba; - u16 wReserved; - struct ieee80211_cts data; - u16 reserved2; - struct vnt_tx_datahead_g data_head; -} __packed __aligned(2); - -union vnt_tx_data_head { - /* rts g */ - struct vnt_rts_g rts_g; - /* rts a/b */ - struct vnt_rts_ab rts_ab; - /* cts g */ - struct vnt_cts cts_g; - /* no rts/cts */ - struct vnt_tx_datahead_ab data_head_ab; -}; - -struct vnt_tx_mic_hdr { - struct vnt_mic_hdr hdr; - union vnt_tx_data_head head; -} __packed; - -union vnt_tx { - struct vnt_tx_mic_hdr mic; - union vnt_tx_data_head head; -}; - -union vnt_tx_head { - struct { - struct vnt_rrv_time_rts rts; - union vnt_tx tx; - } __packed tx_rts; - struct { - struct vnt_rrv_time_cts cts; - union vnt_tx tx; - } __packed tx_cts; - struct { - struct vnt_rrv_time_ab ab; - union vnt_tx tx; - } __packed tx_ab; -}; - -struct vnt_tx_fifo_head { - u8 tx_key[WLAN_KEY_LEN_CCMP]; - __le16 fifo_ctl; - __le16 time_stamp; - __le16 frag_ctl; - __le16 current_rate; -} __packed; - -struct vnt_tx_buffer { - struct vnt_tx_fifo_head fifo_head; - union vnt_tx_head tx_head; -} __packed; - -struct vnt_tx_short_buf_head { - __le16 fifo_ctl; - u16 time_stamp; - struct vnt_phy_field ab; - __le16 duration; - __le16 time_stamp_off; -} __packed; - -int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb); -int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif); -int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf); - -#endif /* __RXTX_H__ */ diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c deleted file mode 100644 index d505b4b69ba4933699ac212681c9dea1e1a8a1df..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/usbpipe.c +++ /dev/null @@ -1,506 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handle USB control endpoint - * - * Author: Warren Hsu - * - * Date: Mar. 29, 2005 - * - * Functions: - * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM - * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM - * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM - * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM - * - * Revision History: - * 04-05-2004 Jerry Chen: Initial release - * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte, - * ControlvMaskByte - * - */ - -#include "rxtx.h" -#include "desc.h" -#include "device.h" -#include "usbpipe.h" -#include "mac.h" -#include "rf.h" - -#define USB_CTL_WAIT 500 /* ms */ - -int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, const u8 *buffer) -{ - int ret = 0; - u8 *usb_buffer; - - if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) { - ret = -EINVAL; - goto end; - } - - mutex_lock(&priv->usb_lock); - - usb_buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!usb_buffer) { - ret = -ENOMEM; - goto end_unlock; - } - - ret = usb_control_msg(priv->usb, - usb_sndctrlpipe(priv->usb, 0), - request, 0x40, value, - index, usb_buffer, length, USB_CTL_WAIT); - - kfree(usb_buffer); - - if (ret == (int)length) - ret = 0; - else - ret = -EIO; - -end_unlock: - mutex_unlock(&priv->usb_lock); -end: - return ret; -} - -int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data) -{ - return vnt_control_out(priv, MESSAGE_TYPE_WRITE, - reg_off, reg, sizeof(u8), &data); -} - -int vnt_control_out_blocks(struct vnt_private *priv, - u16 block, u8 reg, u16 length, const u8 *data) -{ - int ret = 0, i; - - for (i = 0; i < length; i += block) { - u16 len = min_t(int, length - i, block); - - ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, - i, reg, len, data + i); - if (ret) - goto end; - } -end: - return ret; -} - -int vnt_control_in(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, u8 *buffer) -{ - int ret = 0; - u8 *usb_buffer; - - if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) { - ret = -EINVAL; - goto end; - } - - mutex_lock(&priv->usb_lock); - - usb_buffer = kmalloc(length, GFP_KERNEL); - if (!usb_buffer) { - ret = -ENOMEM; - goto end_unlock; - } - - ret = usb_control_msg(priv->usb, - usb_rcvctrlpipe(priv->usb, 0), - request, 0xc0, value, - index, usb_buffer, length, USB_CTL_WAIT); - - if (ret == length) - memcpy(buffer, usb_buffer, length); - - kfree(usb_buffer); - - if (ret == (int)length) - ret = 0; - else - ret = -EIO; - -end_unlock: - mutex_unlock(&priv->usb_lock); -end: - return ret; -} - -int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data) -{ - return vnt_control_in(priv, MESSAGE_TYPE_READ, - reg_off, reg, sizeof(u8), data); -} - -static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr) -{ - struct vnt_usb_send_context *context; - struct ieee80211_tx_info *info; - u8 tx_retry = (tsr & 0xf0) >> 4; - s8 idx; - - if (pkt_no >= priv->num_tx_context) - return -EINVAL; - - context = priv->tx_context[pkt_no]; - - if (!context->skb) - return -EINVAL; - - info = IEEE80211_SKB_CB(context->skb); - idx = info->control.rates[0].idx; - - ieee80211_tx_info_clear_status(info); - - info->status.rates[0].count = tx_retry; - - if (!(tsr & TSR_TMO)) { - info->status.rates[0].idx = idx; - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - info->flags |= IEEE80211_TX_STAT_ACK; - } - - ieee80211_tx_status_irqsafe(priv->hw, context->skb); - - context->in_use = false; - - return 0; -} - -static void vnt_int_process_data(struct vnt_private *priv) -{ - struct vnt_interrupt_data *int_data; - struct ieee80211_low_level_stats *low_stats = &priv->low_stats; - - dev_dbg(&priv->usb->dev, "---->s_nsInterruptProcessData\n"); - - int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf; - - if (int_data->tsr0 & TSR_VALID) - vnt_int_report_rate(priv, int_data->pkt0, int_data->tsr0); - - if (int_data->tsr1 & TSR_VALID) - vnt_int_report_rate(priv, int_data->pkt1, int_data->tsr1); - - if (int_data->tsr2 & TSR_VALID) - vnt_int_report_rate(priv, int_data->pkt2, int_data->tsr2); - - if (int_data->tsr3 & TSR_VALID) - vnt_int_report_rate(priv, int_data->pkt3, int_data->tsr3); - - if (!int_data->isr0) - return; - - if (int_data->isr0 & ISR_BNTX && priv->op_mode == NL80211_IFTYPE_AP) - vnt_schedule_command(priv, WLAN_CMD_BECON_SEND); - - priv->current_tsf = le64_to_cpu(int_data->tsf); - - low_stats->dot11RTSSuccessCount += int_data->rts_success; - low_stats->dot11RTSFailureCount += int_data->rts_fail; - low_stats->dot11ACKFailureCount += int_data->ack_fail; - low_stats->dot11FCSErrorCount += int_data->fcs_err; -} - -static void vnt_start_interrupt_urb_complete(struct urb *urb) -{ - struct vnt_private *priv = urb->context; - int status = urb->status; - - switch (status) { - case 0: - case -ETIMEDOUT: - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - default: - break; - } - - if (status) - dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status); - else - vnt_int_process_data(priv); - - if (!test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) - status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC); - - if (status) - dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status); -} - -int vnt_start_interrupt_urb(struct vnt_private *priv) -{ - int ret = 0; - - dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n"); - - usb_fill_int_urb(priv->interrupt_urb, - priv->usb, - usb_rcvintpipe(priv->usb, 1), - priv->int_buf.data_buf, - MAX_INTERRUPT_SIZE, - vnt_start_interrupt_urb_complete, - priv, - priv->int_interval); - - ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC); - if (ret) - dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret); - - return ret; -} - -static int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, - unsigned long bytes_received) -{ - struct ieee80211_hw *hw = priv->hw; - struct ieee80211_supported_band *sband; - struct sk_buff *skb; - struct ieee80211_rx_status *rx_status; - struct vnt_rx_header *head; - struct vnt_rx_tail *tail; - u32 frame_size; - int ii; - u16 rx_bitrate, pay_load_with_padding; - u8 rate_idx = 0; - long rx_dbm; - - skb = ptr_rcb->skb; - rx_status = IEEE80211_SKB_RXCB(skb); - - /* [31:16]RcvByteCount ( not include 4-byte Status ) */ - head = (struct vnt_rx_header *)skb->data; - frame_size = head->wbk_status >> 16; - frame_size += 4; - - if (bytes_received != frame_size) { - dev_dbg(&priv->usb->dev, "------- WRONG Length 1\n"); - return false; - } - - if ((bytes_received > 2372) || (bytes_received <= 40)) { - /* Frame Size error drop this packet.*/ - dev_dbg(&priv->usb->dev, "------ WRONG Length 2\n"); - return false; - } - - /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */ - /* -8TSF - 4RSR - 4SQ3 - ?Padding */ - - /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */ - - /*Fix hardware bug => PLCP_Length error */ - if (((bytes_received - head->pay_load_len) > 27) || - ((bytes_received - head->pay_load_len) < 24) || - (bytes_received < head->pay_load_len)) { - dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n", - head->pay_load_len); - return false; - } - - sband = hw->wiphy->bands[hw->conf.chandef.chan->band]; - rx_bitrate = head->rx_rate * 5; /* rx_rate * 5 */ - - for (ii = 0; ii < sband->n_bitrates; ii++) { - if (sband->bitrates[ii].bitrate == rx_bitrate) { - rate_idx = ii; - break; - } - } - - if (ii == sband->n_bitrates) { - dev_dbg(&priv->usb->dev, "Wrong Rx Bit Rate %d\n", rx_bitrate); - return false; - } - - pay_load_with_padding = ((head->pay_load_len / 4) + - ((head->pay_load_len % 4) ? 1 : 0)) * 4; - - tail = (struct vnt_rx_tail *)(skb->data + - sizeof(*head) + pay_load_with_padding); - priv->tsf_time = le64_to_cpu(tail->tsf_time); - - if (tail->rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) - return false; - - vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm); - - priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1; - priv->current_rssi = priv->bb_pre_ed_rssi; - - skb_pull(skb, sizeof(*head)); - skb_trim(skb, head->pay_load_len); - - rx_status->mactime = priv->tsf_time; - rx_status->band = hw->conf.chandef.chan->band; - rx_status->signal = rx_dbm; - rx_status->flag = 0; - rx_status->freq = hw->conf.chandef.chan->center_freq; - - if (!(tail->rsr & RSR_CRCOK)) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - rx_status->rate_idx = rate_idx; - - if (tail->new_rsr & NEWRSR_DECRYPTOK) - rx_status->flag |= RX_FLAG_DECRYPTED; - - ieee80211_rx_irqsafe(priv->hw, skb); - - return true; -} - -static void vnt_submit_rx_urb_complete(struct urb *urb) -{ - struct vnt_rcb *rcb = urb->context; - struct vnt_private *priv = rcb->priv; - - switch (urb->status) { - case 0: - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - case -ETIMEDOUT: - default: - dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status); - break; - } - - if (urb->actual_length) { - if (vnt_rx_data(priv, rcb, urb->actual_length)) { - rcb->skb = dev_alloc_skb(priv->rx_buf_sz); - if (!rcb->skb) - return; - } else { - skb_push(rcb->skb, skb_headroom(rcb->skb)); - skb_trim(rcb->skb, 0); - } - - urb->transfer_buffer = skb_put(rcb->skb, - skb_tailroom(rcb->skb)); - } - - if (usb_submit_urb(urb, GFP_ATOMIC)) - dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n"); -} - -int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb) -{ - int ret = 0; - struct urb *urb = rcb->urb; - - if (!rcb->skb) { - dev_dbg(&priv->usb->dev, "rcb->skb is null\n"); - ret = -EINVAL; - goto end; - } - - usb_fill_bulk_urb(urb, - priv->usb, - usb_rcvbulkpipe(priv->usb, 2), - skb_put(rcb->skb, skb_tailroom(rcb->skb)), - MAX_TOTAL_SIZE_WITH_ALL_HEADERS, - vnt_submit_rx_urb_complete, - rcb); - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret); -end: - return ret; -} - -static void vnt_tx_context_complete(struct urb *urb) -{ - struct vnt_usb_send_context *context = urb->context; - struct vnt_private *priv = context->priv; - - switch (urb->status) { - case 0: - dev_dbg(&priv->usb->dev, - "Write %d bytes\n", urb->actual_length); - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - context->in_use = false; - return; - case -ETIMEDOUT: - default: - dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status); - break; - } - - if (context->type == CONTEXT_DATA_PACKET) - ieee80211_wake_queues(priv->hw); - - if (urb->status || context->type == CONTEXT_BEACON_PACKET) { - if (context->skb) - ieee80211_free_txskb(priv->hw, context->skb); - - context->in_use = false; - } -} - -int vnt_tx_context(struct vnt_private *priv, - struct vnt_usb_send_context *context, - struct sk_buff *skb) -{ - struct vnt_tx_usb_header *usb; - struct urb *urb; - int status; - u16 count = skb->len; - - usb = skb_push(skb, sizeof(*usb)); - usb->tx_byte_count = cpu_to_le16(count); - usb->pkt_no = context->pkt_no; - usb->type = context->type; - - if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) { - context->in_use = false; - return -ENODEV; - } - - if (skb->len > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) { - context->in_use = false; - return -E2BIG; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - context->in_use = false; - return -ENOMEM; - } - - usb_fill_bulk_urb(urb, - priv->usb, - usb_sndbulkpipe(priv->usb, 3), - skb->data, - skb->len, - vnt_tx_context_complete, - context); - - usb_anchor_urb(urb, &priv->tx_submitted); - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status); - usb_unanchor_urb(urb); - context->in_use = false; - } - - usb_free_urb(urb); - - return status; -} diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h deleted file mode 100644 index 922312e299bf64ff2446011a9c358215fbe5388e..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/usbpipe.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: - * - * Author: Warren Hsu - * - * Date: Mar. 30, 2005 - * - */ - -#ifndef __USBPIPE_H__ -#define __USBPIPE_H__ - -#include "device.h" - -struct vnt_interrupt_data { - u8 tsr0; - u8 pkt0; - u16 time0; - u8 tsr1; - u8 pkt1; - u16 time1; - u8 tsr2; - u8 pkt2; - u16 time2; - u8 tsr3; - u8 pkt3; - u16 time3; - __le64 tsf; - u8 isr0; - u8 isr1; - u8 rts_success; - u8 rts_fail; - u8 ack_fail; - u8 fcs_err; - u8 sw[2]; -} __packed; - -struct vnt_tx_usb_header { - u8 type; - u8 pkt_no; - __le16 tx_byte_count; -} __packed; - -#define VNT_REG_BLOCK_SIZE 64 - -int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, const u8 *buffer); -int vnt_control_in(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, u8 *buffer); - -int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data); -int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data); - -int vnt_control_out_blocks(struct vnt_private *priv, - u16 block, u8 reg, u16 len, const u8 *data); - -int vnt_start_interrupt_urb(struct vnt_private *priv); -int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb); -int vnt_tx_context(struct vnt_private *priv, - struct vnt_usb_send_context *context, - struct sk_buff *skb); - -#endif /* __USBPIPE_H__ */ diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c deleted file mode 100644 index 14b8aa58711906358d3231444e527bd457f94694..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/wcmd.c +++ /dev/null @@ -1,185 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handles the management command interface functions - * - * Author: Lyndon Chen - * - * Date: May 8, 2003 - * - * Functions: - * vnt_cmd_complete - Command Complete function - * vnt_schedule_command - Push Command and wait Command Scheduler to do - * vnt_cmd_timer_wait- Call back timer - * - * Revision History: - * - */ - -#include "device.h" -#include "mac.h" -#include "wcmd.h" -#include "power.h" -#include "usbpipe.h" -#include "rxtx.h" -#include "rf.h" - -static void vnt_cmd_timer_wait(struct vnt_private *priv, unsigned long msecs) -{ - schedule_delayed_work(&priv->run_command_work, msecs_to_jiffies(msecs)); -} - -static u32 add_one_with_wrap_around(u32 var, u8 modulo) -{ - if (var >= (modulo - 1)) - var = 0; - else - var++; - return var; -} - -static int vnt_cmd_complete(struct vnt_private *priv) -{ - priv->command_state = WLAN_CMD_IDLE; - if (priv->free_cmd_queue == CMD_Q_SIZE) { - /* Command Queue Empty */ - priv->cmd_running = false; - return true; - } - - priv->command = priv->cmd_queue[priv->cmd_dequeue_idx]; - - priv->cmd_dequeue_idx = add_one_with_wrap_around(priv->cmd_dequeue_idx, CMD_Q_SIZE); - priv->free_cmd_queue++; - priv->cmd_running = true; - - switch (priv->command) { - case WLAN_CMD_INIT_MAC80211: - priv->command_state = WLAN_CMD_INIT_MAC80211_START; - break; - - case WLAN_CMD_TBTT_WAKEUP: - priv->command_state = WLAN_CMD_TBTT_WAKEUP_START; - break; - - case WLAN_CMD_BECON_SEND: - priv->command_state = WLAN_CMD_BECON_SEND_START; - break; - - case WLAN_CMD_SETPOWER: - priv->command_state = WLAN_CMD_SETPOWER_START; - break; - - case WLAN_CMD_CHANGE_ANTENNA: - priv->command_state = WLAN_CMD_CHANGE_ANTENNA_START; - break; - - default: - break; - } - - vnt_cmd_timer_wait(priv, 0); - - return true; -} - -void vnt_run_command(struct work_struct *work) -{ - struct vnt_private *priv = - container_of(work, struct vnt_private, run_command_work.work); - - if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) - return; - - if (!priv->cmd_running) - return; - - switch (priv->command_state) { - case WLAN_CMD_INIT_MAC80211_START: - if (priv->mac_hw) - break; - - dev_info(&priv->usb->dev, "Starting mac80211\n"); - - if (vnt_init(priv)) { - /* If fail all ends TODO retry */ - dev_err(&priv->usb->dev, "failed to start\n"); - usb_set_intfdata(priv->intf, NULL); - ieee80211_free_hw(priv->hw); - return; - } - - break; - - case WLAN_CMD_TBTT_WAKEUP_START: - vnt_next_tbtt_wakeup(priv); - break; - - case WLAN_CMD_BECON_SEND_START: - if (!priv->vif) - break; - - vnt_beacon_make(priv, priv->vif); - - vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX); - - break; - - case WLAN_CMD_SETPOWER_START: - - vnt_rf_setpower(priv, priv->hw->conf.chandef.chan); - - break; - - case WLAN_CMD_CHANGE_ANTENNA_START: - dev_dbg(&priv->usb->dev, "Change from Antenna%d to", - priv->rx_antenna_sel); - - if (priv->rx_antenna_sel == 0) { - priv->rx_antenna_sel = 1; - if (priv->tx_rx_ant_inv) - vnt_set_antenna_mode(priv, ANT_RXA); - else - vnt_set_antenna_mode(priv, ANT_RXB); - } else { - priv->rx_antenna_sel = 0; - if (priv->tx_rx_ant_inv) - vnt_set_antenna_mode(priv, ANT_RXB); - else - vnt_set_antenna_mode(priv, ANT_RXA); - } - break; - - default: - break; - } - - vnt_cmd_complete(priv); -} - -int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command) -{ - if (priv->free_cmd_queue == 0) - return false; - - priv->cmd_queue[priv->cmd_enqueue_idx] = command; - - priv->cmd_enqueue_idx = add_one_with_wrap_around(priv->cmd_enqueue_idx, CMD_Q_SIZE); - priv->free_cmd_queue--; - - if (!priv->cmd_running) - vnt_cmd_complete(priv); - - return true; -} - -void vnt_reset_command_timer(struct vnt_private *priv) -{ - priv->free_cmd_queue = CMD_Q_SIZE; - priv->cmd_dequeue_idx = 0; - priv->cmd_enqueue_idx = 0; - priv->command_state = WLAN_CMD_IDLE; - priv->cmd_running = false; -} diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h deleted file mode 100644 index a62924671b17e6a483696873f5cb21a954bac01c..0000000000000000000000000000000000000000 --- a/drivers/staging/vt6656/wcmd.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. - * All rights reserved. - * - * Purpose: Handles the management command interface functions - * - * Author: Lyndon Chen - * - * Date: May 8, 2002 - * - */ - -#ifndef __WCMD_H__ -#define __WCMD_H__ - -#include "device.h" - -/* Command code */ -enum vnt_cmd { - WLAN_CMD_INIT_MAC80211, - WLAN_CMD_SETPOWER, - WLAN_CMD_TBTT_WAKEUP, - WLAN_CMD_BECON_SEND, - WLAN_CMD_CHANGE_ANTENNA -}; - -#define CMD_Q_SIZE 32 - -/* Command state */ -enum vnt_cmd_state { - WLAN_CMD_INIT_MAC80211_START, - WLAN_CMD_SETPOWER_START, - WLAN_CMD_TBTT_WAKEUP_START, - WLAN_CMD_BECON_SEND_START, - WLAN_CMD_CHANGE_ANTENNA_START, - WLAN_CMD_IDLE -}; - -struct vnt_private; - -void vnt_reset_command_timer(struct vnt_private *priv); - -int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd); - -void vnt_run_command(struct work_struct *work); - -#endif /* __WCMD_H__ */