aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/admin-guide/devices.txt12
-rw-r--r--Documentation/devicetree/bindings/serial/8250.yaml30
-rw-r--r--Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml95
-rw-r--r--Documentation/devicetree/bindings/serial/mtk-uart.txt1
-rw-r--r--Documentation/devicetree/bindings/serial/samsung_uart.yaml18
-rw-r--r--Documentation/devicetree/bindings/serial/serial.yaml10
-rw-r--r--Documentation/devicetree/bindings/serial/st,stm32-uart.yaml59
-rw-r--r--Documentation/driver-api/serial/cyclades_z.rst11
-rw-r--r--Documentation/driver-api/serial/index.rst1
-rw-r--r--Documentation/driver-api/serial/rocket.rst185
-rw-r--r--Documentation/process/magic-number.rst4
-rw-r--r--Documentation/translations/it_IT/process/magic-number.rst4
-rw-r--r--Documentation/translations/zh_CN/process/magic-number.rst4
-rw-r--r--Documentation/userspace-api/ioctl/ioctl-number.rst1
-rw-r--r--MAINTAINERS30
-rw-r--r--arch/arm/boot/dts/stm32mp151.dtsi24
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig1
-rw-r--r--arch/xtensa/platforms/iss/console.c45
-rw-r--r--drivers/accessibility/speakup/spk_ttyio.c1
-rw-r--r--drivers/bluetooth/hci_ldisc.c1
-rw-r--r--drivers/char/pcmcia/synclink_cs.c2
-rw-r--r--drivers/char/ttyprintk.c11
-rw-r--r--drivers/misc/ti-st/st_core.c1
-rw-r--r--drivers/net/caif/caif_serial.c18
-rw-r--r--drivers/net/can/slcan.c1
-rw-r--r--drivers/net/hamradio/6pack.c1
-rw-r--r--drivers/net/hamradio/mkiss.c1
-rw-r--r--drivers/net/ppp/ppp_async.c1
-rw-r--r--drivers/net/ppp/ppp_synctty.c1
-rw-r--r--drivers/net/slip/slip.c1
-rw-r--r--drivers/pps/clients/pps-ldisc.c3
-rw-r--r--drivers/s390/char/con3215.c56
-rw-r--r--drivers/staging/fwserial/fwserial.c19
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c2
-rw-r--r--drivers/staging/greybus/uart.c16
-rw-r--r--drivers/tty/Kconfig86
-rw-r--r--drivers/tty/Makefile3
-rw-r--r--drivers/tty/amiserial.c33
-rw-r--r--drivers/tty/cyclades.c4119
-rw-r--r--drivers/tty/hvc/hvc_udbg.c2
-rw-r--r--drivers/tty/hvc/hvcs.c24
-rw-r--r--drivers/tty/ipwireless/tty.c11
-rw-r--r--drivers/tty/isicom.c1699
-rw-r--r--drivers/tty/moxa.c25
-rw-r--r--drivers/tty/mxser.c38
-rw-r--r--drivers/tty/n_gsm.c37
-rw-r--r--drivers/tty/n_hdlc.c2
-rw-r--r--drivers/tty/n_null.c1
-rw-r--r--drivers/tty/n_r3964.c1
-rw-r--r--drivers/tty/n_tty.c3
-rw-r--r--drivers/tty/nozomi.c26
-rw-r--r--drivers/tty/pty.c5
-rw-r--r--drivers/tty/rocket.c3127
-rw-r--r--drivers/tty/rocket.h111
-rw-r--r--drivers/tty/rocket_int.h1214
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c107
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c1202
-rw-r--r--drivers/tty/serial/8250/8250_exar.c17
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c16
-rw-r--r--drivers/tty/serial/8250/8250_of.c1
-rw-r--r--drivers/tty/serial/8250/8250_omap.c6
-rw-r--r--drivers/tty/serial/8250/8250_port.c30
-rw-r--r--drivers/tty/serial/8250/Kconfig21
-rw-r--r--drivers/tty/serial/8250/Makefile1
-rw-r--r--drivers/tty/serial/8250/serial_cs.c12
-rw-r--r--drivers/tty/serial/Kconfig21
-rw-r--r--drivers/tty/serial/altera_jtaguart.c2
-rw-r--r--drivers/tty/serial/altera_uart.c2
-rw-r--r--drivers/tty/serial/amba-pl010.c2
-rw-r--r--drivers/tty/serial/amba-pl011.c2
-rw-r--r--drivers/tty/serial/apbuart.c2
-rw-r--r--drivers/tty/serial/ar933x_uart.c2
-rw-r--r--drivers/tty/serial/arc_uart.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c18
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c2
-rw-r--r--drivers/tty/serial/icom.c2
-rw-r--r--drivers/tty/serial/imx.c16
-rw-r--r--drivers/tty/serial/jsm/jsm_tty.c24
-rw-r--r--drivers/tty/serial/kgdb_nmi.c4
-rw-r--r--drivers/tty/serial/liteuart.c4
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c2
-rw-r--r--drivers/tty/serial/max310x.c2
-rw-r--r--drivers/tty/serial/mcf.c2
-rw-r--r--drivers/tty/serial/meson_uart.c2
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c2
-rw-r--r--drivers/tty/serial/msm_serial.c4
-rw-r--r--drivers/tty/serial/omap-serial.c51
-rw-r--r--drivers/tty/serial/owl-uart.c2
-rw-r--r--drivers/tty/serial/pch_uart.c22
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c6
-rw-r--r--drivers/tty/serial/rda-uart.c2
-rw-r--r--drivers/tty/serial/rp2.c2
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung_tty.c507
-rw-r--r--drivers/tty/serial/sc16is7xx.c2
-rw-r--r--drivers/tty/serial/serial_core.c8
-rw-r--r--drivers/tty/serial/serial_txx9.c4
-rw-r--r--drivers/tty/serial/sh-sci.c15
-rw-r--r--drivers/tty/serial/sifive.c2
-rw-r--r--drivers/tty/serial/stm32-usart.c310
-rw-r--r--drivers/tty/serial/stm32-usart.h17
-rw-r--r--drivers/tty/serial/sunsu.c4
-rw-r--r--drivers/tty/serial/tegra-tcu.c1
-rw-r--r--drivers/tty/serial/timbuart.c2
-rw-r--r--drivers/tty/serial/vt8500_serial.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c3
-rw-r--r--drivers/tty/synclink_gt.c66
-rw-r--r--drivers/tty/sysrq.c35
-rw-r--r--drivers/tty/tty.h114
-rw-r--r--drivers/tty/tty_audit.c1
-rw-r--r--drivers/tty/tty_baudrate.c1
-rw-r--r--drivers/tty/tty_buffer.c2
-rw-r--r--drivers/tty/tty_io.c69
-rw-r--r--drivers/tty/tty_ioctl.c8
-rw-r--r--drivers/tty/tty_jobctrl.c30
-rw-r--r--drivers/tty/tty_ldisc.c42
-rw-r--r--drivers/tty/tty_mutex.c1
-rw-r--r--drivers/tty/tty_port.c1
-rw-r--r--drivers/tty/vcc.c72
-rw-r--r--drivers/tty/vt/keyboard.c2
-rw-r--r--drivers/tty/vt/vt.c3
-rw-r--r--drivers/usb/serial/mos7720.c2
-rw-r--r--drivers/video/console/vgacon.c5
-rw-r--r--include/linux/cyclades.h364
-rw-r--r--include/linux/isicom.h85
-rw-r--r--include/linux/pci_ids.h31
-rw-r--r--include/linux/serial_core.h10
-rw-r--r--include/linux/serial_s3c.h16
-rw-r--r--include/linux/tty.h103
-rw-r--r--include/linux/tty_driver.h2
-rw-r--r--include/linux/tty_ldisc.h3
-rw-r--r--include/net/nfc/nci_core.h2
-rw-r--r--include/uapi/linux/cyclades.h494
-rw-r--r--include/uapi/linux/major.h2
-rw-r--r--include/uapi/linux/serial.h4
-rw-r--r--include/uapi/linux/tty_flags.h8
-rw-r--r--net/nfc/nci/uart.c148
-rw-r--r--sound/soc/codecs/cx20442.c1
-rw-r--r--sound/soc/ti/ams-delta.c1
139 files changed, 2730 insertions, 12732 deletions
diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt
index 63fd4e6a014b..ef41f77cb979 100644
--- a/Documentation/admin-guide/devices.txt
+++ b/Documentation/admin-guide/devices.txt
@@ -289,7 +289,7 @@
152 = /dev/kpoll Kernel Poll Driver
153 = /dev/mergemem Memory merge device
154 = /dev/pmu Macintosh PowerBook power manager
- 155 = /dev/isictl MultiTech ISICom serial control
+ 155 =
156 = /dev/lcd Front panel LCD display
157 = /dev/ac Applicom Intl Profibus card
158 = /dev/nwbutton Netwinder external button
@@ -477,11 +477,6 @@
18 block Sanyo CD-ROM
0 = /dev/sjcd Sanyo CD-ROM
- 19 char Cyclades serial card
- 0 = /dev/ttyC0 First Cyclades port
- ...
- 31 = /dev/ttyC31 32nd Cyclades port
-
19 block "Double" compressed disk
0 = /dev/double0 First compressed disk
...
@@ -493,11 +488,6 @@
See the Double documentation for the meaning of the
mirror devices.
- 20 char Cyclades serial card - alternate devices
- 0 = /dev/cub0 Callout device for ttyC0
- ...
- 31 = /dev/cub31 Callout device for ttyC31
-
20 block Hitachi CD-ROM (under development)
0 = /dev/hitcd Hitachi CD-ROM
diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
index f54cae9ff7b2..f0506a917793 100644
--- a/Documentation/devicetree/bindings/serial/8250.yaml
+++ b/Documentation/devicetree/bindings/serial/8250.yaml
@@ -12,8 +12,13 @@ maintainers:
allOf:
- $ref: /schemas/serial.yaml#
- if:
- required:
- - aspeed,sirq-polarity-sense
+ anyOf:
+ - required:
+ - aspeed,lpc-io-reg
+ - required:
+ - aspeed,lpc-interrupts
+ - required:
+ - aspeed,sirq-polarity-sense
then:
properties:
compatible:
@@ -55,6 +60,7 @@ properties:
- const: aspeed,ast2500-vuart
- const: intel,xscale-uart
- const: mrvl,pxa-uart
+ - const: nuvoton,wpcm450-uart
- const: nuvoton,npcm750-uart
- const: nvidia,tegra20-uart
- const: nxp,lpc3220-uart
@@ -165,7 +171,6 @@ properties:
property.
tx-threshold:
- $ref: /schemas/types.yaml#/definitions/uint32
description: |
Specify the TX FIFO low water indication for parts with programmable
TX FIFO thresholds.
@@ -188,6 +193,21 @@ properties:
offset and bit number to identify how the SIRQ polarity should be
configured. One possible data source is the LPC/eSPI mode bit. Only
applicable to aspeed,ast2500-vuart.
+ deprecated: true
+
+ aspeed,lpc-io-reg:
+ $ref: '/schemas/types.yaml#/definitions/uint32'
+ description: |
+ The VUART LPC address. Only applicable to aspeed,ast2500-vuart.
+
+ aspeed,lpc-interrupts:
+ $ref: "/schemas/types.yaml#/definitions/uint32-array"
+ minItems: 2
+ maxItems: 2
+ description: |
+ A 2-cell property describing the VUART SIRQ number and SIRQ
+ polarity (IRQ_TYPE_LEVEL_LOW or IRQ_TYPE_LEVEL_HIGH). Only
+ applicable to aspeed,ast2500-vuart.
required:
- reg
@@ -220,6 +240,7 @@ examples:
};
- |
#include <dt-bindings/clock/aspeed-clock.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
serial@1e787000 {
compatible = "aspeed,ast2500-vuart";
reg = <0x1e787000 0x40>;
@@ -227,7 +248,8 @@ examples:
interrupts = <8>;
clocks = <&syscon ASPEED_CLK_APB>;
no-loopback-test;
- aspeed,sirq-polarity-sense = <&syscon 0x70 25>;
+ aspeed,lpc-io-reg = <0x3f8>;
+ aspeed,lpc-interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
};
...
diff --git a/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml b/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml
new file mode 100644
index 000000000000..46c62745f901
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/brcm,bcm7271-uart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom 8250 based serial port devicetree bindings
+
+maintainers:
+ - Al Cooper <alcooperx@gmail.com>
+
+allOf:
+ - $ref: /schemas/serial.yaml#
+
+description: |+
+ The Broadcom UART is based on the basic 8250 UART but with
+ enhancements for more accurate high speed baud rates and support
+ for DMA.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - brcm,bcm7271-uart
+ - brcm,bcm7278-uart
+
+ reg:
+ minItems: 1
+ maxItems: 5
+
+ reg-names:
+ description: The UART register block and optionally the DMA register blocks.
+ oneOf:
+ - items:
+ - const: uart
+ - items:
+ - const: uart
+ - const: dma_arb
+ - const: dma_rx
+ - const: dma_tx
+ - const: dma_intr2
+
+ clocks:
+ minItems: 1
+
+ clock-names:
+ const: sw_baud
+
+ interrupts:
+ minItems: 1
+ maxItems: 2
+
+ interrupt-names:
+ description: The UART interrupt and optionally the DMA interrupt.
+ minItems: 1
+ items:
+ - const: uart
+ - const: dma
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - interrupts
+ - interrupt-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ serial@840d000 {
+ compatible = "brcm,bcm7271-uart";
+ reg = <0x840d000 0x20>;
+ reg-names = "uart";
+ interrupts = <0x0 0x62 0x4>;
+ interrupt-names = "uart";
+ clocks = <&scmi_clk 190>;
+ clock-names = "sw_baud";
+ };
+
+ serial@840e000 {
+ compatible = "brcm,bcm7271-uart";
+ reg = <0x840e000 0x20>,
+ <0x840e080 0x8>,
+ <0x840e100 0xa8>,
+ <0x840e200 0x4c>,
+ <0x840e300 0x30>;
+ reg-names = "uart", "dma_arb", "dma_rx", "dma_tx", "dma_intr2";
+ interrupts = <0x0 0x62 0x4>, <0x0 0x75 0x4>;
+ interrupt-names = "uart", "dma";
+ clocks = <&scmi_clk 190>;
+ clock-names = "sw_baud";
+ };
diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt
index 647b5aee86f3..64c4fb59acd1 100644
--- a/Documentation/devicetree/bindings/serial/mtk-uart.txt
+++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt
@@ -20,6 +20,7 @@ Required properties:
* "mediatek,mt8173-uart" for MT8173 compatible UARTS
* "mediatek,mt8183-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt8192-uart", "mediatek,mt6577-uart" for MT8192 compatible UARTS
+ * "mediatek,mt8195-uart", "mediatek,mt6577-uart" for MT8195 compatible UARTS
* "mediatek,mt8516-uart" for MT8516 compatible UARTS
* "mediatek,mt6577-uart" for MT6577 and all of the above
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.yaml b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
index 21ee627b2ced..97ec8a093bf3 100644
--- a/Documentation/devicetree/bindings/serial/samsung_uart.yaml
+++ b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/serial/samsung_uart.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Samsung S3C, S5P and Exynos SoC UART Controller
+title: Samsung S3C, S5P, Exynos, and S5L (Apple SoC) SoC UART Controller
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
@@ -19,6 +19,7 @@ properties:
compatible:
items:
- enum:
+ - apple,s5l-uart
- samsung,s3c2410-uart
- samsung,s3c2412-uart
- samsung,s3c2440-uart
@@ -51,6 +52,16 @@ properties:
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
+ dmas:
+ items:
+ - description: DMA controller phandle and request line for RX
+ - description: DMA controller phandle and request line for TX
+
+ dma-names:
+ items:
+ - const: rx
+ - const: tx
+
interrupts:
description: RX interrupt and optionally TX interrupt.
minItems: 1
@@ -68,9 +79,11 @@ required:
- interrupts
- reg
-additionalProperties: false
+unevaluatedProperties: false
allOf:
+ - $ref: /schemas/serial.yaml#
+
- if:
properties:
compatible:
@@ -96,6 +109,7 @@ allOf:
compatible:
contains:
enum:
+ - apple,s5l-uart
- samsung,exynos4210-uart
then:
properties:
diff --git a/Documentation/devicetree/bindings/serial/serial.yaml b/Documentation/devicetree/bindings/serial/serial.yaml
index 65e75d040521..f368d58e8086 100644
--- a/Documentation/devicetree/bindings/serial/serial.yaml
+++ b/Documentation/devicetree/bindings/serial/serial.yaml
@@ -75,6 +75,16 @@ properties:
type: boolean
description: CTS and RTS pins are swapped.
+ rx-threshold:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ RX FIFO threshold configuration (in bytes).
+
+ tx-threshold:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ TX FIFO threshold configuration (in bytes).
+
if:
required:
- uart-has-rtscts
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
index 8631678283f9..71a6426bc558 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
@@ -9,9 +9,6 @@ maintainers:
title: STMicroelectronics STM32 USART bindings
-allOf:
- - $ref: rs485.yaml
-
properties:
compatible:
enum:
@@ -40,6 +37,8 @@ properties:
uart-has-rtscts: true
+ rx-tx-swap: true
+
dmas:
minItems: 1
maxItems: 2
@@ -66,13 +65,46 @@ properties:
linux,rs485-enabled-at-boot-time: true
rs485-rx-during-tx: true
-if:
- required:
- - st,hw-flow-ctrl
-then:
- properties:
- cts-gpios: false
- rts-gpios: false
+ rx-threshold:
+ description:
+ If value is set to 1, RX FIFO threshold is disabled.
+ enum: [1, 2, 4, 8, 12, 14, 16]
+ default: 8
+
+ tx-threshold:
+ description:
+ If value is set to 1, TX FIFO threshold is disabled.
+ enum: [1, 2, 4, 8, 12, 14, 16]
+ default: 8
+
+allOf:
+ - $ref: rs485.yaml#
+ - $ref: serial.yaml#
+ - if:
+ required:
+ - st,hw-flow-ctrl
+ then:
+ properties:
+ cts-gpios: false
+ rts-gpios: false
+ - if:
+ properties:
+ compatible:
+ const: st,stm32-uart
+ then:
+ properties:
+ rx-tx-swap: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - st,stm32-uart
+ - st,stm32f7-uart
+ then:
+ properties:
+ rx-threshold: false
+ tx-threshold: false
required:
- compatible
@@ -80,19 +112,22 @@ required:
- interrupts
- clocks
-additionalProperties: false
+additionalProperties:
+ type: object
examples:
- |
#include <dt-bindings/clock/stm32mp1-clks.h>
usart1: serial@40011000 {
- compatible = "st,stm32-uart";
+ compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
interrupts = <37>;
clocks = <&rcc 0 164>;
dmas = <&dma2 2 4 0x414 0x0>,
<&dma2 7 4 0x414 0x0>;
dma-names = "rx", "tx";
+ rx-threshold = <4>;
+ tx-threshold = <4>;
rs485-rts-active-low;
};
diff --git a/Documentation/driver-api/serial/cyclades_z.rst b/Documentation/driver-api/serial/cyclades_z.rst
deleted file mode 100644
index 532ff67e2f1c..000000000000
--- a/Documentation/driver-api/serial/cyclades_z.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-================
-Cyclades-Z notes
-================
-
-The Cyclades-Z must have firmware loaded onto the card before it will
-operate. This operation should be performed during system startup,
-
-The firmware, loader program and the latest device driver code are
-available from Cyclades at
-
- ftp://ftp.cyclades.com/pub/cyclades/cyclades-z/linux/
diff --git a/Documentation/driver-api/serial/index.rst b/Documentation/driver-api/serial/index.rst
index 33ad10d05b26..21351b8c95a4 100644
--- a/Documentation/driver-api/serial/index.rst
+++ b/Documentation/driver-api/serial/index.rst
@@ -17,7 +17,6 @@ Serial drivers
.. toctree::
:maxdepth: 1
- cyclades_z
moxa-smartio
n_gsm
rocket
diff --git a/Documentation/driver-api/serial/rocket.rst b/Documentation/driver-api/serial/rocket.rst
deleted file mode 100644
index 23761eae4282..000000000000
--- a/Documentation/driver-api/serial/rocket.rst
+++ /dev/null
@@ -1,185 +0,0 @@
-================================================
-Comtrol(tm) RocketPort(R)/RocketModem(TM) Series
-================================================
-
-Device Driver for the Linux Operating System
-============================================
-
-Product overview
-----------------
-
-This driver provides a loadable kernel driver for the Comtrol RocketPort
-and RocketModem PCI boards. These boards provide, 2, 4, 8, 16, or 32
-high-speed serial ports or modems. This driver supports up to a combination
-of four RocketPort or RocketModems boards in one machine simultaneously.
-This file assumes that you are using the RocketPort driver which is
-integrated into the kernel sources.
-
-The driver can also be installed as an external module using the usual
-"make;make install" routine. This external module driver, obtainable
-from the Comtrol website listed below, is useful for updating the driver
-or installing it into kernels which do not have the driver configured
-into them. Installations instructions for the external module
-are in the included README and HW_INSTALL files.
-
-RocketPort ISA and RocketModem II PCI boards currently are only supported by
-this driver in module form.
-
-The RocketPort ISA board requires I/O ports to be configured by the DIP
-switches on the board. See the section "ISA Rocketport Boards" below for
-information on how to set the DIP switches.
-
-You pass the I/O port to the driver using the following module parameters:
-
-board1:
- I/O port for the first ISA board
-board2:
- I/O port for the second ISA board
-board3:
- I/O port for the third ISA board
-board4:
- I/O port for the fourth ISA board
-
-There is a set of utilities and scripts provided with the external driver
-(downloadable from http://www.comtrol.com) that ease the configuration and
-setup of the ISA cards.
-
-The RocketModem II PCI boards require firmware to be loaded into the card
-before it will function. The driver has only been tested as a module for this
-board.
-
-Installation Procedures
------------------------
-
-RocketPort/RocketModem PCI cards require no driver configuration, they are
-automatically detected and configured.
-
-The RocketPort driver can be installed as a module (recommended) or built
-into the kernel. This is selected, as for other drivers, through the `make config`
-command from the root of the Linux source tree during the kernel build process.
-
-The RocketPort/RocketModem serial ports installed by this driver are assigned
-device major number 46, and will be named /dev/ttyRx, where x is the port number
-starting at zero (ex. /dev/ttyR0, /devttyR1, ...). If you have multiple cards
-installed in the system, the mapping of port names to serial ports is displayed
-in the system log at /var/log/messages.
-
-If installed as a module, the module must be loaded. This can be done
-manually by entering "modprobe rocket". To have the module loaded automatically
-upon system boot, edit a `/etc/modprobe.d/*.conf` file and add the line
-"alias char-major-46 rocket".
-
-In order to use the ports, their device names (nodes) must be created with mknod.
-This is only required once, the system will retain the names once created. To
-create the RocketPort/RocketModem device names, use the command
-"mknod /dev/ttyRx c 46 x" where x is the port number starting at zero.
-
-For example::
-
- > mknod /dev/ttyR0 c 46 0
- > mknod /dev/ttyR1 c 46 1
- > mknod /dev/ttyR2 c 46 2
-
-The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes)
-for you::
-
- >/dev/MAKEDEV ttyR
-
-ISA Rocketport Boards
----------------------
-
-You must assign and configure the I/O addresses used by the ISA Rocketport
-card before installing and using it. This is done by setting a set of DIP
-switches on the Rocketport board.
-
-
-Setting the I/O address
------------------------
-
-Before installing RocketPort(R) or RocketPort RA boards, you must find
-a range of I/O addresses for it to use. The first RocketPort card
-requires a 68-byte contiguous block of I/O addresses, starting at one
-of the following: 0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h,
-0x300h, 0x340h, 0x380h. This I/O address must be reflected in the DIP
-switches of *all* of the Rocketport cards.
-
-The second, third, and fourth RocketPort cards require a 64-byte
-contiguous block of I/O addresses, starting at one of the following
-I/O addresses: 0x100h, 0x140h, 0x180h, 0x1C0h, 0x200h, 0x240h, 0x280h,
-0x2C0h, 0x300h, 0x340h, 0x380h, 0x3C0h. The I/O address used by the
-second, third, and fourth Rocketport cards (if present) are set via
-software control. The DIP switch settings for the I/O address must be
-set to the value of the first Rocketport cards.
-
-In order to distinguish each of the card from the others, each card
-must have a unique board ID set on the dip switches. The first
-Rocketport board must be set with the DIP switches corresponding to
-the first board, the second board must be set with the DIP switches
-corresponding to the second board, etc. IMPORTANT: The board ID is
-the only place where the DIP switch settings should differ between the
-various Rocketport boards in a system.
-
-The I/O address range used by any of the RocketPort cards must not
-conflict with any other cards in the system, including other
-RocketPort cards. Below, you will find a list of commonly used I/O
-address ranges which may be in use by other devices in your system.
-On a Linux system, "cat /proc/ioports" will also be helpful in
-identifying what I/O addresses are being used by devices on your
-system.
-
-Remember, the FIRST RocketPort uses 68 I/O addresses. So, if you set it
-for 0x100, it will occupy 0x100 to 0x143. This would mean that you
-CAN NOT set the second, third or fourth board for address 0x140 since
-the first 4 bytes of that range are used by the first board. You would
-need to set the second, third, or fourth board to one of the next available
-blocks such as 0x180.
-
-RocketPort and RocketPort RA SW1 Settings::
-
- +-------------------------------+
- | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
- +-------+-------+---------------+
- | Unused| Card | I/O Port Block|
- +-------------------------------+
-
- DIP Switches DIP Switches
- 7 8 6 5
- =================== ===================
- On On UNUSED, MUST BE ON. On On First Card <==== Default
- On Off Second Card
- Off On Third Card
- Off Off Fourth Card
-
- DIP Switches I/O Address Range
- 4 3 2 1 Used by the First Card
- =====================================
- On Off On Off 100-143
- On Off Off On 140-183
- On Off Off Off 180-1C3 <==== Default
- Off On On Off 200-243
- Off On Off On 240-283
- Off On Off Off 280-2C3
- Off Off On Off 300-343
- Off Off Off On 340-383
- Off Off Off Off 380-3C3
-
-Reporting Bugs
---------------
-
-For technical support, please provide the following
-information: Driver version, kernel release, distribution of
-kernel, and type of board you are using. Error messages and log
-printouts port configuration details are especially helpful.
-
-USA:
- :Phone: (612) 494-4100
- :FAX: (612) 494-4199
- :email: support@comtrol.com
-
-Comtrol Europe:
- :Phone: +44 (0) 1 869 323-220
- :FAX: +44 (0) 1 869 323-211
- :email: support@comtrol.co.uk
-
-Web: http://www.comtrol.com
-FTP: ftp.comtrol.com
diff --git a/Documentation/process/magic-number.rst b/Documentation/process/magic-number.rst
index fa5a62f4150c..f5ba36e96461 100644
--- a/Documentation/process/magic-number.rst
+++ b/Documentation/process/magic-number.rst
@@ -73,12 +73,10 @@ CMAGIC 0x0111 user ``include/linux/
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
-CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
-ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
@@ -90,14 +88,12 @@ TTY_MAGIC 0x5401 tty_struct ``include/linux/
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
-TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
-RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
NBD_REQUEST_MAGIC 0x12560953 nbd_request ``include/linux/nbd.h``
diff --git a/Documentation/translations/it_IT/process/magic-number.rst b/Documentation/translations/it_IT/process/magic-number.rst
index 1af30f4228f2..e8c782d155a3 100644
--- a/Documentation/translations/it_IT/process/magic-number.rst
+++ b/Documentation/translations/it_IT/process/magic-number.rst
@@ -79,12 +79,10 @@ CMAGIC 0x0111 user ``include/linux/
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
-CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
-ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
@@ -96,14 +94,12 @@ TTY_MAGIC 0x5401 tty_struct ``include/linux/
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
-TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
-RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
diff --git a/Documentation/translations/zh_CN/process/magic-number.rst b/Documentation/translations/zh_CN/process/magic-number.rst
index 7bb9d4165ed3..42f0635ca70a 100644
--- a/Documentation/translations/zh_CN/process/magic-number.rst
+++ b/Documentation/translations/zh_CN/process/magic-number.rst
@@ -62,12 +62,10 @@ CMAGIC 0x0111 user ``include/linux/
MKISS_DRIVER_MAGIC 0x04bf mkiss_channel ``drivers/net/mkiss.h``
HDLC_MAGIC 0x239e n_hdlc ``drivers/char/n_hdlc.c``
APM_BIOS_MAGIC 0x4101 apm_user ``arch/x86/kernel/apm_32.c``
-CYCLADES_MAGIC 0x4359 cyclades_port ``include/linux/cyclades.h``
DB_MAGIC 0x4442 fc_info ``drivers/net/iph5526_novram.c``
DL_MAGIC 0x444d fc_info ``drivers/net/iph5526_novram.c``
FASYNC_MAGIC 0x4601 fasync_struct ``include/linux/fs.h``
FF_MAGIC 0x4646 fc_info ``drivers/net/iph5526_novram.c``
-ISICOM_MAGIC 0x4d54 isi_port ``include/linux/isicom.h``
PTY_MAGIC 0x5001 ``drivers/char/pty.c``
PPP_MAGIC 0x5002 ppp ``include/linux/if_pppvar.h``
SSTATE_MAGIC 0x5302 serial_state ``include/linux/serial.h``
@@ -79,14 +77,12 @@ TTY_MAGIC 0x5401 tty_struct ``include/linux/
MGSL_MAGIC 0x5401 mgsl_info ``drivers/char/synclink.c``
TTY_DRIVER_MAGIC 0x5402 tty_driver ``include/linux/tty_driver.h``
MGSLPC_MAGIC 0x5402 mgslpc_info ``drivers/char/pcmcia/synclink_cs.c``
-TTY_LDISC_MAGIC 0x5403 tty_ldisc ``include/linux/tty_ldisc.h``
USB_SERIAL_MAGIC 0x6702 usb_serial ``drivers/usb/serial/usb-serial.h``
FULL_DUPLEX_MAGIC 0x6969 ``drivers/net/ethernet/dec/tulip/de2104x.c``
USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth ``drivers/usb/class/bluetty.c``
RFCOMM_TTY_MAGIC 0x6d02 ``net/bluetooth/rfcomm/tty.c``
USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port ``drivers/usb/serial/usb-serial.h``
CG_MAGIC 0x00090255 ufs_cylinder_group ``include/linux/ufs_fs.h``
-RPORT_MAGIC 0x00525001 r_port ``drivers/char/rocket_int.h``
LSEMAGIC 0x05091998 lse ``drivers/fc4/fc.c``
GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str ``drivers/scsi/gdth_ioctl.h``
RIEBL_MAGIC 0x09051990 ``drivers/net/atarilance.c``
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index 5618a39456df..181211beb01d 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -209,7 +209,6 @@ Code Seq# Include File Comments
linux/fs.h,
'X' all fs/ocfs2/ocfs_fs.h conflict!
'X' 01 linux/pktcdvd.h conflict!
-'Y' all linux/cyclades.h
'Z' 14-15 drivers/message/fusion/mptctl.h
'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices
<mailto:gregkh@linuxfoundation.org>
diff --git a/MAINTAINERS b/MAINTAINERS
index 1d08d7a76470..0504a13a8087 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3578,6 +3578,14 @@ S: Supported
F: Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml
F: drivers/i2c/busses/i2c-brcmstb.c
+BROADCOM BRCMSTB UART DRIVER
+M: Al Cooper <alcooperx@gmail.com>
+L: linux-serial@vger.kernel.org
+L: bcm-kernel-feedback-list@broadcom.com
+S: Maintained
+F: Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml
+F: drivers/tty/serial/8250/8250_bcm7271.c
+
BROADCOM BRCMSTB USB EHCI DRIVER
M: Al Cooper <alcooperx@gmail.com>
L: linux-usb@vger.kernel.org
@@ -4902,16 +4910,8 @@ S: Maintained
W: http://www.armlinux.org.uk/
F: drivers/video/fbdev/cyber2000fb.*
-CYCLADES ASYNC MUX DRIVER
-S: Orphan
-W: http://www.cyclades.com/
-F: drivers/tty/cyclades.c
-F: include/linux/cyclades.h
-F: include/uapi/linux/cyclades.h
-
CYCLADES PC300 DRIVER
S: Orphan
-W: http://www.cyclades.com/
F: drivers/net/wan/pc300*
CYPRESS_FIRMWARE MEDIA DRIVER
@@ -12167,8 +12167,7 @@ F: drivers/media/pci/meye/
F: include/uapi/linux/meye.h
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
-M: Jiri Slaby <jirislaby@kernel.org>
-S: Maintained
+S: Orphan
F: Documentation/driver-api/serial/moxa-smartio.rst
F: drivers/tty/mxser.*
@@ -12312,11 +12311,6 @@ F: drivers/mux/
F: include/dt-bindings/mux/
F: include/linux/mux/
-MULTITECH MULTIPORT CARD (ISICOM)
-S: Orphan
-F: drivers/tty/isicom.c
-F: include/linux/isicom.h
-
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Bin Liu <b-liu@ti.com>
L: linux-usb@vger.kernel.org
@@ -15493,12 +15487,6 @@ L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/rocker/
-ROCKETPORT DRIVER
-S: Maintained
-W: http://www.comtrol.com
-F: Documentation/driver-api/serial/rocket.rst
-F: drivers/tty/rocket*
-
ROCKETPORT EXPRESS/INFINITY DRIVER
M: Kevin Cernekee <cernekee@gmail.com>
L: linux-serial@vger.kernel.org
diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi
index 4b8031782555..e242d7211059 100644
--- a/arch/arm/boot/dts/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/stm32mp151.dtsi
@@ -452,32 +452,36 @@
usart2: serial@4000e000 {
compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
- interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART2_K>;
+ wakeup-source;
status = "disabled";
};
usart3: serial@4000f000 {
compatible = "st,stm32h7-uart";
reg = <0x4000f000 0x400>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART3_K>;
+ wakeup-source;
status = "disabled";
};
uart4: serial@40010000 {
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
- interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART4_K>;
+ wakeup-source;
status = "disabled";
};
uart5: serial@40011000 {
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
- interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART5_K>;
+ wakeup-source;
status = "disabled";
};
@@ -577,16 +581,18 @@
uart7: serial@40018000 {
compatible = "st,stm32h7-uart";
reg = <0x40018000 0x400>;
- interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART7_K>;
+ wakeup-source;
status = "disabled";
};
uart8: serial@40019000 {
compatible = "st,stm32h7-uart";
reg = <0x40019000 0x400>;
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc UART8_K>;
+ wakeup-source;
status = "disabled";
};
@@ -665,8 +671,9 @@
usart6: serial@44003000 {
compatible = "st,stm32h7-uart";
reg = <0x44003000 0x400>;
- interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART6_K>;
+ wakeup-source;
status = "disabled";
};
@@ -1505,8 +1512,9 @@
usart1: serial@5c000000 {
compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc USART1_K>;
+ wakeup-source;
status = "disabled";
};
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 6677ac0da45a..1fd9d1260f9e 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -595,7 +595,6 @@ CONFIG_GAMEPORT_FM801=m
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_NONSTANDARD=y
CONFIG_ROCKETPORT=m
-CONFIG_CYCLADES=m
CONFIG_SYNCLINK_GT=m
CONFIG_NOZOMI=m
CONFIG_N_HDLC=m
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index af81a62faba6..a3dda25a4e45 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -31,48 +31,23 @@
#define SERIAL_MAX_NUM_LINES 1
#define SERIAL_TIMER_VALUE (HZ / 10)
+static void rs_poll(struct timer_list *);
+
static struct tty_driver *serial_driver;
static struct tty_port serial_port;
-static struct timer_list serial_timer;
-
+static DEFINE_TIMER(serial_timer, rs_poll);
static DEFINE_SPINLOCK(timer_lock);
-static char *serial_version = "0.1";
-static char *serial_name = "ISS serial driver";
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-
-static void rs_poll(struct timer_list *);
-
static int rs_open(struct tty_struct *tty, struct file * filp)
{
- tty->port = &serial_port;
spin_lock_bh(&timer_lock);
- if (tty->count == 1) {
- timer_setup(&serial_timer, rs_poll, 0);
+ if (tty->count == 1)
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
- }
spin_unlock_bh(&timer_lock);
return 0;
}
-
-/*
- * ------------------------------------------------------------
- * iss_serial_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
static void rs_close(struct tty_struct *tty, struct file * filp)
{
spin_lock_bh(&timer_lock);
@@ -149,7 +124,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
static int rs_proc_show(struct seq_file *m, void *v)
{
- seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
+ seq_printf(m, "serinfo:1.0 driver:0.1\n");
return 0;
}
@@ -166,14 +141,12 @@ static const struct tty_operations serial_ops = {
.proc_show = rs_proc_show,
};
-int __init rs_init(void)
+static int __init rs_init(void)
{
tty_port_init(&serial_port);
serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
- pr_info("%s %s\n", serial_name, serial_version);
-
/* Initialize the tty_driver structure */
serial_driver->driver_name = "iss_serial";
@@ -198,11 +171,7 @@ int __init rs_init(void)
static __exit void rs_exit(void)
{
- int error;
-
- if ((error = tty_unregister_driver(serial_driver)))
- pr_err("ISS_SERIAL: failed to unregister serial driver (%d)\n",
- error);
+ tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_port_destroy(&serial_port);
}
diff --git a/drivers/accessibility/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c
index 9af1d4c124d3..2e39fcf492d8 100644
--- a/drivers/accessibility/speakup/spk_ttyio.c
+++ b/drivers/accessibility/speakup/spk_ttyio.c
@@ -104,7 +104,6 @@ static int spk_ttyio_receive_buf2(struct tty_struct *tty,
static struct tty_ldisc_ops spk_ttyio_ldisc_ops = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "speakup_ldisc",
.open = spk_ttyio_ldisc_open,
.close = spk_ttyio_ldisc_close,
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 637c5b8c2aa1..71a4ca505e09 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -821,7 +821,6 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty,
static struct tty_ldisc_ops hci_uart_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "n_hci",
.open = hci_uart_tty_open,
.close = hci_uart_tty_close,
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 2be8d9a8eec5..3287a7627ed0 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -530,8 +530,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
info->port.ops = &mgslpc_port_ops;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
- info->port.close_delay = 5*HZ/10;
- info->port.closing_wait = 30*HZ;
init_waitqueue_head(&info->status_event_wait_q);
init_waitqueue_head(&info->event_wait_q);
spin_lock_init(&info->lock);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index 6a0059e508e3..93f5d11c830b 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -158,12 +158,23 @@ static int tpk_ioctl(struct tty_struct *tty,
return 0;
}
+/*
+ * TTY operations hangup function.
+ */
+static void tpk_hangup(struct tty_struct *tty)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+
+ tty_port_hangup(&tpkp->port);
+}
+
static const struct tty_operations ttyprintk_ops = {
.open = tpk_open,
.close = tpk_close,
.write = tpk_write,
.write_room = tpk_write_room,
.ioctl = tpk_ioctl,
+ .hangup = tpk_hangup,
};
static const struct tty_port_operations null_ops = { };
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 5a0a5fc3d3ab..071844b58073 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -845,7 +845,6 @@ static void st_tty_flush_buffer(struct tty_struct *tty)
}
static struct tty_ldisc_ops st_ldisc_ops = {
- .magic = TTY_LDISC_MAGIC,
.name = "n_st",
.open = st_tty_open,
.close = st_tty_close,
diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c
index 8215cd77301f..da6fffb4d5a8 100644
--- a/drivers/net/caif/caif_serial.c
+++ b/drivers/net/caif/caif_serial.c
@@ -382,7 +382,6 @@ static void ldisc_close(struct tty_struct *tty)
/* The line discipline structure. */
static struct tty_ldisc_ops caif_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "n_caif",
.open = ldisc_open,
.close = ldisc_close,
@@ -390,18 +389,6 @@ static struct tty_ldisc_ops caif_ldisc = {
.write_wakeup = ldisc_tx_wakeup
};
-static int register_ldisc(void)
-{
- int result;
-
- result = tty_register_ldisc(N_CAIF, &caif_ldisc);
- if (result < 0) {
- pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF,
- result);
- return result;
- }
- return result;
-}
static const struct net_device_ops netdev_ops = {
.ndo_open = caif_net_open,
.ndo_stop = caif_net_close,
@@ -444,7 +431,10 @@ static int __init caif_ser_init(void)
{
int ret;
- ret = register_ldisc();
+ ret = tty_register_ldisc(N_CAIF, &caif_ldisc);
+ if (ret < 0)
+ pr_err("cannot register CAIF ldisc=%d err=%d\n", N_CAIF, ret);
+
debugfsdir = debugfs_create_dir("caif_serial", NULL);
return ret;
}
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 30c8d53c9745..31ba6664503d 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -697,7 +697,6 @@ static int slcan_ioctl(struct tty_struct *tty, struct file *file,
static struct tty_ldisc_ops slc_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "slcan",
.open = slcan_open,
.close = slcan_close,
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 9f5b5614a150..80f41945709f 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -744,7 +744,6 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
static struct tty_ldisc_ops sp_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "6pack",
.open = sixpack_open,
.close = sixpack_close,
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 17be2bb2985c..65154224d5b8 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -933,7 +933,6 @@ out:
static struct tty_ldisc_ops ax_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "mkiss",
.open = mkiss_open,
.close = mkiss_close,
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index 2a91caa4f37b..8b41aa3fb64e 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -372,7 +372,6 @@ ppp_asynctty_wakeup(struct tty_struct *tty)
static struct tty_ldisc_ops ppp_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "ppp",
.open = ppp_asynctty_open,
.close = ppp_asynctty_close,
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index d8890923a9e3..576b6a93bf23 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -365,7 +365,6 @@ ppp_sync_wakeup(struct tty_struct *tty)
static struct tty_ldisc_ops ppp_sync_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "pppsync",
.open = ppp_sync_open,
.close = ppp_sync_close,
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index f81fb0b13a94..1ab124eba8eb 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -1263,7 +1263,6 @@ static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static struct tty_ldisc_ops sl_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "slip",
.open = slip_open,
.close = slip_close,
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c
index 4fd0cbf7f931..bf26cc56b863 100644
--- a/drivers/pps/clients/pps-ldisc.c
+++ b/drivers/pps/clients/pps-ldisc.c
@@ -13,8 +13,6 @@
#include <linux/pps_kernel.h>
#include <linux/bug.h>
-#define PPS_TTY_MAGIC 0x0001
-
static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status)
{
struct pps_device *pps;
@@ -114,7 +112,6 @@ static int __init pps_tty_init(void)
/* Init PPS_TTY data */
pps_ldisc_ops.owner = THIS_MODULE;
- pps_ldisc_ops.magic = PPS_TTY_MAGIC;
pps_ldisc_ops.name = "pps_tty";
pps_ldisc_ops.dcd_change = pps_tty_dcd_change;
pps_ldisc_ops.open = pps_tty_open;
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 671efee612af..d26947d743bc 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -85,7 +85,6 @@ struct raw3215_info {
int written; /* number of bytes in write requests */
struct raw3215_req *queued_read; /* pointer to queued read requests */
struct raw3215_req *queued_write;/* pointer to queued write requests */
- struct tasklet_struct tlet; /* tasklet to invoke tty_wakeup */
wait_queue_head_t empty_wait; /* wait queue for flushing */
struct timer_list timer; /* timer for delayed output */
int line_pos; /* position on the line (for tabs) */
@@ -330,21 +329,6 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
}
/*
- * Call tty_wakeup from tasklet context
- */
-static void raw3215_wakeup(unsigned long data)
-{
- struct raw3215_info *raw = (struct raw3215_info *) data;
- struct tty_struct *tty;
-
- tty = tty_port_tty_get(&raw->port);
- if (tty) {
- tty_wakeup(tty);
- tty_kref_put(tty);
- }
-}
-
-/*
* Try to start the next IO and wake up processes waiting on the tty.
*/
static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
@@ -352,7 +336,7 @@ static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty)
raw3215_mk_write_req(raw);
raw3215_try_io(raw);
if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE)
- tasklet_schedule(&raw->tlet);
+ tty_wakeup(tty);
}
/*
@@ -644,7 +628,6 @@ static struct raw3215_info *raw3215_alloc_info(void)
timer_setup(&info->timer, raw3215_timeout, 0);
init_waitqueue_head(&info->empty_wait);
- tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info);
tty_port_init(&info->port);
return info;
@@ -928,15 +911,13 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp)
*/
static void tty3215_close(struct tty_struct *tty, struct file * filp)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
- raw = (struct raw3215_info *) tty->driver_data;
if (raw == NULL || tty->count > 1)
return;
tty->closing = 1;
/* Shutdown the terminal */
raw3215_shutdown(raw);
- tasklet_kill(&raw->tlet);
tty->closing = 0;
tty_port_tty_set(&raw->port, NULL);
}
@@ -946,9 +927,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp)
*/
static int tty3215_write_room(struct tty_struct *tty)
{
- struct raw3215_info *raw;
-
- raw = (struct raw3215_info *) tty->driver_data;
+ struct raw3215_info *raw = tty->driver_data;
/* Subtract TAB_STOP_SIZE to allow for a tab, 8 <<< 64K */
if ((RAW3215_BUFFER_SIZE - raw->count - TAB_STOP_SIZE) >= 0)
@@ -963,12 +942,9 @@ static int tty3215_write_room(struct tty_struct *tty)
static int tty3215_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
int i, written;
- if (!tty)
- return 0;
- raw = (struct raw3215_info *) tty->driver_data;
written = count;
while (count > 0) {
for (i = 0; i < count; i++)
@@ -991,12 +967,10 @@ static int tty3215_write(struct tty_struct * tty,
*/
static int tty3215_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
- if (!tty)
- return 0;
- raw = (struct raw3215_info *) tty->driver_data;
raw3215_putchar(raw, ch);
+
return 1;
}
@@ -1009,17 +983,15 @@ static void tty3215_flush_chars(struct tty_struct *tty)
*/
static int tty3215_chars_in_buffer(struct tty_struct *tty)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
- raw = (struct raw3215_info *) tty->driver_data;
return raw->count;
}
static void tty3215_flush_buffer(struct tty_struct *tty)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
- raw = (struct raw3215_info *) tty->driver_data;
raw3215_flush_buffer(raw);
tty_wakeup(tty);
}
@@ -1029,9 +1001,8 @@ static void tty3215_flush_buffer(struct tty_struct *tty)
*/
static void tty3215_throttle(struct tty_struct * tty)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
- raw = (struct raw3215_info *) tty->driver_data;
raw->flags |= RAW3215_THROTTLED;
}
@@ -1040,10 +1011,9 @@ static void tty3215_throttle(struct tty_struct * tty)
*/
static void tty3215_unthrottle(struct tty_struct * tty)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
unsigned long flags;
- raw = (struct raw3215_info *) tty->driver_data;
if (raw->flags & RAW3215_THROTTLED) {
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw->flags &= ~RAW3215_THROTTLED;
@@ -1057,9 +1027,8 @@ static void tty3215_unthrottle(struct tty_struct * tty)
*/
static void tty3215_stop(struct tty_struct *tty)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
- raw = (struct raw3215_info *) tty->driver_data;
raw->flags |= RAW3215_STOPPED;
}
@@ -1068,10 +1037,9 @@ static void tty3215_stop(struct tty_struct *tty)
*/
static void tty3215_start(struct tty_struct *tty)
{
- struct raw3215_info *raw;
+ struct raw3215_info *raw = tty->driver_data;
unsigned long flags;
- raw = (struct raw3215_info *) tty->driver_data;
if (raw->flags & RAW3215_STOPPED) {
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
raw->flags &= ~RAW3215_STOPPED;
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index 2cc461b26897..1ee6382cafc4 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -1218,13 +1218,12 @@ static int get_serial_info(struct tty_struct *tty,
struct fwtty_port *port = tty->driver_data;
mutex_lock(&port->port.mutex);
- ss->type = PORT_UNKNOWN;
- ss->line = port->port.tty->index;
- ss->flags = port->port.flags;
- ss->xmit_fifo_size = FWTTY_PORT_TXFIFO_LEN;
+ ss->line = port->index;
ss->baud_base = 400000000;
- ss->close_delay = port->port.close_delay;
+ ss->close_delay = jiffies_to_msecs(port->port.close_delay) / 10;
+ ss->closing_wait = 3000;
mutex_unlock(&port->port.mutex);
+
return 0;
}
@@ -1232,20 +1231,20 @@ static int set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct fwtty_port *port = tty->driver_data;
+ unsigned int cdelay;
- if (ss->irq != 0 || ss->port != 0 || ss->custom_divisor != 0 ||
- ss->baud_base != 400000000)
- return -EPERM;
+ cdelay = msecs_to_jiffies(ss->close_delay * 10);
mutex_lock(&port->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
- if (((ss->flags & ~ASYNC_USR_MASK) !=
+ if (cdelay != port->port.close_delay ||
+ ((ss->flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->port.mutex);
return -EPERM;
}
}
- port->port.close_delay = ss->close_delay * HZ / 100;
+ port->port.close_delay = cdelay;
mutex_unlock(&port->port.mutex);
return 0;
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
index 6e813693a766..0ccc8c24e754 100644
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -188,7 +188,7 @@ static int gdm_tty_write_room(struct tty_struct *tty)
struct gdm *gdm = tty->driver_data;
if (!GDM_TTY_READY(gdm))
- return -ENODEV;
+ return 0;
return WRITE_SIZE;
}
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c
index 607378bfebb7..b1e63f7798b0 100644
--- a/drivers/staging/greybus/uart.c
+++ b/drivers/staging/greybus/uart.c
@@ -610,14 +610,13 @@ static int get_serial_info(struct tty_struct *tty,
{
struct gb_tty *gb_tty = tty->driver_data;
- ss->type = PORT_16550A;
ss->line = gb_tty->minor;
- ss->xmit_fifo_size = 16;
- ss->baud_base = 9600;
- ss->close_delay = gb_tty->port.close_delay / 10;
+ 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 : gb_tty->port.closing_wait / 10;
+ ASYNC_CLOSING_WAIT_NONE :
+ jiffies_to_msecs(gb_tty->port.closing_wait) / 10;
+
return 0;
}
@@ -629,17 +628,16 @@ static int set_serial_info(struct tty_struct *tty,
unsigned int close_delay;
int retval = 0;
- close_delay = ss->close_delay * 10;
+ close_delay = msecs_to_jiffies(ss->close_delay * 10);
closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ?
- ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10;
+ ASYNC_CLOSING_WAIT_NONE :
+ msecs_to_jiffies(ss->closing_wait * 10);
mutex_lock(&gb_tty->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if ((close_delay != gb_tty->port.close_delay) ||
(closing_wait != gb_tty->port.closing_wait))
retval = -EPERM;
- else
- retval = -EOPNOTSUPP;
} else {
gb_tty->port.close_delay = close_delay;
gb_tty->port.closing_wait = closing_wait;
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index e15cd6b5bb99..f6a7fd6d3bb6 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -181,7 +181,7 @@ config SERIAL_NONSTANDARD
help
Say Y here if you have any non-standard serial boards -- boards
which aren't supported using the standard "dumb" serial driver.
- This includes intelligent serial boards such as Cyclades,
+ This includes intelligent serial boards such as
Digiboards, etc. These are usually used for systems that need many
serial ports because they serve many terminals or dial-in
connections.
@@ -192,50 +192,6 @@ config SERIAL_NONSTANDARD
Most people can say N here.
-config ROCKETPORT
- tristate "Comtrol RocketPort support"
- depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
- help
- This driver supports Comtrol RocketPort and RocketModem PCI boards.
- These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
- modems. For information about the RocketPort/RocketModem boards
- and this driver read <file:Documentation/driver-api/serial/rocket.rst>.
-
- To compile this driver as a module, choose M here: the
- module will be called rocket.
-
- If you want to compile this driver into the kernel, say Y here. If
- you don't have a Comtrol RocketPort/RocketModem card installed, say N.
-
-config CYCLADES
- tristate "Cyclades async mux support"
- depends on SERIAL_NONSTANDARD && (PCI || ISA)
- select FW_LOADER
- help
- This driver supports Cyclades Z and Y multiserial boards.
- You would need something like this to connect more than two modems to
- your Linux box, for instance in order to become a dial-in server.
-
- For information about the Cyclades-Z card, read
- <file:Documentation/driver-api/serial/cyclades_z.rst>.
-
- To compile this driver as a module, choose M here: the
- module will be called cyclades.
-
- If you haven't heard about it, it's safe to say N.
-
-config CYZ_INTR
- bool "Cyclades-Z interrupt mode operation"
- depends on CYCLADES && PCI
- help
- The Cyclades-Z family of multiport cards allows 2 (two) driver op
- modes: polling and interrupt. In polling mode, the driver will check
- the status of the Cyclades-Z ports every certain amount of time
- (which is called polling cycle and is configurable). In interrupt
- mode, it will use an interrupt line (IRQ) in order to check the
- status of the Cyclades-Z ports. The default op mode is polling. If
- unsure, say N.
-
config MOXA_INTELLIO
tristate "Moxa Intellio support"
depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
@@ -267,16 +223,6 @@ config SYNCLINK_GT
synchronous and asynchronous serial adapters
manufactured by Microgate Systems, Ltd. (www.microgate.com)
-config ISI
- tristate "Multi-Tech multiport card support"
- depends on SERIAL_NONSTANDARD && PCI
- select FW_LOADER
- help
- This is a driver for the Multi-Tech cards which provide several
- serial ports. The driver is experimental and can currently only be
- built as a module. The module will be called isicom.
- If you want to do that, choose M here.
-
config N_HDLC
tristate "HDLC line discipline support"
depends on SERIAL_NONSTANDARD
@@ -415,36 +361,6 @@ config NULL_TTY
If unsure, say N.
-config TRACE_ROUTER
- tristate "Trace data router for MIPI P1149.7 cJTAG standard"
- depends on TRACE_SINK
- help
- The trace router uses the Linux tty line discipline framework to
- route trace data coming from a tty port (say UART for example) to
- the trace sink line discipline driver and to another tty port (say
- USB). This is part of a solution for the MIPI P1149.7, compact JTAG,
- standard, which is for debugging mobile devices. The PTI driver in
- drivers/misc/pti.c defines the majority of this MIPI solution.
-
- You should select this driver if the target kernel is meant for
- a mobile device containing a modem. Then you will need to select
- "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline
- driver.
-
-config TRACE_SINK
- tristate "Trace data sink for MIPI P1149.7 cJTAG standard"
- help
- The trace sink uses the Linux line discipline framework to receive
- trace data coming from the trace router line discipline driver
- to a user-defined tty port target, like USB.
- This is to provide a way to extract modem trace data on
- devices that do not have a PTI HW module, or just need modem
- trace data to come out of a different HW output port.
- This is part of a solution for the P1149.7, compact JTAG, standard.
-
- If you select this option, you need to select
- "Trace data router for MIPI P1149.7 cJTAG standard".
-
config VCC
tristate "Sun Virtual Console Concentrator"
depends on SUN_LDOMS
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 730de6bf048b..c7054f5117c3 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -18,13 +18,10 @@ obj-$(CONFIG_SERIAL_DEV_BUS) += serdev/
# tty drivers
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
-obj-$(CONFIG_CYCLADES) += cyclades.o
-obj-$(CONFIG_ISI) += isicom.o
obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
obj-$(CONFIG_NOZOMI) += nozomi.o
obj-$(CONFIG_NULL_TTY) += ttynull.o
-obj-$(CONFIG_ROCKETPORT) += rocket.o
obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o
obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 18b78ea110ef..ca48ce5a0862 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -937,15 +937,21 @@ static void rs_unthrottle(struct tty_struct * tty)
static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct serial_state *state = tty->driver_data;
+ unsigned int close_delay, closing_wait;
tty_lock(tty);
+ close_delay = jiffies_to_msecs(state->tport.close_delay) / 10;
+ closing_wait = state->tport.closing_wait;
+ if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ closing_wait = jiffies_to_msecs(closing_wait) / 10;
+
ss->line = tty->index;
ss->port = state->port;
ss->flags = state->tport.flags;
ss->xmit_fifo_size = state->xmit_fifo_size;
ss->baud_base = state->baud_base;
- ss->close_delay = state->tport.close_delay;
- ss->closing_wait = state->tport.closing_wait;
+ ss->close_delay = close_delay;
+ ss->closing_wait = closing_wait;
ss->custom_divisor = state->custom_divisor;
tty_unlock(tty);
return 0;
@@ -957,6 +963,7 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
struct tty_port *port = &state->tport;
bool change_spd;
int retval = 0;
+ unsigned int close_delay, closing_wait;
tty_lock(tty);
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
@@ -966,10 +973,16 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
tty_unlock(tty);
return -EINVAL;
}
-
+
+ close_delay = msecs_to_jiffies(ss->close_delay * 10);
+ closing_wait = ss->closing_wait;
+ if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ closing_wait = msecs_to_jiffies(closing_wait * 10);
+
if (!serial_isroot()) {
if ((ss->baud_base != state->baud_base) ||
- (ss->close_delay != port->close_delay) ||
+ (close_delay != port->close_delay) ||
+ (closing_wait != port->closing_wait) ||
(ss->xmit_fifo_size != state->xmit_fifo_size) ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
@@ -996,8 +1009,8 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
port->flags = ((port->flags & ~ASYNC_FLAGS) |
(ss->flags & ASYNC_FLAGS));
state->custom_divisor = ss->custom_divisor;
- port->close_delay = ss->close_delay * HZ/100;
- port->closing_wait = ss->closing_wait * HZ/100;
+ port->close_delay = close_delay;
+ port->closing_wait = closing_wait;
check_and_exit:
if (tty_port_initialized(port)) {
@@ -1622,21 +1635,17 @@ fail_put_tty_driver:
static int __exit amiga_serial_remove(struct platform_device *pdev)
{
- int error;
struct serial_state *state = platform_get_drvdata(pdev);
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
- error = tty_unregister_driver(serial_driver);
- if (error)
- printk("SERIAL: failed to unregister serial driver (%d)\n",
- error);
+ tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
tty_port_destroy(&state->tport);
free_irq(IRQ_AMIGA_TBE, state);
free_irq(IRQ_AMIGA_RBF, state);
- return error;
+ return 0;
}
static struct platform_driver amiga_serial_driver = {
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
deleted file mode 100644
index 097266342e5e..000000000000
--- a/drivers/tty/cyclades.c
+++ /dev/null
@@ -1,4119 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#undef BLOCKMOVE
-#define Z_WAKE
-#undef Z_EXT_CHARS_IN_BUFFER
-
-/*
- * This file contains the driver for the Cyclades async multiport
- * serial boards.
- *
- * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
- * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
- *
- * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com>
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992 Linus Torvalds. It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- * Converted to pci probing and cleaned up by Jiri Slaby.
- *
- */
-
-#define CY_VERSION "2.6"
-
-/* If you need to install more boards than NR_CARDS, change the constant
- in the definition below. No other change is necessary to support up to
- eight boards. Beyond that you'll have to extend cy_isa_addresses. */
-
-#define NR_CARDS 4
-
-/*
- If the total number of ports is larger than NR_PORTS, change this
- constant in the definition below. No other change is necessary to
- support more boards/ports. */
-
-#define NR_PORTS 256
-
-#define ZO_V1 0
-#define ZO_V2 1
-#define ZE_V1 2
-
-#define SERIAL_PARANOIA_CHECK
-#undef CY_DEBUG_OPEN
-#undef CY_DEBUG_THROTTLE
-#undef CY_DEBUG_OTHER
-#undef CY_DEBUG_IO
-#undef CY_DEBUG_COUNT
-#undef CY_DEBUG_DTR
-#undef CY_DEBUG_INTERRUPTS
-#undef CY_16Y_HACK
-#undef CY_ENABLE_MONITORING
-#undef CY_PCI_DEBUG
-
-/*
- * Include section
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/cyclades.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/bitops.h>
-#include <linux/firmware.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static void cy_send_xchar(struct tty_struct *tty, char ch);
-
-#ifndef SERIAL_XMIT_SIZE
-#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
-#endif
-
-/* firmware stuff */
-#define ZL_MAX_BLOCKS 16
-#define DRIVER_VERSION 0x02010203
-#define RAM_SIZE 0x80000
-
-enum zblock_type {
- ZBLOCK_PRG = 0,
- ZBLOCK_FPGA = 1
-};
-
-struct zfile_header {
- char name[64];
- char date[32];
- char aux[32];
- u32 n_config;
- u32 config_offset;
- u32 n_blocks;
- u32 block_offset;
- u32 reserved[9];
-} __attribute__ ((packed));
-
-struct zfile_config {
- char name[64];
- u32 mailbox;
- u32 function;
- u32 n_blocks;
- u32 block_list[ZL_MAX_BLOCKS];
-} __attribute__ ((packed));
-
-struct zfile_block {
- u32 type;
- u32 file_offset;
- u32 ram_offset;
- u32 size;
-} __attribute__ ((packed));
-
-static struct tty_driver *cy_serial_driver;
-
-#ifdef CONFIG_ISA
-/* This is the address lookup table. The driver will probe for
- Cyclom-Y/ISA boards at all addresses in here. If you want the
- driver to probe addresses at a different address, add it to
- this table. If the driver is probing some other board and
- causing problems, remove the offending address from this table.
-*/
-
-static unsigned int cy_isa_addresses[] = {
- 0xD0000,
- 0xD2000,
- 0xD4000,
- 0xD6000,
- 0xD8000,
- 0xDA000,
- 0xDC000,
- 0xDE000,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
-
-static long maddr[NR_CARDS];
-static int irq[NR_CARDS];
-
-module_param_hw_array(maddr, long, iomem, NULL, 0);
-module_param_hw_array(irq, int, irq, NULL, 0);
-
-#endif /* CONFIG_ISA */
-
-/* This is the per-card data structure containing address, irq, number of
- channels, etc. This driver supports a maximum of NR_CARDS cards.
-*/
-static struct cyclades_card cy_card[NR_CARDS];
-
-static int cy_next_channel; /* next minor available */
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates. The extra
- * are accessed via settings in info->port.flags.
- * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
- * 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- * HI VHI
- * 20
- */
-static const int baud_table[] = {
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
- 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
- 230400, 0
-};
-
-static const char baud_co_25[] = { /* 25 MHz clock option table */
- /* value => 00 01 02 03 04 */
- /* divide by 8 32 128 512 2048 */
- 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
- 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const char baud_bpr_25[] = { /* 25 MHz baud rate period table */
- 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
- 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-
-static const char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */
- /* value => 00 01 02 03 04 */
- /* divide by 8 32 128 512 2048 */
- 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
- 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00
-};
-
-static const char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */
- 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
- 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
- 0x21
-};
-
-static const char baud_cor3[] = { /* receive threshold */
- 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
- 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
- 0x07
-};
-
-/*
- * The Cyclades driver implements HW flow control as any serial driver.
- * The cyclades_port structure member rflow and the vector rflow_thr
- * allows us to take advantage of a special feature in the CD1400 to avoid
- * data loss even when the system interrupt latency is too high. These flags
- * are to be used only with very special applications. Setting these flags
- * requires the use of a special cable (DTR and RTS reversed). In the new
- * CD1400-based boards (rev. 6.00 or later), there is no need for special
- * cables.
- */
-
-static const char rflow_thr[] = { /* rflow threshold */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
- 0x0a
-};
-
-/* The Cyclom-Ye has placed the sequential chips in non-sequential
- * address order. This look-up table overcomes that problem.
- */
-static const unsigned int cy_chip_offset[] = { 0x0000,
- 0x0400,
- 0x0800,
- 0x0C00,
- 0x0200,
- 0x0600,
- 0x0A00,
- 0x0E00
-};
-
-/* PCI related definitions */
-
-#ifdef CONFIG_PCI
-static const struct pci_device_id cy_pci_dev_id[] = {
- /* PCI < 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
- /* PCI > 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
- /* 4Y PCI < 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
- /* 4Y PCI > 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
- /* 8Y PCI < 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
- /* 8Y PCI > 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
- /* Z PCI < 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
- /* Z PCI > 1Mb */
- { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
- { } /* end of table */
-};
-MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
-#endif
-
-static void cy_start(struct tty_struct *);
-static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
-static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
-#ifdef CONFIG_ISA
-static unsigned detect_isa_irq(void __iomem *);
-#endif /* CONFIG_ISA */
-
-#ifndef CONFIG_CYZ_INTR
-static void cyz_poll(struct timer_list *);
-
-/* The Cyclades-Z polling cycle is defined by this variable */
-static long cyz_polling_cycle = CZ_DEF_POLL;
-
-static DEFINE_TIMER(cyz_timerlist, cyz_poll);
-
-#else /* CONFIG_CYZ_INTR */
-static void cyz_rx_restart(struct timer_list *);
-#endif /* CONFIG_CYZ_INTR */
-
-static void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
-{
- struct cyclades_card *card = port->card;
-
- cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
-}
-
-static u8 cyy_readb(struct cyclades_port *port, u32 reg)
-{
- struct cyclades_card *card = port->card;
-
- return readb(port->u.cyy.base_addr + (reg << card->bus_index));
-}
-
-static inline bool cy_is_Z(struct cyclades_card *card)
-{
- return card->num_chips == (unsigned int)-1;
-}
-
-static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
-{
- return readl(&ctl_addr->init_ctrl) & (1 << 17);
-}
-
-static inline bool cyz_fpga_loaded(struct cyclades_card *card)
-{
- return __cyz_fpga_loaded(card->ctl_addr.p9060);
-}
-
-static bool cyz_is_loaded(struct cyclades_card *card)
-{
- struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
-
- return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
- readl(&fw_id->signature) == ZFIRM_ID;
-}
-
-static int serial_paranoia_check(struct cyclades_port *info,
- const char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- if (!info) {
- printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
- "in %s\n", name, routine);
- return 1;
- }
-
- if (info->magic != CYCLADES_MAGIC) {
- printk(KERN_WARNING "cyc Warning: bad magic number for serial "
- "struct (%s) in %s\n", name, routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-/***********************************************************/
-/********* Start of block of Cyclom-Y specific code ********/
-
-/* This routine waits up to 1000 micro-seconds for the previous
- command to the Cirrus chip to complete and then issues the
- new command. An error is returned if the previous command
- didn't finish within the time limit.
-
- This function is only called from inside spinlock-protected code.
- */
-static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index)
-{
- void __iomem *ccr = base_addr + (CyCCR << index);
- unsigned int i;
-
- /* Check to see that the previous command has completed */
- for (i = 0; i < 100; i++) {
- if (readb(ccr) == 0)
- break;
- udelay(10L);
- }
- /* if the CCR never cleared, the previous command
- didn't finish within the "reasonable time" */
- if (i == 100)
- return -1;
-
- /* Issue the new command */
- cy_writeb(ccr, cmd);
-
- return 0;
-}
-
-static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd)
-{
- return __cyy_issue_cmd(port->u.cyy.base_addr, cmd,
- port->card->bus_index);
-}
-
-#ifdef CONFIG_ISA
-/* ISA interrupt detection code */
-static unsigned detect_isa_irq(void __iomem *address)
-{
- int irq;
- unsigned long irqs, flags;
- int save_xir, save_car;
- int index = 0; /* IRQ probing is only for ISA */
-
- /* forget possible initially masked and pending IRQ */
- irq = probe_irq_off(probe_irq_on());
-
- /* Clear interrupts on the board first */
- cy_writeb(address + (Cy_ClrIntr << index), 0);
- /* Cy_ClrIntr is 0x1800 */
-
- irqs = probe_irq_on();
- /* Wait ... */
- msleep(5);
-
- /* Enable the Tx interrupts on the CD1400 */
- local_irq_save(flags);
- cy_writeb(address + (CyCAR << index), 0);
- __cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
-
- cy_writeb(address + (CyCAR << index), 0);
- cy_writeb(address + (CySRER << index),
- readb(address + (CySRER << index)) | CyTxRdy);
- local_irq_restore(flags);
-
- /* Wait ... */
- msleep(5);
-
- /* Check which interrupt is in use */
- irq = probe_irq_off(irqs);
-
- /* Clean up */
- save_xir = (u_char) readb(address + (CyTIR << index));
- save_car = readb(address + (CyCAR << index));
- cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
- cy_writeb(address + (CySRER << index),
- readb(address + (CySRER << index)) & ~CyTxRdy);
- cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
- cy_writeb(address + (CyCAR << index), (save_car));
- cy_writeb(address + (Cy_ClrIntr << index), 0);
- /* Cy_ClrIntr is 0x1800 */
-
- return (irq > 0) ? irq : 0;
-}
-#endif /* CONFIG_ISA */
-
-static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
- void __iomem *base_addr)
-{
- struct cyclades_port *info;
- struct tty_port *port;
- int len, index = cinfo->bus_index;
- u8 ivr, save_xir, channel, save_car, data, char_count;
-
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
-#endif
- /* determine the channel & change to that context */
- save_xir = readb(base_addr + (CyRIR << index));
- channel = save_xir & CyIRChannel;
- info = &cinfo->ports[channel + chip * 4];
- port = &info->port;
- save_car = cyy_readb(info, CyCAR);
- cyy_writeb(info, CyCAR, save_xir);
- ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
-
- /* there is an open port for this data */
- if (ivr == CyIVRRxEx) { /* exception */
- data = cyy_readb(info, CyRDSR);
-
- /* For statistics only */
- if (data & CyBREAK)
- info->icount.brk++;
- else if (data & CyFRAME)
- info->icount.frame++;
- else if (data & CyPARITY)
- info->icount.parity++;
- else if (data & CyOVERRUN)
- info->icount.overrun++;
-
- if (data & info->ignore_status_mask) {
- info->icount.rx++;
- return;
- }
- if (tty_buffer_request_room(port, 1)) {
- if (data & info->read_status_mask) {
- if (data & CyBREAK) {
- tty_insert_flip_char(port,
- cyy_readb(info, CyRDSR),
- TTY_BREAK);
- info->icount.rx++;
- if (port->flags & ASYNC_SAK) {
- struct tty_struct *tty =
- tty_port_tty_get(port);
- if (tty) {
- do_SAK(tty);
- tty_kref_put(tty);
- }
- }
- } else if (data & CyFRAME) {
- tty_insert_flip_char(port,
- cyy_readb(info, CyRDSR),
- TTY_FRAME);
- info->icount.rx++;
- info->idle_stats.frame_errs++;
- } else if (data & CyPARITY) {
- /* Pieces of seven... */
- tty_insert_flip_char(port,
- cyy_readb(info, CyRDSR),
- TTY_PARITY);
- info->icount.rx++;
- info->idle_stats.parity_errs++;
- } else if (data & CyOVERRUN) {
- tty_insert_flip_char(port, 0,
- TTY_OVERRUN);
- info->icount.rx++;
- /* If the flip buffer itself is
- overflowing, we still lose
- the next incoming character.
- */
- tty_insert_flip_char(port,
- cyy_readb(info, CyRDSR),
- TTY_FRAME);
- info->icount.rx++;
- info->idle_stats.overruns++;
- /* These two conditions may imply */
- /* a normal read should be done. */
- /* } else if(data & CyTIMEOUT) { */
- /* } else if(data & CySPECHAR) { */
- } else {
- tty_insert_flip_char(port, 0,
- TTY_NORMAL);
- info->icount.rx++;
- }
- } else {
- tty_insert_flip_char(port, 0, TTY_NORMAL);
- info->icount.rx++;
- }
- } else {
- /* there was a software buffer overrun and nothing
- * could be done about it!!! */
- info->icount.buf_overrun++;
- info->idle_stats.overruns++;
- }
- } else { /* normal character reception */
- /* load # chars available from the chip */
- char_count = cyy_readb(info, CyRDCR);
-
-#ifdef CY_ENABLE_MONITORING
- ++info->mon.int_count;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
-#endif
- len = tty_buffer_request_room(port, char_count);
- while (len--) {
- data = cyy_readb(info, CyRDSR);
- tty_insert_flip_char(port, data, TTY_NORMAL);
- info->idle_stats.recv_bytes++;
- info->icount.rx++;
-#ifdef CY_16Y_HACK
- udelay(10L);
-#endif
- }
- info->idle_stats.recv_idle = jiffies;
- }
- tty_schedule_flip(port);
-
- /* end of service */
- cyy_writeb(info, CyRIR, save_xir & 0x3f);
- cyy_writeb(info, CyCAR, save_car);
-}
-
-static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
- void __iomem *base_addr)
-{
- struct cyclades_port *info;
- struct tty_struct *tty;
- int char_count, index = cinfo->bus_index;
- u8 save_xir, channel, save_car, outch;
-
- /* Since we only get here when the transmit buffer
- is empty, we know we can always stuff a dozen
- characters. */
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
-#endif
-
- /* determine the channel & change to that context */
- save_xir = readb(base_addr + (CyTIR << index));
- channel = save_xir & CyIRChannel;
- save_car = readb(base_addr + (CyCAR << index));
- cy_writeb(base_addr + (CyCAR << index), save_xir);
-
- info = &cinfo->ports[channel + chip * 4];
- tty = tty_port_tty_get(&info->port);
- if (tty == NULL) {
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
- goto end;
- }
-
- /* load the on-chip space for outbound data */
- char_count = info->xmit_fifo_size;
-
- if (info->x_char) { /* send special char */
- outch = info->x_char;
- cyy_writeb(info, CyTDR, outch);
- char_count--;
- info->icount.tx++;
- info->x_char = 0;
- }
-
- if (info->breakon || info->breakoff) {
- if (info->breakon) {
- cyy_writeb(info, CyTDR, 0);
- cyy_writeb(info, CyTDR, 0x81);
- info->breakon = 0;
- char_count -= 2;
- }
- if (info->breakoff) {
- cyy_writeb(info, CyTDR, 0);
- cyy_writeb(info, CyTDR, 0x83);
- info->breakoff = 0;
- char_count -= 2;
- }
- }
-
- while (char_count-- > 0) {
- if (!info->xmit_cnt) {
- if (cyy_readb(info, CySRER) & CyTxMpty) {
- cyy_writeb(info, CySRER,
- cyy_readb(info, CySRER) & ~CyTxMpty);
- } else {
- cyy_writeb(info, CySRER, CyTxMpty |
- (cyy_readb(info, CySRER) & ~CyTxRdy));
- }
- goto done;
- }
- if (info->port.xmit_buf == NULL) {
- cyy_writeb(info, CySRER,
- cyy_readb(info, CySRER) & ~CyTxRdy);
- goto done;
- }
- if (tty->stopped || tty->hw_stopped) {
- cyy_writeb(info, CySRER,
- cyy_readb(info, CySRER) & ~CyTxRdy);
- goto done;
- }
- /* Because the Embedded Transmit Commands have been enabled,
- * we must check to see if the escape character, NULL, is being
- * sent. If it is, we must ensure that there is room for it to
- * be doubled in the output stream. Therefore we no longer
- * advance the pointer when the character is fetched, but
- * rather wait until after the check for a NULL output
- * character. This is necessary because there may not be room
- * for the two chars needed to send a NULL.)
- */
- outch = info->port.xmit_buf[info->xmit_tail];
- if (outch) {
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1) &
- (SERIAL_XMIT_SIZE - 1);
- cyy_writeb(info, CyTDR, outch);
- info->icount.tx++;
- } else {
- if (char_count > 1) {
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1) &
- (SERIAL_XMIT_SIZE - 1);
- cyy_writeb(info, CyTDR, outch);
- cyy_writeb(info, CyTDR, 0);
- info->icount.tx++;
- char_count--;
- }
- }
- }
-
-done:
- tty_wakeup(tty);
- tty_kref_put(tty);
-end:
- /* end of service */
- cyy_writeb(info, CyTIR, save_xir & 0x3f);
- cyy_writeb(info, CyCAR, save_car);
-}
-
-static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
- void __iomem *base_addr)
-{
- struct cyclades_port *info;
- struct tty_struct *tty;
- int index = cinfo->bus_index;
- u8 save_xir, channel, save_car, mdm_change, mdm_status;
-
- /* determine the channel & change to that context */
- save_xir = readb(base_addr + (CyMIR << index));
- channel = save_xir & CyIRChannel;
- info = &cinfo->ports[channel + chip * 4];
- save_car = cyy_readb(info, CyCAR);
- cyy_writeb(info, CyCAR, save_xir);
-
- mdm_change = cyy_readb(info, CyMISR);
- mdm_status = cyy_readb(info, CyMSVR1);
-
- tty = tty_port_tty_get(&info->port);
- if (!tty)
- goto end;
-
- if (mdm_change & CyANY_DELTA) {
- /* For statistics only */
- if (mdm_change & CyDCD)
- info->icount.dcd++;
- if (mdm_change & CyCTS)
- info->icount.cts++;
- if (mdm_change & CyDSR)
- info->icount.dsr++;
- if (mdm_change & CyRI)
- info->icount.rng++;
-
- wake_up_interruptible(&info->port.delta_msr_wait);
- }
-
- if ((mdm_change & CyDCD) && tty_port_check_carrier(&info->port)) {
- if (mdm_status & CyDCD)
- wake_up_interruptible(&info->port.open_wait);
- else
- tty_hangup(tty);
- }
- if ((mdm_change & CyCTS) && tty_port_cts_enabled(&info->port)) {
- if (tty->hw_stopped) {
- if (mdm_status & CyCTS) {
- /* cy_start isn't used
- because... !!! */
- tty->hw_stopped = 0;
- cyy_writeb(info, CySRER,
- cyy_readb(info, CySRER) | CyTxRdy);
- tty_wakeup(tty);
- }
- } else {
- if (!(mdm_status & CyCTS)) {
- /* cy_stop isn't used
- because ... !!! */
- tty->hw_stopped = 1;
- cyy_writeb(info, CySRER,
- cyy_readb(info, CySRER) & ~CyTxRdy);
- }
- }
- }
-/* if (mdm_change & CyDSR) {
- }
- if (mdm_change & CyRI) {
- }*/
- tty_kref_put(tty);
-end:
- /* end of service */
- cyy_writeb(info, CyMIR, save_xir & 0x3f);
- cyy_writeb(info, CyCAR, save_car);
-}
-
-/* The real interrupt service routine is called
- whenever the card wants its hand held--chars
- received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cyy_interrupt(int irq, void *dev_id)
-{
- int status;
- struct cyclades_card *cinfo = dev_id;
- void __iomem *base_addr, *card_base_addr;
- unsigned int chip, too_many, had_work;
- int index;
-
- if (unlikely(cinfo == NULL)) {
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
- irq);
-#endif
- return IRQ_NONE; /* spurious interrupt */
- }
-
- card_base_addr = cinfo->base_addr;
- index = cinfo->bus_index;
-
- /* card was not initialized yet (e.g. DEBUG_SHIRQ) */
- if (unlikely(card_base_addr == NULL))
- return IRQ_HANDLED;
-
- /* This loop checks all chips in the card. Make a note whenever
- _any_ chip had some work to do, as this is considered an
- indication that there will be more to do. Only when no chip
- has any work does this outermost loop exit.
- */
- do {
- had_work = 0;
- for (chip = 0; chip < cinfo->num_chips; chip++) {
- base_addr = cinfo->base_addr +
- (cy_chip_offset[chip] << index);
- too_many = 0;
- while ((status = readb(base_addr +
- (CySVRR << index))) != 0x00) {
- had_work++;
- /* The purpose of the following test is to ensure that
- no chip can monopolize the driver. This forces the
- chips to be checked in a round-robin fashion (after
- draining each of a bunch (1000) of characters).
- */
- if (1000 < too_many++)
- break;
- spin_lock(&cinfo->card_lock);
- if (status & CySRReceive) /* rx intr */
- cyy_chip_rx(cinfo, chip, base_addr);
- if (status & CySRTransmit) /* tx intr */
- cyy_chip_tx(cinfo, chip, base_addr);
- if (status & CySRModem) /* modem intr */
- cyy_chip_modem(cinfo, chip, base_addr);
- spin_unlock(&cinfo->card_lock);
- }
- }
- } while (had_work);
-
- /* clear interrupts */
- spin_lock(&cinfo->card_lock);
- cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
- /* Cy_ClrIntr is 0x1800 */
- spin_unlock(&cinfo->card_lock);
- return IRQ_HANDLED;
-} /* cyy_interrupt */
-
-static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
- unsigned int clear)
-{
- struct cyclades_card *card = info->card;
- int channel = info->line - card->first_line;
- u32 rts, dtr, msvrr, msvrd;
-
- channel &= 0x03;
-
- if (info->rtsdtr_inv) {
- msvrr = CyMSVR2;
- msvrd = CyMSVR1;
- rts = CyDTR;
- dtr = CyRTS;
- } else {
- msvrr = CyMSVR1;
- msvrd = CyMSVR2;
- rts = CyRTS;
- dtr = CyDTR;
- }
- if (set & TIOCM_RTS) {
- cyy_writeb(info, CyCAR, channel);
- cyy_writeb(info, msvrr, rts);
- }
- if (clear & TIOCM_RTS) {
- cyy_writeb(info, CyCAR, channel);
- cyy_writeb(info, msvrr, ~rts);
- }
- if (set & TIOCM_DTR) {
- cyy_writeb(info, CyCAR, channel);
- cyy_writeb(info, msvrd, dtr);
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
- printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
- cyy_readb(info, CyMSVR1),
- cyy_readb(info, CyMSVR2));
-#endif
- }
- if (clear & TIOCM_DTR) {
- cyy_writeb(info, CyCAR, channel);
- cyy_writeb(info, msvrd, ~dtr);
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
- printk(KERN_DEBUG " status: 0x%x, 0x%x\n",
- cyy_readb(info, CyMSVR1),
- cyy_readb(info, CyMSVR2));
-#endif
- }
-}
-
-/***********************************************************/
-/********* End of block of Cyclom-Y specific code **********/
-/******** Start of block of Cyclades-Z specific code *******/
-/***********************************************************/
-
-static int
-cyz_fetch_msg(struct cyclades_card *cinfo,
- __u32 *channel, __u8 *cmd, __u32 *param)
-{
- struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
- unsigned long loc_doorbell;
-
- loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
- if (loc_doorbell) {
- *cmd = (char)(0xff & loc_doorbell);
- *channel = readl(&board_ctrl->fwcmd_channel);
- *param = (__u32) readl(&board_ctrl->fwcmd_param);
- cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
- return 1;
- }
- return 0;
-} /* cyz_fetch_msg */
-
-static int
-cyz_issue_cmd(struct cyclades_card *cinfo,
- __u32 channel, __u8 cmd, __u32 param)
-{
- struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
- __u32 __iomem *pci_doorbell;
- unsigned int index;
-
- if (!cyz_is_loaded(cinfo))
- return -1;
-
- index = 0;
- pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
- while ((readl(pci_doorbell) & 0xff) != 0) {
- if (index++ == 1000)
- return (int)(readl(pci_doorbell) & 0xff);
- udelay(50L);
- }
- cy_writel(&board_ctrl->hcmd_channel, channel);
- cy_writel(&board_ctrl->hcmd_param, param);
- cy_writel(pci_doorbell, (long)cmd);
-
- return 0;
-} /* cyz_issue_cmd */
-
-static void cyz_handle_rx(struct cyclades_port *info)
-{
- struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
- struct cyclades_card *cinfo = info->card;
- struct tty_port *port = &info->port;
- unsigned int char_count;
- int len;
-#ifdef BLOCKMOVE
- unsigned char *buf;
-#else
- char data;
-#endif
- __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
-
- rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
- rx_put = readl(&buf_ctrl->rx_put);
- rx_bufsize = readl(&buf_ctrl->rx_bufsize);
- rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
-
- if (!char_count)
- return;
-
-#ifdef CY_ENABLE_MONITORING
- info->mon.int_count++;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
-#endif
-
-#ifdef BLOCKMOVE
- /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
- for performance, but because of buffer boundaries, there
- may be several steps to the operation */
- while (1) {
- len = tty_prepare_flip_string(port, &buf,
- char_count);
- if (!len)
- break;
-
- len = min_t(unsigned int, min(len, char_count),
- rx_bufsize - new_rx_get);
-
- memcpy_fromio(buf, cinfo->base_addr +
- rx_bufaddr + new_rx_get, len);
-
- new_rx_get = (new_rx_get + len) &
- (rx_bufsize - 1);
- char_count -= len;
- info->icount.rx += len;
- info->idle_stats.recv_bytes += len;
- }
-#else
- len = tty_buffer_request_room(port, char_count);
- while (len--) {
- data = readb(cinfo->base_addr + rx_bufaddr +
- new_rx_get);
- new_rx_get = (new_rx_get + 1) &
- (rx_bufsize - 1);
- tty_insert_flip_char(port, data, TTY_NORMAL);
- info->idle_stats.recv_bytes++;
- info->icount.rx++;
- }
-#endif
-#ifdef CONFIG_CYZ_INTR
- /* Recalculate the number of chars in the RX buffer and issue
- a cmd in case it's higher than the RX high water mark */
- rx_put = readl(&buf_ctrl->rx_put);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
- if (char_count >= readl(&buf_ctrl->rx_threshold) &&
- !timer_pending(&info->rx_full_timer))
- mod_timer(&info->rx_full_timer, jiffies + 1);
-#endif
- info->idle_stats.recv_idle = jiffies;
- tty_schedule_flip(&info->port);
-
- /* Update rx_get */
- cy_writel(&buf_ctrl->rx_get, new_rx_get);
-}
-
-static void cyz_handle_tx(struct cyclades_port *info)
-{
- struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
- struct cyclades_card *cinfo = info->card;
- struct tty_struct *tty;
- u8 data;
- unsigned int char_count;
-#ifdef BLOCKMOVE
- int small_count;
-#endif
- __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
-
- if (info->xmit_cnt <= 0) /* Nothing to transmit */
- return;
-
- tx_get = readl(&buf_ctrl->tx_get);
- tx_put = readl(&buf_ctrl->tx_put);
- tx_bufsize = readl(&buf_ctrl->tx_bufsize);
- tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
- if (tx_put >= tx_get)
- char_count = tx_get - tx_put - 1 + tx_bufsize;
- else
- char_count = tx_get - tx_put - 1;
-
- if (!char_count)
- return;
-
- tty = tty_port_tty_get(&info->port);
- if (tty == NULL)
- goto ztxdone;
-
- if (info->x_char) { /* send special char */
- data = info->x_char;
-
- cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- info->x_char = 0;
- char_count--;
- info->icount.tx++;
- }
-#ifdef BLOCKMOVE
- while (0 < (small_count = min_t(unsigned int,
- tx_bufsize - tx_put, min_t(unsigned int,
- (SERIAL_XMIT_SIZE - info->xmit_tail),
- min_t(unsigned int, info->xmit_cnt,
- char_count))))) {
-
- memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put),
- &info->port.xmit_buf[info->xmit_tail],
- small_count);
-
- tx_put = (tx_put + small_count) & (tx_bufsize - 1);
- char_count -= small_count;
- info->icount.tx += small_count;
- info->xmit_cnt -= small_count;
- info->xmit_tail = (info->xmit_tail + small_count) &
- (SERIAL_XMIT_SIZE - 1);
- }
-#else
- while (info->xmit_cnt && char_count) {
- data = info->port.xmit_buf[info->xmit_tail];
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1) &
- (SERIAL_XMIT_SIZE - 1);
-
- cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- char_count--;
- info->icount.tx++;
- }
-#endif
- tty_wakeup(tty);
- tty_kref_put(tty);
-ztxdone:
- /* Update tx_put */
- cy_writel(&buf_ctrl->tx_put, tx_put);
-}
-
-static void cyz_handle_cmd(struct cyclades_card *cinfo)
-{
- struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
- struct cyclades_port *info;
- __u32 channel, param, fw_ver;
- __u8 cmd;
- int special_count;
- int delta_count;
-
- fw_ver = readl(&board_ctrl->fw_version);
-
- while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
- special_count = 0;
- delta_count = 0;
- info = &cinfo->ports[channel];
-
- switch (cmd) {
- case C_CM_PR_ERROR:
- tty_insert_flip_char(&info->port, 0, TTY_PARITY);
- info->icount.rx++;
- special_count++;
- break;
- case C_CM_FR_ERROR:
- tty_insert_flip_char(&info->port, 0, TTY_FRAME);
- info->icount.rx++;
- special_count++;
- break;
- case C_CM_RXBRK:
- tty_insert_flip_char(&info->port, 0, TTY_BREAK);
- info->icount.rx++;
- special_count++;
- break;
- case C_CM_MDCD:
- info->icount.dcd++;
- delta_count++;
- if (tty_port_check_carrier(&info->port)) {
- u32 dcd = fw_ver > 241 ? param :
- readl(&info->u.cyz.ch_ctrl->rs_status);
- if (dcd & C_RS_DCD)
- wake_up_interruptible(&info->port.open_wait);
- else
- tty_port_tty_hangup(&info->port, false);
- }
- break;
- case C_CM_MCTS:
- info->icount.cts++;
- delta_count++;
- break;
- case C_CM_MRI:
- info->icount.rng++;
- delta_count++;
- break;
- case C_CM_MDSR:
- info->icount.dsr++;
- delta_count++;
- break;
-#ifdef Z_WAKE
- case C_CM_IOCTLW:
- complete(&info->shutdown_wait);
- break;
-#endif
-#ifdef CONFIG_CYZ_INTR
- case C_CM_RXHIWM:
- case C_CM_RXNNDT:
- case C_CM_INTBACK2:
- /* Reception Interrupt */
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
- "port %ld\n", info->card, channel);
-#endif
- cyz_handle_rx(info);
- break;
- case C_CM_TXBEMPTY:
- case C_CM_TXLOWWM:
- case C_CM_INTBACK:
- /* Transmission Interrupt */
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
- "port %ld\n", info->card, channel);
-#endif
- cyz_handle_tx(info);
- break;
-#endif /* CONFIG_CYZ_INTR */
- case C_CM_FATAL:
- /* should do something with this !!! */
- break;
- default:
- break;
- }
- if (delta_count)
- wake_up_interruptible(&info->port.delta_msr_wait);
- if (special_count)
- tty_schedule_flip(&info->port);
- }
-}
-
-#ifdef CONFIG_CYZ_INTR
-static irqreturn_t cyz_interrupt(int irq, void *dev_id)
-{
- struct cyclades_card *cinfo = dev_id;
-
- if (unlikely(!cyz_is_loaded(cinfo))) {
-#ifdef CY_DEBUG_INTERRUPTS
- printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
- "(IRQ%d).\n", irq);
-#endif
- return IRQ_NONE;
- }
-
- /* Handle the interrupts */
- cyz_handle_cmd(cinfo);
-
- return IRQ_HANDLED;
-} /* cyz_interrupt */
-
-static void cyz_rx_restart(struct timer_list *t)
-{
- struct cyclades_port *info = from_timer(info, t, rx_full_timer);
- struct cyclades_card *card = info->card;
- int retval;
- __u32 channel = info->line - card->first_line;
- unsigned long flags;
-
- spin_lock_irqsave(&card->card_lock, flags);
- retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
- info->line, retval);
- }
- spin_unlock_irqrestore(&card->card_lock, flags);
-}
-
-#else /* CONFIG_CYZ_INTR */
-
-static void cyz_poll(struct timer_list *unused)
-{
- struct cyclades_card *cinfo;
- struct cyclades_port *info;
- unsigned long expires = jiffies + HZ;
- unsigned int port, card;
-
- for (card = 0; card < NR_CARDS; card++) {
- cinfo = &cy_card[card];
-
- if (!cy_is_Z(cinfo))
- continue;
- if (!cyz_is_loaded(cinfo))
- continue;
-
- /* Skip first polling cycle to avoid racing conditions with the FW */
- if (!cinfo->intr_enabled) {
- cinfo->intr_enabled = 1;
- continue;
- }
-
- cyz_handle_cmd(cinfo);
-
- for (port = 0; port < cinfo->nports; port++) {
- info = &cinfo->ports[port];
-
- if (!info->throttle)
- cyz_handle_rx(info);
- cyz_handle_tx(info);
- }
- /* poll every 'cyz_polling_cycle' period */
- expires = jiffies + cyz_polling_cycle;
- }
- mod_timer(&cyz_timerlist, expires);
-} /* cyz_poll */
-
-#endif /* CONFIG_CYZ_INTR */
-
-/********** End of block of Cyclades-Z specific code *********/
-/***********************************************************/
-
-/* This is called whenever a port becomes active;
- interrupts are enabled and DTR & RTS are turned on.
- */
-static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
-{
- struct cyclades_card *card;
- unsigned long flags;
- int retval = 0;
- int channel;
- unsigned long page;
-
- card = info->card;
- channel = info->line - card->first_line;
-
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- spin_lock_irqsave(&card->card_lock, flags);
-
- if (tty_port_initialized(&info->port))
- goto errout;
-
- if (!info->type) {
- set_bit(TTY_IO_ERROR, &tty->flags);
- goto errout;
- }
-
- if (info->port.xmit_buf)
- free_page(page);
- else
- info->port.xmit_buf = (unsigned char *)page;
-
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- cy_set_line_char(info, tty);
-
- if (!cy_is_Z(card)) {
- channel &= 0x03;
-
- spin_lock_irqsave(&card->card_lock, flags);
-
- cyy_writeb(info, CyCAR, channel);
-
- cyy_writeb(info, CyRTPR,
- (info->default_timeout ? info->default_timeout : 0x02));
- /* 10ms rx timeout */
-
- cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR);
-
- cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
-
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData);
- } else {
- struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-
- if (!cyz_is_loaded(card))
- return -ENODEV;
-
-#ifdef CY_DEBUG_OPEN
- printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
- "base_addr %p\n", card, channel, card->base_addr);
-#endif
- spin_lock_irqsave(&card->card_lock, flags);
-
- cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE);
-#ifdef Z_WAKE
-#ifdef CONFIG_CYZ_INTR
- cy_writel(&ch_ctrl->intr_enable,
- C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
- C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
-#else
- cy_writel(&ch_ctrl->intr_enable,
- C_IN_IOCTLW | C_IN_MDCD);
-#endif /* CONFIG_CYZ_INTR */
-#else
-#ifdef CONFIG_CYZ_INTR
- cy_writel(&ch_ctrl->intr_enable,
- C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
- C_IN_RXNNDT | C_IN_MDCD);
-#else
- cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD);
-#endif /* CONFIG_CYZ_INTR */
-#endif /* Z_WAKE */
-
- retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
- "%x\n", info->line, retval);
- }
-
- /* Flush RX buffers before raising DTR and RTS */
- retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
- "%x\n", info->line, retval);
- }
-
- /* set timeout !!! */
- /* set RTS and DTR !!! */
- tty_port_raise_dtr_rts(&info->port);
-
- /* enable send, recv, modem !!! */
- }
-
- tty_port_set_initialized(&info->port, 1);
-
- clear_bit(TTY_IO_ERROR, &tty->flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- info->breakon = info->breakoff = 0;
- memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
- info->idle_stats.in_use =
- info->idle_stats.recv_idle =
- info->idle_stats.xmit_idle = jiffies;
-
- spin_unlock_irqrestore(&card->card_lock, flags);
-
-#ifdef CY_DEBUG_OPEN
- printk(KERN_DEBUG "cyc startup done\n");
-#endif
- return 0;
-
-errout:
- spin_unlock_irqrestore(&card->card_lock, flags);
- free_page(page);
- return retval;
-} /* startup */
-
-static void start_xmit(struct cyclades_port *info)
-{
- struct cyclades_card *card = info->card;
- unsigned long flags;
- int channel = info->line - card->first_line;
-
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_writeb(info, CyCAR, channel & 0x03);
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
- spin_unlock_irqrestore(&card->card_lock, flags);
- } else {
-#ifdef CONFIG_CYZ_INTR
- int retval;
-
- spin_lock_irqsave(&card->card_lock, flags);
- retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
- "%x\n", info->line, retval);
- }
- spin_unlock_irqrestore(&card->card_lock, flags);
-#else /* CONFIG_CYZ_INTR */
- /* Don't have to do anything at this time */
-#endif /* CONFIG_CYZ_INTR */
- }
-} /* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
-{
- struct cyclades_card *card;
- unsigned long flags;
-
- if (!tty_port_initialized(&info->port))
- return;
-
- card = info->card;
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
-
- /* Clear delta_msr_wait queue to avoid mem leaks. */
- wake_up_interruptible(&info->port.delta_msr_wait);
-
- if (info->port.xmit_buf) {
- unsigned char *temp;
- temp = info->port.xmit_buf;
- info->port.xmit_buf = NULL;
- free_page((unsigned long)temp);
- }
- if (C_HUPCL(tty))
- cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
-
- cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
- /* it may be appropriate to clear _XMIT at
- some later date (after testing)!!! */
-
- set_bit(TTY_IO_ERROR, &tty->flags);
- tty_port_set_initialized(&info->port, 0);
- spin_unlock_irqrestore(&card->card_lock, flags);
- } else {
-#ifdef CY_DEBUG_OPEN
- int channel = info->line - card->first_line;
- printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
- "base_addr %p\n", card, channel, card->base_addr);
-#endif
-
- if (!cyz_is_loaded(card))
- return;
-
- spin_lock_irqsave(&card->card_lock, flags);
-
- if (info->port.xmit_buf) {
- unsigned char *temp;
- temp = info->port.xmit_buf;
- info->port.xmit_buf = NULL;
- free_page((unsigned long)temp);
- }
-
- if (C_HUPCL(tty))
- tty_port_lower_dtr_rts(&info->port);
-
- set_bit(TTY_IO_ERROR, &tty->flags);
- tty_port_set_initialized(&info->port, 0);
-
- spin_unlock_irqrestore(&card->card_lock, flags);
- }
-
-#ifdef CY_DEBUG_OPEN
- printk(KERN_DEBUG "cyc shutdown done\n");
-#endif
-} /* shutdown */
-
-/*
- * ------------------------------------------------------------
- * cy_open() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * This routine is called whenever a serial port is opened. It
- * performs the serial-specific initialization for the tty structure.
- */
-static int cy_open(struct tty_struct *tty, struct file *filp)
-{
- struct cyclades_port *info;
- unsigned int i, line = tty->index;
- int retval;
-
- for (i = 0; i < NR_CARDS; i++)
- if (line < cy_card[i].first_line + cy_card[i].nports &&
- line >= cy_card[i].first_line)
- break;
- if (i >= NR_CARDS)
- return -ENODEV;
- info = &cy_card[i].ports[line - cy_card[i].first_line];
- if (info->line < 0)
- return -ENODEV;
-
- /* If the card's firmware hasn't been loaded,
- treat it as absent from the system. This
- will make the user pay attention.
- */
- if (cy_is_Z(info->card)) {
- struct cyclades_card *cinfo = info->card;
- struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
-
- if (!cyz_is_loaded(cinfo)) {
- if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
- readl(&firm_id->signature) ==
- ZFIRM_HLT) {
- printk(KERN_ERR "cyc:Cyclades-Z Error: you "
- "need an external power supply for "
- "this number of ports.\nFirmware "
- "halted.\n");
- } else {
- printk(KERN_ERR "cyc:Cyclades-Z firmware not "
- "yet loaded\n");
- }
- return -ENODEV;
- }
-#ifdef CONFIG_CYZ_INTR
- else {
- /* In case this Z board is operating in interrupt mode, its
- interrupts should be enabled as soon as the first open
- happens to one of its ports. */
- if (!cinfo->intr_enabled) {
- u16 intr;
-
- /* Enable interrupts on the PLX chip */
- intr = readw(&cinfo->ctl_addr.p9060->
- intr_ctrl_stat) | 0x0900;
- cy_writew(&cinfo->ctl_addr.p9060->
- intr_ctrl_stat, intr);
- /* Enable interrupts on the FW */
- retval = cyz_issue_cmd(cinfo, 0,
- C_CM_IRQ_ENBL, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:IRQ enable retval "
- "was %x\n", retval);
- }
- cinfo->intr_enabled = 1;
- }
- }
-#endif /* CONFIG_CYZ_INTR */
- /* Make sure this Z port really exists in hardware */
- if (info->line > (cinfo->first_line + cinfo->nports - 1))
- return -ENODEV;
- }
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
-#endif
- tty->driver_data = info;
- if (serial_paranoia_check(info, tty->name, "cy_open"))
- return -ENODEV;
-
-#ifdef CY_DEBUG_OPEN
- printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
- info->port.count);
-#endif
- info->port.count++;
-#ifdef CY_DEBUG_COUNT
- printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
- current->pid, info->port.count);
-#endif
-
- /*
- * Start up serial port
- */
- retval = cy_startup(info, tty);
- if (retval)
- return retval;
-
- retval = tty_port_block_til_ready(&info->port, tty, filp);
- if (retval) {
-#ifdef CY_DEBUG_OPEN
- printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
- "with %d\n", retval);
-#endif
- return retval;
- }
-
- info->throttle = 0;
- tty_port_tty_set(&info->port, tty);
-
-#ifdef CY_DEBUG_OPEN
- printk(KERN_DEBUG "cyc:cy_open done\n");
-#endif
- return 0;
-} /* cy_open */
-
-/*
- * cy_wait_until_sent() --- wait until the transmitter is empty
- */
-static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- struct cyclades_card *card;
- struct cyclades_port *info = tty->driver_data;
- unsigned long orig_jiffies;
- int char_time;
-
- if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
- return;
-
- if (info->xmit_fifo_size == 0)
- return; /* Just in case.... */
-
- orig_jiffies = jiffies;
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
- char_time = char_time / 5;
- if (char_time <= 0)
- char_time = 1;
- if (timeout < 0)
- timeout = 0;
- if (timeout)
- char_time = min(char_time, timeout);
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than info->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*info->timeout.
- */
- if (!timeout || timeout > 2 * info->timeout)
- timeout = 2 * info->timeout;
-
- card = info->card;
- if (!cy_is_Z(card)) {
- while (cyy_readb(info, CySRER) & CyTxRdy) {
- if (msleep_interruptible(jiffies_to_msecs(char_time)))
- break;
- if (timeout && time_after(jiffies, orig_jiffies +
- timeout))
- break;
- }
- }
- /* Run one more char cycle */
- msleep_interruptible(jiffies_to_msecs(char_time * 5));
-}
-
-static void cy_flush_buffer(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- int channel, retval;
- unsigned long flags;
-
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
- return;
-
- card = info->card;
- channel = info->line - card->first_line;
-
- spin_lock_irqsave(&card->card_lock, flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board
- buffers as well */
- spin_lock_irqsave(&card->card_lock, flags);
- retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
- "was %x\n", info->line, retval);
- }
- spin_unlock_irqrestore(&card->card_lock, flags);
- }
- tty_wakeup(tty);
-} /* cy_flush_buffer */
-
-
-static void cy_do_close(struct tty_port *port)
-{
- struct cyclades_port *info = container_of(port, struct cyclades_port,
- port);
- struct cyclades_card *card;
- unsigned long flags;
- int channel;
-
- card = info->card;
- channel = info->line - card->first_line;
- spin_lock_irqsave(&card->card_lock, flags);
-
- if (!cy_is_Z(card)) {
- /* Stop accepting input */
- cyy_writeb(info, CyCAR, channel & 0x03);
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData);
- if (tty_port_initialized(&info->port)) {
- /* Waiting for on-board buffers to be empty before
- closing the port */
- spin_unlock_irqrestore(&card->card_lock, flags);
- cy_wait_until_sent(port->tty, info->timeout);
- spin_lock_irqsave(&card->card_lock, flags);
- }
- } else {
-#ifdef Z_WAKE
- /* Waiting for on-board buffers to be empty before closing
- the port */
- struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
- int retval;
-
- if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
- retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
- if (retval != 0) {
- printk(KERN_DEBUG "cyc:cy_close retval on "
- "ttyC%d was %x\n", info->line, retval);
- }
- spin_unlock_irqrestore(&card->card_lock, flags);
- wait_for_completion_interruptible(&info->shutdown_wait);
- spin_lock_irqsave(&card->card_lock, flags);
- }
-#endif
- }
- spin_unlock_irqrestore(&card->card_lock, flags);
- cy_shutdown(info, port->tty);
-}
-
-/*
- * This routine is called when a particular tty device is closed.
- */
-static void cy_close(struct tty_struct *tty, struct file *filp)
-{
- struct cyclades_port *info = tty->driver_data;
- if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
- return;
- tty_port_close(&info->port, tty, filp);
-} /* cy_close */
-
-/* This routine gets called when tty_write has put something into
- * the write_queue. The characters may come from user space or
- * kernel space.
- *
- * This routine will return the number of characters actually
- * accepted for writing.
- *
- * If the port is not already transmitting stuff, start it off by
- * enabling interrupts. The interrupt service routine will then
- * ensure that the characters are sent.
- * If the port is already active, there is no need to kick it.
- *
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
- struct cyclades_port *info = tty->driver_data;
- unsigned long flags;
- int c, ret = 0;
-
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_write"))
- return 0;
-
- if (!info->port.xmit_buf)
- return 0;
-
- spin_lock_irqsave(&info->card->card_lock, flags);
- while (1) {
- c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
- c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
-
- if (c <= 0)
- break;
-
- memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = (info->xmit_head + c) &
- (SERIAL_XMIT_SIZE - 1);
- info->xmit_cnt += c;
- buf += c;
- count -= c;
- ret += c;
- }
- spin_unlock_irqrestore(&info->card->card_lock, flags);
-
- info->idle_stats.xmit_bytes += ret;
- info->idle_stats.xmit_idle = jiffies;
-
- if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
- start_xmit(info);
-
- return ret;
-} /* cy_write */
-
-/*
- * This routine is called by the kernel to write a single
- * character to the tty device. If the kernel uses this routine,
- * it must call the flush_chars() routine (if defined) when it is
- * done stuffing characters into the driver. If there is no room
- * in the queue, the character is ignored.
- */
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct cyclades_port *info = tty->driver_data;
- unsigned long flags;
-
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_put_char"))
- return 0;
-
- if (!info->port.xmit_buf)
- return 0;
-
- spin_lock_irqsave(&info->card->card_lock, flags);
- if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
- spin_unlock_irqrestore(&info->card->card_lock, flags);
- return 0;
- }
-
- info->port.xmit_buf[info->xmit_head++] = ch;
- info->xmit_head &= SERIAL_XMIT_SIZE - 1;
- info->xmit_cnt++;
- info->idle_stats.xmit_bytes++;
- info->idle_stats.xmit_idle = jiffies;
- spin_unlock_irqrestore(&info->card->card_lock, flags);
- return 1;
-} /* cy_put_char */
-
-/*
- * This routine is called by the kernel after it has written a
- * series of characters to the tty device using put_char().
- */
-static void cy_flush_chars(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
- return;
-
- if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
- !info->port.xmit_buf)
- return;
-
- start_xmit(info);
-} /* cy_flush_chars */
-
-/*
- * This routine returns the numbers of characters the tty driver
- * will accept for queuing to be written. This number is subject
- * to change as output buffers get emptied, or if the output flow
- * control is activated.
- */
-static int cy_write_room(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- int ret;
-
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_write_room"))
- return 0;
- ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
- if (ret < 0)
- ret = 0;
- return ret;
-} /* cy_write_room */
-
-static int cy_chars_in_buffer(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
-
- if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
- return 0;
-
-#ifdef Z_EXT_CHARS_IN_BUFFER
- if (!cy_is_Z(info->card)) {
-#endif /* Z_EXT_CHARS_IN_BUFFER */
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
- info->line, info->xmit_cnt);
-#endif
- return info->xmit_cnt;
-#ifdef Z_EXT_CHARS_IN_BUFFER
- } else {
- struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
- int char_count;
- __u32 tx_put, tx_get, tx_bufsize;
-
- tx_get = readl(&buf_ctrl->tx_get);
- tx_put = readl(&buf_ctrl->tx_put);
- tx_bufsize = readl(&buf_ctrl->tx_bufsize);
- if (tx_put >= tx_get)
- char_count = tx_put - tx_get;
- else
- char_count = tx_put - tx_get + tx_bufsize;
-#ifdef CY_DEBUG_IO
- printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
- info->line, info->xmit_cnt + char_count);
-#endif
- return info->xmit_cnt + char_count;
- }
-#endif /* Z_EXT_CHARS_IN_BUFFER */
-} /* cy_chars_in_buffer */
-
-/*
- * ------------------------------------------------------------
- * cy_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
-{
- int co, co_val, bpr;
- __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
- 25000000);
-
- if (baud == 0) {
- info->tbpr = info->tco = info->rbpr = info->rco = 0;
- return;
- }
-
- /* determine which prescaler to use */
- for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
- if (cy_clock / co_val / baud > 63)
- break;
- }
-
- bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
- if (bpr > 255)
- bpr = 255;
-
- info->tbpr = info->rbpr = bpr;
- info->tco = info->rco = co;
-}
-
-/*
- * This routine finds or computes the various line characteristics.
- * It used to be called config_setup
- */
-static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
-{
- struct cyclades_card *card;
- unsigned long flags;
- int channel;
- unsigned cflag, iflag;
- int baud, baud_rate = 0;
- int i;
-
- if (info->line == -1)
- return;
-
- cflag = tty->termios.c_cflag;
- iflag = tty->termios.c_iflag;
-
- card = info->card;
- channel = info->line - card->first_line;
-
- if (!cy_is_Z(card)) {
- u32 cflags;
-
- /* baud rate */
- baud = tty_get_baud_rate(tty);
- if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
- ASYNC_SPD_CUST) {
- if (info->custom_divisor)
- baud_rate = info->baud / info->custom_divisor;
- else
- baud_rate = info->baud;
- } else if (baud > CD1400_MAX_SPEED) {
- baud = CD1400_MAX_SPEED;
- }
- /* find the baud index */
- for (i = 0; i < 20; i++) {
- if (baud == baud_table[i])
- break;
- }
- if (i == 20)
- i = 19; /* CD1400_MAX_SPEED */
-
- if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
- ASYNC_SPD_CUST) {
- cyy_baud_calc(info, baud_rate);
- } else {
- if (info->chip_rev >= CD1400_REV_J) {
- /* It is a CD1400 rev. J or later */
- info->tbpr = baud_bpr_60[i]; /* Tx BPR */
- info->tco = baud_co_60[i]; /* Tx CO */
- info->rbpr = baud_bpr_60[i]; /* Rx BPR */
- info->rco = baud_co_60[i]; /* Rx CO */
- } else {
- info->tbpr = baud_bpr_25[i]; /* Tx BPR */
- info->tco = baud_co_25[i]; /* Tx CO */
- info->rbpr = baud_bpr_25[i]; /* Rx BPR */
- info->rco = baud_co_25[i]; /* Rx CO */
- }
- }
- if (baud_table[i] == 134) {
- /* get it right for 134.5 baud */
- info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
- 2;
- } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
- ASYNC_SPD_CUST) {
- info->timeout = (info->xmit_fifo_size * HZ * 15 /
- baud_rate) + 2;
- } else if (baud_table[i]) {
- info->timeout = (info->xmit_fifo_size * HZ * 15 /
- baud_table[i]) + 2;
- /* this needs to be propagated into the card info */
- } else {
- info->timeout = 0;
- }
- /* By tradition (is it a standard?) a baud rate of zero
- implies the line should be/has been closed. A bit
- later in this routine such a test is performed. */
-
- /* byte size and parity */
- info->cor5 = 0;
- info->cor4 = 0;
- /* receive threshold */
- info->cor3 = (info->default_threshold ?
- info->default_threshold : baud_cor3[i]);
- info->cor2 = CyETC;
- switch (cflag & CSIZE) {
- case CS5:
- info->cor1 = Cy_5_BITS;
- break;
- case CS6:
- info->cor1 = Cy_6_BITS;
- break;
- case CS7:
- info->cor1 = Cy_7_BITS;
- break;
- case CS8:
- info->cor1 = Cy_8_BITS;
- break;
- }
- if (cflag & CSTOPB)
- info->cor1 |= Cy_2_STOP;
-
- if (cflag & PARENB) {
- if (cflag & PARODD)
- info->cor1 |= CyPARITY_O;
- else
- info->cor1 |= CyPARITY_E;
- } else
- info->cor1 |= CyPARITY_NONE;
-
- /* CTS flow control flag */
- tty_port_set_cts_flow(&info->port, cflag & CRTSCTS);
- if (cflag & CRTSCTS)
- info->cor2 |= CyCtsAE;
- else
- info->cor2 &= ~CyCtsAE;
- tty_port_set_check_carrier(&info->port, ~cflag & CLOCAL);
-
- /***********************************************
- The hardware option, CyRtsAO, presents RTS when
- the chip has characters to send. Since most modems
- use RTS as reverse (inbound) flow control, this
- option is not used. If inbound flow control is
- necessary, DTR can be programmed to provide the
- appropriate signals for use with a non-standard
- cable. Contact Marcio Saito for details.
- ***********************************************/
-
- channel &= 0x03;
-
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_writeb(info, CyCAR, channel);
-
- /* tx and rx baud rate */
-
- cyy_writeb(info, CyTCOR, info->tco);
- cyy_writeb(info, CyTBPR, info->tbpr);
- cyy_writeb(info, CyRCOR, info->rco);
- cyy_writeb(info, CyRBPR, info->rbpr);
-
- /* set line characteristics according configuration */
-
- cyy_writeb(info, CySCHR1, START_CHAR(tty));
- cyy_writeb(info, CySCHR2, STOP_CHAR(tty));
- cyy_writeb(info, CyCOR1, info->cor1);
- cyy_writeb(info, CyCOR2, info->cor2);
- cyy_writeb(info, CyCOR3, info->cor3);
- cyy_writeb(info, CyCOR4, info->cor4);
- cyy_writeb(info, CyCOR5, info->cor5);
-
- cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
- CyCOR3ch);
-
- /* !!! Is this needed? */
- cyy_writeb(info, CyCAR, channel);
- cyy_writeb(info, CyRTPR,
- (info->default_timeout ? info->default_timeout : 0x02));
- /* 10ms rx timeout */
-
- cflags = CyCTS;
- if (!C_CLOCAL(tty))
- cflags |= CyDSR | CyRI | CyDCD;
- /* without modem intr */
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
- /* act on 1->0 modem transitions */
- if ((cflag & CRTSCTS) && info->rflow)
- cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
- else
- cyy_writeb(info, CyMCOR1, cflags);
- /* act on 0->1 modem transitions */
- cyy_writeb(info, CyMCOR2, cflags);
-
- if (i == 0) /* baud rate is zero, turn off line */
- cyy_change_rts_dtr(info, 0, TIOCM_DTR);
- else
- cyy_change_rts_dtr(info, TIOCM_DTR, 0);
-
- clear_bit(TTY_IO_ERROR, &tty->flags);
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- } else {
- struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
- __u32 sw_flow;
- int retval;
-
- if (!cyz_is_loaded(card))
- return;
-
- /* baud rate */
- baud = tty_get_baud_rate(tty);
- if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
- ASYNC_SPD_CUST) {
- if (info->custom_divisor)
- baud_rate = info->baud / info->custom_divisor;
- else
- baud_rate = info->baud;
- } else if (baud > CYZ_MAX_SPEED) {
- baud = CYZ_MAX_SPEED;
- }
- cy_writel(&ch_ctrl->comm_baud, baud);
-
- if (baud == 134) {
- /* get it right for 134.5 baud */
- info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
- 2;
- } else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
- ASYNC_SPD_CUST) {
- info->timeout = (info->xmit_fifo_size * HZ * 15 /
- baud_rate) + 2;
- } else if (baud) {
- info->timeout = (info->xmit_fifo_size * HZ * 15 /
- baud) + 2;
- /* this needs to be propagated into the card info */
- } else {
- info->timeout = 0;
- }
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5:
- cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
- break;
- case CS6:
- cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
- break;
- case CS7:
- cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
- break;
- case CS8:
- cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
- break;
- }
- if (cflag & CSTOPB) {
- cy_writel(&ch_ctrl->comm_data_l,
- readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
- } else {
- cy_writel(&ch_ctrl->comm_data_l,
- readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
- }
- if (cflag & PARENB) {
- if (cflag & PARODD)
- cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
- else
- cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
- } else
- cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
-
- /* CTS flow control flag */
- if (cflag & CRTSCTS) {
- cy_writel(&ch_ctrl->hw_flow,
- readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
- } else {
- cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
- ~(C_RS_CTS | C_RS_RTS));
- }
- /* As the HW flow control is done in firmware, the driver
- doesn't need to care about it */
- tty_port_set_cts_flow(&info->port, 0);
-
- /* XON/XOFF/XANY flow control flags */
- sw_flow = 0;
- if (iflag & IXON) {
- sw_flow |= C_FL_OXX;
- if (iflag & IXANY)
- sw_flow |= C_FL_OIXANY;
- }
- cy_writel(&ch_ctrl->sw_flow, sw_flow);
-
- retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
- "was %x\n", info->line, retval);
- }
-
- /* CD sensitivity */
- tty_port_set_check_carrier(&info->port, ~cflag & CLOCAL);
-
- if (baud == 0) { /* baud rate is zero, turn off line */
- cy_writel(&ch_ctrl->rs_control,
- readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n");
-#endif
- } else {
- cy_writel(&ch_ctrl->rs_control,
- readl(&ch_ctrl->rs_control) | C_RS_DTR);
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n");
-#endif
- }
-
- retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
- "was %x\n", info->line, retval);
- }
-
- clear_bit(TTY_IO_ERROR, &tty->flags);
- }
-} /* set_line_char */
-
-static int cy_get_serial_info(struct tty_struct *tty,
- struct serial_struct *ss)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *cinfo = info->card;
-
- if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
- return -ENODEV;
- ss->type = info->type;
- ss->line = info->line;
- ss->port = (info->card - cy_card) * 0x100 + info->line -
- cinfo->first_line;
- ss->irq = cinfo->irq;
- ss->flags = info->port.flags;
- ss->close_delay = info->port.close_delay;
- ss->closing_wait = info->port.closing_wait;
- ss->baud_base = info->baud;
- ss->custom_divisor = info->custom_divisor;
- return 0;
-}
-
-static int cy_set_serial_info(struct tty_struct *tty,
- struct serial_struct *ss)
-{
- struct cyclades_port *info = tty->driver_data;
- int old_flags;
- int ret;
-
- if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
- return -ENODEV;
-
- mutex_lock(&info->port.mutex);
-
- old_flags = info->port.flags;
-
- if (!capable(CAP_SYS_ADMIN)) {
- if (ss->close_delay != info->port.close_delay ||
- ss->baud_base != info->baud ||
- (ss->flags & ASYNC_FLAGS &
- ~ASYNC_USR_MASK) !=
- (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
- {
- mutex_unlock(&info->port.mutex);
- return -EPERM;
- }
- info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
- (ss->flags & ASYNC_USR_MASK);
- info->baud = ss->baud_base;
- info->custom_divisor = ss->custom_divisor;
- goto check_and_exit;
- }
-
- /*
- * OK, past this point, all the error checking has been done.
- * At this point, we start making changes.....
- */
-
- info->baud = ss->baud_base;
- info->custom_divisor = ss->custom_divisor;
- info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
- (ss->flags & ASYNC_FLAGS);
- info->port.close_delay = ss->close_delay * HZ / 100;
- info->port.closing_wait = ss->closing_wait * HZ / 100;
-
-check_and_exit:
- if (tty_port_initialized(&info->port)) {
- if ((ss->flags ^ old_flags) & ASYNC_SPD_MASK) {
- /* warn about deprecation unless clearing */
- if (ss->flags & ASYNC_SPD_MASK)
- dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
- }
- cy_set_line_char(info, tty);
- ret = 0;
- } else {
- ret = cy_startup(info, tty);
- }
- mutex_unlock(&info->port.mutex);
- return ret;
-} /* set_serial_info */
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
-{
- struct cyclades_card *card = info->card;
- unsigned int result;
- unsigned long flags;
- u8 status;
-
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
- status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty);
- spin_unlock_irqrestore(&card->card_lock, flags);
- result = (status ? 0 : TIOCSER_TEMT);
- } else {
- /* Not supported yet */
- return -EINVAL;
- }
- return put_user(result, value);
-}
-
-static int cy_tiocmget(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- int result;
-
- if (serial_paranoia_check(info, tty->name, __func__))
- return -ENODEV;
-
- card = info->card;
-
- if (!cy_is_Z(card)) {
- unsigned long flags;
- int channel = info->line - card->first_line;
- u8 status;
-
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_writeb(info, CyCAR, channel & 0x03);
- status = cyy_readb(info, CyMSVR1);
- status |= cyy_readb(info, CyMSVR2);
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- if (info->rtsdtr_inv) {
- result = ((status & CyRTS) ? TIOCM_DTR : 0) |
- ((status & CyDTR) ? TIOCM_RTS : 0);
- } else {
- result = ((status & CyRTS) ? TIOCM_RTS : 0) |
- ((status & CyDTR) ? TIOCM_DTR : 0);
- }
- result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
- ((status & CyRI) ? TIOCM_RNG : 0) |
- ((status & CyDSR) ? TIOCM_DSR : 0) |
- ((status & CyCTS) ? TIOCM_CTS : 0);
- } else {
- u32 lstatus;
-
- if (!cyz_is_loaded(card)) {
- result = -ENODEV;
- goto end;
- }
-
- lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
- result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
- ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
- ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
- ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
- ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
- ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
- }
-end:
- return result;
-} /* cy_tiomget */
-
-static int
-cy_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->name, __func__))
- return -ENODEV;
-
- card = info->card;
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_change_rts_dtr(info, set, clear);
- spin_unlock_irqrestore(&card->card_lock, flags);
- } else {
- struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
- int retval, channel = info->line - card->first_line;
- u32 rs;
-
- if (!cyz_is_loaded(card))
- return -ENODEV;
-
- spin_lock_irqsave(&card->card_lock, flags);
- rs = readl(&ch_ctrl->rs_control);
- if (set & TIOCM_RTS)
- rs |= C_RS_RTS;
- if (clear & TIOCM_RTS)
- rs &= ~C_RS_RTS;
- if (set & TIOCM_DTR) {
- rs |= C_RS_DTR;
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n");
-#endif
- }
- if (clear & TIOCM_DTR) {
- rs &= ~C_RS_DTR;
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "cyc:set_modem_info clearing "
- "Z DTR\n");
-#endif
- }
- cy_writel(&ch_ctrl->rs_control, rs);
- retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
- spin_unlock_irqrestore(&card->card_lock, flags);
- if (retval != 0) {
- printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
- "was %x\n", info->line, retval);
- }
- }
- return 0;
-}
-
-/*
- * cy_break() --- routine which turns the break handling on or off
- */
-static int cy_break(struct tty_struct *tty, int break_state)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- unsigned long flags;
- int retval = 0;
-
- if (serial_paranoia_check(info, tty->name, "cy_break"))
- return -EINVAL;
-
- card = info->card;
-
- spin_lock_irqsave(&card->card_lock, flags);
- if (!cy_is_Z(card)) {
- /* Let the transmit ISR take care of this (since it
- requires stuffing characters into the output stream).
- */
- if (break_state == -1) {
- if (!info->breakon) {
- info->breakon = 1;
- if (!info->xmit_cnt) {
- spin_unlock_irqrestore(&card->card_lock, flags);
- start_xmit(info);
- spin_lock_irqsave(&card->card_lock, flags);
- }
- }
- } else {
- if (!info->breakoff) {
- info->breakoff = 1;
- if (!info->xmit_cnt) {
- spin_unlock_irqrestore(&card->card_lock, flags);
- start_xmit(info);
- spin_lock_irqsave(&card->card_lock, flags);
- }
- }
- }
- } else {
- if (break_state == -1) {
- retval = cyz_issue_cmd(card,
- info->line - card->first_line,
- C_CM_SET_BREAK, 0L);
- if (retval != 0) {
- printk(KERN_ERR "cyc:cy_break (set) retval on "
- "ttyC%d was %x\n", info->line, retval);
- }
- } else {
- retval = cyz_issue_cmd(card,
- info->line - card->first_line,
- C_CM_CLR_BREAK, 0L);
- if (retval != 0) {
- printk(KERN_DEBUG "cyc:cy_break (clr) retval "
- "on ttyC%d was %x\n", info->line,
- retval);
- }
- }
- }
- spin_unlock_irqrestore(&card->card_lock, flags);
- return retval;
-} /* cy_break */
-
-static int set_threshold(struct cyclades_port *info, unsigned long value)
-{
- struct cyclades_card *card = info->card;
- unsigned long flags;
-
- if (!cy_is_Z(card)) {
- info->cor3 &= ~CyREC_FIFO;
- info->cor3 |= value & CyREC_FIFO;
-
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_writeb(info, CyCOR3, info->cor3);
- cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch);
- spin_unlock_irqrestore(&card->card_lock, flags);
- }
- return 0;
-} /* set_threshold */
-
-static int get_threshold(struct cyclades_port *info,
- unsigned long __user *value)
-{
- struct cyclades_card *card = info->card;
-
- if (!cy_is_Z(card)) {
- u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO;
- return put_user(tmp, value);
- }
- return 0;
-} /* get_threshold */
-
-static int set_timeout(struct cyclades_port *info, unsigned long value)
-{
- struct cyclades_card *card = info->card;
- unsigned long flags;
-
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_writeb(info, CyRTPR, value & 0xff);
- spin_unlock_irqrestore(&card->card_lock, flags);
- }
- return 0;
-} /* set_timeout */
-
-static int get_timeout(struct cyclades_port *info,
- unsigned long __user *value)
-{
- struct cyclades_card *card = info->card;
-
- if (!cy_is_Z(card)) {
- u8 tmp = cyy_readb(info, CyRTPR);
- return put_user(tmp, value);
- }
- return 0;
-} /* get_timeout */
-
-static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg,
- struct cyclades_icount *cprev)
-{
- struct cyclades_icount cnow;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&info->card->card_lock, flags);
- cnow = info->icount; /* atomic copy */
- spin_unlock_irqrestore(&info->card->card_lock, flags);
-
- ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
-
- *cprev = cnow;
-
- return ret;
-}
-
-/*
- * This routine allows the tty driver to implement device-
- * specific ioctl's. If the ioctl number passed in cmd is
- * not recognized by the driver, it should return ENOIOCTLCMD.
- */
-static int
-cy_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_icount cnow; /* kernel counter temps */
- int ret_val = 0;
- unsigned long flags;
- void __user *argp = (void __user *)arg;
-
- if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
- return -ENODEV;
-
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
- info->line, cmd, arg);
-#endif
-
- switch (cmd) {
- case CYGETMON:
- if (copy_to_user(argp, &info->mon, sizeof(info->mon))) {
- ret_val = -EFAULT;
- break;
- }
- memset(&info->mon, 0, sizeof(info->mon));
- break;
- case CYGETTHRESH:
- ret_val = get_threshold(info, argp);
- break;
- case CYSETTHRESH:
- ret_val = set_threshold(info, arg);
- break;
- case CYGETDEFTHRESH:
- ret_val = put_user(info->default_threshold,
- (unsigned long __user *)argp);
- break;
- case CYSETDEFTHRESH:
- info->default_threshold = arg & 0x0f;
- break;
- case CYGETTIMEOUT:
- ret_val = get_timeout(info, argp);
- break;
- case CYSETTIMEOUT:
- ret_val = set_timeout(info, arg);
- break;
- case CYGETDEFTIMEOUT:
- ret_val = put_user(info->default_timeout,
- (unsigned long __user *)argp);
- break;
- case CYSETDEFTIMEOUT:
- info->default_timeout = arg & 0xff;
- break;
- case CYSETRFLOW:
- info->rflow = (int)arg;
- break;
- case CYGETRFLOW:
- ret_val = info->rflow;
- break;
- case CYSETRTSDTR_INV:
- info->rtsdtr_inv = (int)arg;
- break;
- case CYGETRTSDTR_INV:
- ret_val = info->rtsdtr_inv;
- break;
- case CYGETCD1400VER:
- ret_val = info->chip_rev;
- break;
-#ifndef CONFIG_CYZ_INTR
- case CYZSETPOLLCYCLE:
- if (arg > LONG_MAX / HZ)
- return -ENODEV;
- cyz_polling_cycle = (arg * HZ) / 1000;
- break;
- case CYZGETPOLLCYCLE:
- ret_val = (cyz_polling_cycle * 1000) / HZ;
- break;
-#endif /* CONFIG_CYZ_INTR */
- case CYSETWAIT:
- info->port.closing_wait = (unsigned short)arg * HZ / 100;
- break;
- case CYGETWAIT:
- ret_val = info->port.closing_wait / (HZ / 100);
- break;
- case TIOCSERGETLSR: /* Get line status register */
- ret_val = get_lsr_info(info, argp);
- break;
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
- spin_lock_irqsave(&info->card->card_lock, flags);
- /* note the counters on entry */
- cnow = info->icount;
- spin_unlock_irqrestore(&info->card->card_lock, flags);
- ret_val = wait_event_interruptible(info->port.delta_msr_wait,
- cy_cflags_changed(info, arg, &cnow));
- break;
-
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- default:
- ret_val = -ENOIOCTLCMD;
- }
-
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_ioctl done\n");
-#endif
- return ret_val;
-} /* cy_ioctl */
-
-static int cy_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *sic)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_icount cnow; /* Used to snapshot */
- unsigned long flags;
-
- spin_lock_irqsave(&info->card->card_lock, flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->card->card_lock, flags);
-
- sic->cts = cnow.cts;
- sic->dsr = cnow.dsr;
- sic->rng = cnow.rng;
- sic->dcd = cnow.dcd;
- sic->rx = cnow.rx;
- sic->tx = cnow.tx;
- sic->frame = cnow.frame;
- sic->overrun = cnow.overrun;
- sic->parity = cnow.parity;
- sic->brk = cnow.brk;
- sic->buf_overrun = cnow.buf_overrun;
- return 0;
-}
-
-/*
- * This routine allows the tty driver to be notified when
- * device's termios settings have changed. Note that a
- * well-designed tty driver should be prepared to accept the case
- * where old == NULL, and try to do something rational.
- */
-static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
- struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
-#endif
-
- cy_set_line_char(info, tty);
-
- if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
- tty->hw_stopped = 0;
- cy_start(tty);
- }
-#if 0
- /*
- * No need to wake up processes in open wait, since they
- * sample the CLOCAL flag once, and don't recheck it.
- * XXX It's not clear whether the current behavior is correct
- * or not. Hence, this may change.....
- */
- if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
- wake_up_interruptible(&info->port.open_wait);
-#endif
-} /* cy_set_termios */
-
-/* This function is used to send a high-priority XON/XOFF character to
- the device.
-*/
-static void cy_send_xchar(struct tty_struct *tty, char ch)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- int channel;
-
- if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
- return;
-
- info->x_char = ch;
-
- if (ch)
- cy_start(tty);
-
- card = info->card;
- channel = info->line - card->first_line;
-
- if (cy_is_Z(card)) {
- if (ch == STOP_CHAR(tty))
- cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
- else if (ch == START_CHAR(tty))
- cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
- }
-}
-
-/* This routine is called by the upper-layer tty layer to signal
- that incoming characters should be throttled because the input
- buffers are close to full.
- */
-static void cy_throttle(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- unsigned long flags;
-
-#ifdef CY_DEBUG_THROTTLE
- printk(KERN_DEBUG "cyc:throttle %s ...ttyC%d\n", tty_name(tty),
- info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_throttle"))
- return;
-
- card = info->card;
-
- if (I_IXOFF(tty)) {
- if (!cy_is_Z(card))
- cy_send_xchar(tty, STOP_CHAR(tty));
- else
- info->throttle = 1;
- }
-
- if (C_CRTSCTS(tty)) {
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_change_rts_dtr(info, 0, TIOCM_RTS);
- spin_unlock_irqrestore(&card->card_lock, flags);
- } else {
- info->throttle = 1;
- }
- }
-} /* cy_throttle */
-
-/*
- * This routine notifies the tty driver that it should signal
- * that characters can now be sent to the tty without fear of
- * overrunning the input buffers of the line disciplines.
- */
-static void cy_unthrottle(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
- struct cyclades_card *card;
- unsigned long flags;
-
-#ifdef CY_DEBUG_THROTTLE
- printk(KERN_DEBUG "cyc:unthrottle %s ...ttyC%d\n",
- tty_name(tty), info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
- return;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- cy_send_xchar(tty, START_CHAR(tty));
- }
-
- if (C_CRTSCTS(tty)) {
- card = info->card;
- if (!cy_is_Z(card)) {
- spin_lock_irqsave(&card->card_lock, flags);
- cyy_change_rts_dtr(info, TIOCM_RTS, 0);
- spin_unlock_irqrestore(&card->card_lock, flags);
- } else {
- info->throttle = 0;
- }
- }
-} /* cy_unthrottle */
-
-/* cy_start and cy_stop provide software output flow control as a
- function of XON/XOFF, software CTS, and other such stuff.
-*/
-static void cy_stop(struct tty_struct *tty)
-{
- struct cyclades_card *cinfo;
- struct cyclades_port *info = tty->driver_data;
- int channel;
- unsigned long flags;
-
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_stop"))
- return;
-
- cinfo = info->card;
- channel = info->line - cinfo->first_line;
- if (!cy_is_Z(cinfo)) {
- spin_lock_irqsave(&cinfo->card_lock, flags);
- cyy_writeb(info, CyCAR, channel & 0x03);
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
- spin_unlock_irqrestore(&cinfo->card_lock, flags);
- }
-} /* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
- struct cyclades_card *cinfo;
- struct cyclades_port *info = tty->driver_data;
- int channel;
- unsigned long flags;
-
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_start"))
- return;
-
- cinfo = info->card;
- channel = info->line - cinfo->first_line;
- if (!cy_is_Z(cinfo)) {
- spin_lock_irqsave(&cinfo->card_lock, flags);
- cyy_writeb(info, CyCAR, channel & 0x03);
- cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
- spin_unlock_irqrestore(&cinfo->card_lock, flags);
- }
-} /* cy_start */
-
-/*
- * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void cy_hangup(struct tty_struct *tty)
-{
- struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_OTHER
- printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line);
-#endif
-
- if (serial_paranoia_check(info, tty->name, "cy_hangup"))
- return;
-
- cy_flush_buffer(tty);
- cy_shutdown(info, tty);
- tty_port_hangup(&info->port);
-} /* cy_hangup */
-
-static int cyy_carrier_raised(struct tty_port *port)
-{
- struct cyclades_port *info = container_of(port, struct cyclades_port,
- port);
- struct cyclades_card *cinfo = info->card;
- unsigned long flags;
- int channel = info->line - cinfo->first_line;
- u32 cd;
-
- spin_lock_irqsave(&cinfo->card_lock, flags);
- cyy_writeb(info, CyCAR, channel & 0x03);
- cd = cyy_readb(info, CyMSVR1) & CyDCD;
- spin_unlock_irqrestore(&cinfo->card_lock, flags);
-
- return cd;
-}
-
-static void cyy_dtr_rts(struct tty_port *port, int raise)
-{
- struct cyclades_port *info = container_of(port, struct cyclades_port,
- port);
- struct cyclades_card *cinfo = info->card;
- unsigned long flags;
-
- spin_lock_irqsave(&cinfo->card_lock, flags);
- cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
- raise ? 0 : TIOCM_RTS | TIOCM_DTR);
- spin_unlock_irqrestore(&cinfo->card_lock, flags);
-}
-
-static int cyz_carrier_raised(struct tty_port *port)
-{
- struct cyclades_port *info = container_of(port, struct cyclades_port,
- port);
-
- return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD;
-}
-
-static void cyz_dtr_rts(struct tty_port *port, int raise)
-{
- struct cyclades_port *info = container_of(port, struct cyclades_port,
- port);
- struct cyclades_card *cinfo = info->card;
- struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
- int ret, channel = info->line - cinfo->first_line;
- u32 rs;
-
- rs = readl(&ch_ctrl->rs_control);
- if (raise)
- rs |= C_RS_RTS | C_RS_DTR;
- else
- rs &= ~(C_RS_RTS | C_RS_DTR);
- cy_writel(&ch_ctrl->rs_control, rs);
- ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L);
- if (ret != 0)
- printk(KERN_ERR "%s: retval on ttyC%d was %x\n",
- __func__, info->line, ret);
-#ifdef CY_DEBUG_DTR
- printk(KERN_DEBUG "%s: raising Z DTR\n", __func__);
-#endif
-}
-
-static const struct tty_port_operations cyy_port_ops = {
- .carrier_raised = cyy_carrier_raised,
- .dtr_rts = cyy_dtr_rts,
- .shutdown = cy_do_close,
-};
-
-static const struct tty_port_operations cyz_port_ops = {
- .carrier_raised = cyz_carrier_raised,
- .dtr_rts = cyz_dtr_rts,
- .shutdown = cy_do_close,
-};
-
-/*
- * ---------------------------------------------------------------------
- * cy_init() and friends
- *
- * cy_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-static int cy_init_card(struct cyclades_card *cinfo)
-{
- struct cyclades_port *info;
- unsigned int channel, port;
-
- spin_lock_init(&cinfo->card_lock);
- cinfo->intr_enabled = 0;
-
- cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
- GFP_KERNEL);
- if (cinfo->ports == NULL) {
- printk(KERN_ERR "Cyclades: cannot allocate ports\n");
- return -ENOMEM;
- }
-
- for (channel = 0, port = cinfo->first_line; channel < cinfo->nports;
- channel++, port++) {
- info = &cinfo->ports[channel];
- tty_port_init(&info->port);
- info->magic = CYCLADES_MAGIC;
- info->card = cinfo;
- info->line = port;
-
- info->port.closing_wait = CLOSING_WAIT_DELAY;
- info->port.close_delay = 5 * HZ / 10;
- init_completion(&info->shutdown_wait);
-
- if (cy_is_Z(cinfo)) {
- struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
- struct ZFW_CTRL *zfw_ctrl;
-
- info->port.ops = &cyz_port_ops;
- info->type = PORT_STARTECH;
-
- zfw_ctrl = cinfo->base_addr +
- (readl(&firm_id->zfwctrl_addr) & 0xfffff);
- info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel];
- info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
-
- if (cinfo->hw_ver == ZO_V1)
- info->xmit_fifo_size = CYZ_FIFO_SIZE;
- else
- info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
-#ifdef CONFIG_CYZ_INTR
- timer_setup(&info->rx_full_timer, cyz_rx_restart, 0);
-#endif
- } else {
- unsigned short chip_number;
- int index = cinfo->bus_index;
-
- info->port.ops = &cyy_port_ops;
- info->type = PORT_CIRRUS;
- info->xmit_fifo_size = CyMAX_CHAR_FIFO;
- info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
- info->cor2 = CyETC;
- info->cor3 = 0x08; /* _very_ small rcv threshold */
-
- chip_number = channel / CyPORTS_PER_CHIP;
- info->u.cyy.base_addr = cinfo->base_addr +
- (cy_chip_offset[chip_number] << index);
- info->chip_rev = cyy_readb(info, CyGFRCR);
-
- if (info->chip_rev >= CD1400_REV_J) {
- /* It is a CD1400 rev. J or later */
- info->tbpr = baud_bpr_60[13]; /* Tx BPR */
- info->tco = baud_co_60[13]; /* Tx CO */
- info->rbpr = baud_bpr_60[13]; /* Rx BPR */
- info->rco = baud_co_60[13]; /* Rx CO */
- info->rtsdtr_inv = 1;
- } else {
- info->tbpr = baud_bpr_25[13]; /* Tx BPR */
- info->tco = baud_co_25[13]; /* Tx CO */
- info->rbpr = baud_bpr_25[13]; /* Rx BPR */
- info->rco = baud_co_25[13]; /* Rx CO */
- info->rtsdtr_inv = 0;
- }
- info->read_status_mask = CyTIMEOUT | CySPECHAR |
- CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
- }
-
- }
-
-#ifndef CONFIG_CYZ_INTR
- if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
- mod_timer(&cyz_timerlist, jiffies + 1);
-#ifdef CY_PCI_DEBUG
- printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
-#endif
- }
-#endif
- return 0;
-}
-
-/* initialize chips on Cyclom-Y card -- return number of valid
- chips (which is number of ports/4) */
-static unsigned short cyy_init_card(void __iomem *true_base_addr,
- int index)
-{
- unsigned int chip_number;
- void __iomem *base_addr;
-
- cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
- /* Cy_HwReset is 0x1400 */
- cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
- /* Cy_ClrIntr is 0x1800 */
- udelay(500L);
-
- for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
- chip_number++) {
- base_addr =
- true_base_addr + (cy_chip_offset[chip_number] << index);
- mdelay(1);
- if (readb(base_addr + (CyCCR << index)) != 0x00) {
- /*************
- printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
- chip_number, (unsigned long)base_addr);
- *************/
- return chip_number;
- }
-
- cy_writeb(base_addr + (CyGFRCR << index), 0);
- udelay(10L);
-
- /* The Cyclom-16Y does not decode address bit 9 and therefore
- cannot distinguish between references to chip 0 and a non-
- existent chip 4. If the preceding clearing of the supposed
- chip 4 GFRCR register appears at chip 0, there is no chip 4
- and this must be a Cyclom-16Y, not a Cyclom-32Ye.
- */
- if (chip_number == 4 && readb(true_base_addr +
- (cy_chip_offset[0] << index) +
- (CyGFRCR << index)) == 0) {
- return chip_number;
- }
-
- cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
- mdelay(1);
-
- if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
- /*
- printk(" chip #%d at %#6lx is not responding ",
- chip_number, (unsigned long)base_addr);
- printk("(GFRCR stayed 0)\n",
- */
- return chip_number;
- }
- if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
- 0x40) {
- /*
- printk(" chip #%d at %#6lx is not valid (GFRCR == "
- "%#2x)\n",
- chip_number, (unsigned long)base_addr,
- base_addr[CyGFRCR<<index]);
- */
- return chip_number;
- }
- cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
- if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
- /* It is a CD1400 rev. J or later */
- /* Impossible to reach 5ms with this chip.
- Changed to 2ms instead (f = 500 Hz). */
- cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
- } else {
- /* f = 200 Hz */
- cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
- }
-
- /*
- printk(" chip #%d at %#6lx is rev 0x%2x\n",
- chip_number, (unsigned long)base_addr,
- readb(base_addr+(CyGFRCR<<index)));
- */
- }
- return chip_number;
-} /* cyy_init_card */
-
-/*
- * ---------------------------------------------------------------------
- * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
- * sets global variables and return the number of ISA boards found.
- * ---------------------------------------------------------------------
- */
-static int __init cy_detect_isa(void)
-{
-#ifdef CONFIG_ISA
- struct cyclades_card *card;
- unsigned short cy_isa_irq, nboard;
- void __iomem *cy_isa_address;
- unsigned short i, j, k, cy_isa_nchan;
- int isparam = 0;
-
- nboard = 0;
-
- /* Check for module parameters */
- for (i = 0; i < NR_CARDS; i++) {
- if (maddr[i] || i) {
- isparam = 1;
- cy_isa_addresses[i] = maddr[i];
- }
- if (!maddr[i])
- break;
- }
-
- /* scan the address table probing for Cyclom-Y/ISA boards */
- for (i = 0; i < NR_ISA_ADDRS; i++) {
- unsigned int isa_address = cy_isa_addresses[i];
- if (isa_address == 0x0000)
- return nboard;
-
- /* probe for CD1400... */
- cy_isa_address = ioremap(isa_address, CyISA_Ywin);
- if (cy_isa_address == NULL) {
- printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
- "address\n");
- continue;
- }
- cy_isa_nchan = CyPORTS_PER_CHIP *
- cyy_init_card(cy_isa_address, 0);
- if (cy_isa_nchan == 0) {
- iounmap(cy_isa_address);
- continue;
- }
-
- if (isparam && i < NR_CARDS && irq[i])
- cy_isa_irq = irq[i];
- else
- /* find out the board's irq by probing */
- cy_isa_irq = detect_isa_irq(cy_isa_address);
- if (cy_isa_irq == 0) {
- printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
- "IRQ could not be detected.\n",
- (unsigned long)cy_isa_address);
- iounmap(cy_isa_address);
- continue;
- }
-
- if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
- printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
- "more channels are available. Change NR_PORTS "
- "in cyclades.c and recompile kernel.\n",
- (unsigned long)cy_isa_address);
- iounmap(cy_isa_address);
- return nboard;
- }
- /* fill the next cy_card structure available */
- for (j = 0; j < NR_CARDS; j++) {
- card = &cy_card[j];
- if (card->base_addr == NULL)
- break;
- }
- if (j == NR_CARDS) { /* no more cy_cards available */
- printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
- "more cards can be used. Change NR_CARDS in "
- "cyclades.c and recompile kernel.\n",
- (unsigned long)cy_isa_address);
- iounmap(cy_isa_address);
- return nboard;
- }
-
- /* allocate IRQ */
- if (request_irq(cy_isa_irq, cyy_interrupt,
- 0, "Cyclom-Y", card)) {
- printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
- "could not allocate IRQ#%d.\n",
- (unsigned long)cy_isa_address, cy_isa_irq);
- iounmap(cy_isa_address);
- return nboard;
- }
-
- /* set cy_card */
- card->base_addr = cy_isa_address;
- card->ctl_addr.p9050 = NULL;
- card->irq = (int)cy_isa_irq;
- card->bus_index = 0;
- card->first_line = cy_next_channel;
- card->num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
- card->nports = cy_isa_nchan;
- if (cy_init_card(card)) {
- card->base_addr = NULL;
- free_irq(cy_isa_irq, card);
- iounmap(cy_isa_address);
- continue;
- }
- nboard++;
-
- printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
- "%d channels starting from port %d\n",
- j + 1, (unsigned long)cy_isa_address,
- (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
- cy_isa_irq, cy_isa_nchan, cy_next_channel);
-
- for (k = 0, j = cy_next_channel;
- j < cy_next_channel + cy_isa_nchan; j++, k++)
- tty_port_register_device(&card->ports[k].port,
- cy_serial_driver, j, NULL);
- cy_next_channel += cy_isa_nchan;
- }
- return nboard;
-#else
- return 0;
-#endif /* CONFIG_ISA */
-} /* cy_detect_isa */
-
-#ifdef CONFIG_PCI
-static inline int cyc_isfwstr(const char *str, unsigned int size)
-{
- unsigned int a;
-
- for (a = 0; a < size && *str; a++, str++)
- if (*str & 0x80)
- return -EINVAL;
-
- for (; a < size; a++, str++)
- if (*str)
- return -EINVAL;
-
- return 0;
-}
-
-static inline void cyz_fpga_copy(void __iomem *fpga, const u8 *data,
- unsigned int size)
-{
- for (; size > 0; size--) {
- cy_writel(fpga, *data++);
- udelay(10);
- }
-}
-
-static void plx_init(struct pci_dev *pdev, int irq,
- struct RUNTIME_9060 __iomem *addr)
-{
- /* Reset PLX */
- cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
- udelay(100L);
- cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
-
- /* Reload Config. Registers from EEPROM */
- cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
- udelay(100L);
- cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
-
- /* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
- * the IRQ is lost and, thus, we have to re-write it to the PCI config.
- * registers. This will remain here until we find a permanent fix.
- */
- pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
-}
-
-static int __cyz_load_fw(const struct firmware *fw,
- const char *name, const u32 mailbox, void __iomem *base,
- void __iomem *fpga)
-{
- const void *ptr = fw->data;
- const struct zfile_header *h = ptr;
- const struct zfile_config *c, *cs;
- const struct zfile_block *b, *bs;
- unsigned int a, tmp, len = fw->size;
-#define BAD_FW KERN_ERR "Bad firmware: "
- if (len < sizeof(*h)) {
- printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
- return -EINVAL;
- }
-
- cs = ptr + h->config_offset;
- bs = ptr + h->block_offset;
-
- if ((void *)(cs + h->n_config) > ptr + len ||
- (void *)(bs + h->n_blocks) > ptr + len) {
- printk(BAD_FW "too short");
- return -EINVAL;
- }
-
- if (cyc_isfwstr(h->name, sizeof(h->name)) ||
- cyc_isfwstr(h->date, sizeof(h->date))) {
- printk(BAD_FW "bad formatted header string\n");
- return -EINVAL;
- }
-
- if (strncmp(name, h->name, sizeof(h->name))) {
- printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
- return -EINVAL;
- }
-
- tmp = 0;
- for (c = cs; c < cs + h->n_config; c++) {
- for (a = 0; a < c->n_blocks; a++)
- if (c->block_list[a] > h->n_blocks) {
- printk(BAD_FW "bad block ref number in cfgs\n");
- return -EINVAL;
- }
- if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
- tmp++;
- }
- if (!tmp) {
- printk(BAD_FW "nothing appropriate\n");
- return -EINVAL;
- }
-
- for (b = bs; b < bs + h->n_blocks; b++)
- if (b->file_offset + b->size > len) {
- printk(BAD_FW "bad block data offset\n");
- return -EINVAL;
- }
-
- /* everything is OK, let's seek'n'load it */
- for (c = cs; c < cs + h->n_config; c++)
- if (c->mailbox == mailbox && c->function == 0)
- break;
-
- for (a = 0; a < c->n_blocks; a++) {
- b = &bs[c->block_list[a]];
- if (b->type == ZBLOCK_FPGA) {
- if (fpga != NULL)
- cyz_fpga_copy(fpga, ptr + b->file_offset,
- b->size);
- } else {
- if (base != NULL)
- memcpy_toio(base + b->ram_offset,
- ptr + b->file_offset, b->size);
- }
- }
-#undef BAD_FW
- return 0;
-}
-
-static int cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
- struct RUNTIME_9060 __iomem *ctl_addr, int irq)
-{
- const struct firmware *fw;
- struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
- struct CUSTOM_REG __iomem *cust = base_addr;
- struct ZFW_CTRL __iomem *pt_zfwctrl;
- void __iomem *tmp;
- u32 mailbox, status, nchan;
- unsigned int i;
- int retval;
-
- retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
- if (retval) {
- dev_err(&pdev->dev, "can't get firmware\n");
- goto err;
- }
-
- /* Check whether the firmware is already loaded and running. If
- positive, skip this board */
- if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
- u32 cntval = readl(base_addr + 0x190);
-
- udelay(100);
- if (cntval != readl(base_addr + 0x190)) {
- /* FW counter is working, FW is running */
- dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
- "Skipping board.\n");
- retval = 0;
- goto err_rel;
- }
- }
-
- /* start boot */
- cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
- ~0x00030800UL);
-
- mailbox = readl(&ctl_addr->mail_box_0);
-
- if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
- /* stops CPU and set window to beginning of RAM */
- cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
- cy_writel(&cust->cpu_stop, 0);
- cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
- udelay(100);
- }
-
- plx_init(pdev, irq, ctl_addr);
-
- if (mailbox != 0) {
- /* load FPGA */
- retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
- base_addr);
- if (retval)
- goto err_rel;
- if (!__cyz_fpga_loaded(ctl_addr)) {
- dev_err(&pdev->dev, "fw upload successful, but fw is "
- "not loaded\n");
- goto err_rel;
- }
- }
-
- /* stops CPU and set window to beginning of RAM */
- cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
- cy_writel(&cust->cpu_stop, 0);
- cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
- udelay(100);
-
- /* clear memory */
- for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
- cy_writeb(tmp, 255);
- if (mailbox != 0) {
- /* set window to last 512K of RAM */
- cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
- for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
- cy_writeb(tmp, 255);
- /* set window to beginning of RAM */
- cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
- }
-
- retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
- release_firmware(fw);
- if (retval)
- goto err;
-
- /* finish boot and start boards */
- cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
- cy_writel(&cust->cpu_start, 0);
- cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
- i = 0;
- while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
- msleep(100);
- if (status != ZFIRM_ID) {
- if (status == ZFIRM_HLT) {
- dev_err(&pdev->dev, "you need an external power supply "
- "for this number of ports. Firmware halted and "
- "board reset.\n");
- retval = -EIO;
- goto err;
- }
- dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
- "some more time\n", status);
- while ((status = readl(&fid->signature)) != ZFIRM_ID &&
- i++ < 200)
- msleep(100);
- if (status != ZFIRM_ID) {
- dev_err(&pdev->dev, "Board not started in 20 seconds! "
- "Giving up. (fid->signature = 0x%x)\n",
- status);
- dev_info(&pdev->dev, "*** Warning ***: if you are "
- "upgrading the FW, please power cycle the "
- "system before loading the new FW to the "
- "Cyclades-Z.\n");
-
- if (__cyz_fpga_loaded(ctl_addr))
- plx_init(pdev, irq, ctl_addr);
-
- retval = -EIO;
- goto err;
- }
- dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
- i / 10);
- }
- pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
-
- dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
- base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
- base_addr + readl(&fid->zfwctrl_addr));
-
- nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
- dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
- readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
-
- if (nchan == 0) {
- dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
- "check the connection between the Z host card and the "
- "serial expanders.\n");
-
- if (__cyz_fpga_loaded(ctl_addr))
- plx_init(pdev, irq, ctl_addr);
-
- dev_info(&pdev->dev, "Null number of ports detected. Board "
- "reset.\n");
- retval = 0;
- goto err;
- }
-
- cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
- cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
-
- /*
- Early firmware failed to start looking for commands.
- This enables firmware interrupts for those commands.
- */
- cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
- (1 << 17));
- cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
- 0x00030800UL);
-
- return nchan;
-err_rel:
- release_firmware(fw);
-err:
- return retval;
-}
-
-static int cy_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct cyclades_card *card;
- void __iomem *addr0 = NULL, *addr2 = NULL;
- char *card_name = NULL;
- u32 mailbox;
- unsigned int device_id, nchan = 0, card_no, i, j;
- unsigned char plx_ver;
- int retval, irq;
-
- retval = pci_enable_device(pdev);
- if (retval) {
- dev_err(&pdev->dev, "cannot enable device\n");
- goto err;
- }
-
- /* read PCI configuration area */
- irq = pdev->irq;
- device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
-
-#if defined(__alpha__)
- if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
- dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
- "addresses on Alpha systems.\n");
- retval = -EIO;
- goto err_dis;
- }
-#endif
- if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
- dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
- "addresses\n");
- retval = -EIO;
- goto err_dis;
- }
-
- if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
- dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
- "it...\n");
- pdev->resource[2].flags &= ~IORESOURCE_IO;
- }
-
- retval = pci_request_regions(pdev, "cyclades");
- if (retval) {
- dev_err(&pdev->dev, "failed to reserve resources\n");
- goto err_dis;
- }
-
- retval = -EIO;
- if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
- device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
- card_name = "Cyclom-Y";
-
- addr0 = ioremap(pci_resource_start(pdev, 0),
- CyPCI_Yctl);
- if (addr0 == NULL) {
- dev_err(&pdev->dev, "can't remap ctl region\n");
- goto err_reg;
- }
- addr2 = ioremap(pci_resource_start(pdev, 2),
- CyPCI_Ywin);
- if (addr2 == NULL) {
- dev_err(&pdev->dev, "can't remap base region\n");
- goto err_unmap;
- }
-
- nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
- if (nchan == 0) {
- dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
- "Serial-Modules\n");
- goto err_unmap;
- }
- } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
- struct RUNTIME_9060 __iomem *ctl_addr;
-
- ctl_addr = addr0 = ioremap(pci_resource_start(pdev, 0),
- CyPCI_Zctl);
- if (addr0 == NULL) {
- dev_err(&pdev->dev, "can't remap ctl region\n");
- goto err_reg;
- }
-
- /* Disable interrupts on the PLX before resetting it */
- cy_writew(&ctl_addr->intr_ctrl_stat,
- readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
-
- plx_init(pdev, irq, addr0);
-
- mailbox = readl(&ctl_addr->mail_box_0);
-
- addr2 = ioremap(pci_resource_start(pdev, 2),
- mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
- if (addr2 == NULL) {
- dev_err(&pdev->dev, "can't remap base region\n");
- goto err_unmap;
- }
-
- if (mailbox == ZE_V1) {
- card_name = "Cyclades-Ze";
- } else {
- card_name = "Cyclades-8Zo";
-#ifdef CY_PCI_DEBUG
- if (mailbox == ZO_V1) {
- cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
- dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
- "id %lx, ver %lx\n", (ulong)(0xff &
- readl(&((struct CUSTOM_REG *)addr2)->
- fpga_id)), (ulong)(0xff &
- readl(&((struct CUSTOM_REG *)addr2)->
- fpga_version)));
- cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
- } else {
- dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
- "Cyclades-Z board. FPGA not loaded\n");
- }
-#endif
- /* The following clears the firmware id word. This
- ensures that the driver will not attempt to talk to
- the board until it has been properly initialized.
- */
- if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
- cy_writel(addr2 + ID_ADDRESS, 0L);
- }
-
- retval = cyz_load_fw(pdev, addr2, addr0, irq);
- if (retval <= 0)
- goto err_unmap;
- nchan = retval;
- }
-
- if ((cy_next_channel + nchan) > NR_PORTS) {
- dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
- "channels are available. Change NR_PORTS in "
- "cyclades.c and recompile kernel.\n");
- goto err_unmap;
- }
- /* fill the next cy_card structure available */
- for (card_no = 0; card_no < NR_CARDS; card_no++) {
- card = &cy_card[card_no];
- if (card->base_addr == NULL)
- break;
- }
- if (card_no == NR_CARDS) { /* no more cy_cards available */
- dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
- "more cards can be used. Change NR_CARDS in "
- "cyclades.c and recompile kernel.\n");
- goto err_unmap;
- }
-
- if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
- device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
- /* allocate IRQ */
- retval = request_irq(irq, cyy_interrupt,
- IRQF_SHARED, "Cyclom-Y", card);
- if (retval) {
- dev_err(&pdev->dev, "could not allocate IRQ\n");
- goto err_unmap;
- }
- card->num_chips = nchan / CyPORTS_PER_CHIP;
- } else {
- struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
- struct ZFW_CTRL __iomem *zfw_ctrl;
-
- zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-
- card->hw_ver = mailbox;
- card->num_chips = (unsigned int)-1;
- card->board_ctrl = &zfw_ctrl->board_ctrl;
-#ifdef CONFIG_CYZ_INTR
- /* allocate IRQ only if board has an IRQ */
- if (irq != 0 && irq != 255) {
- retval = request_irq(irq, cyz_interrupt,
- IRQF_SHARED, "Cyclades-Z", card);
- if (retval) {
- dev_err(&pdev->dev, "could not allocate IRQ\n");
- goto err_unmap;
- }
- }
-#endif /* CONFIG_CYZ_INTR */
- }
-
- /* set cy_card */
- card->base_addr = addr2;
- card->ctl_addr.p9050 = addr0;
- card->irq = irq;
- card->bus_index = 1;
- card->first_line = cy_next_channel;
- card->nports = nchan;
- retval = cy_init_card(card);
- if (retval)
- goto err_null;
-
- pci_set_drvdata(pdev, card);
-
- if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
- device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
- /* enable interrupts in the PCI interface */
- plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
- switch (plx_ver) {
- case PLX_9050:
- cy_writeb(addr0 + 0x4c, 0x43);
- break;
-
- case PLX_9060:
- case PLX_9080:
- default: /* Old boards, use PLX_9060 */
- {
- struct RUNTIME_9060 __iomem *ctl_addr = addr0;
- plx_init(pdev, irq, ctl_addr);
- cy_writew(&ctl_addr->intr_ctrl_stat,
- readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
- break;
- }
- }
- }
-
- dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
- "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
- for (j = 0, i = cy_next_channel; i < cy_next_channel + nchan; i++, j++)
- tty_port_register_device(&card->ports[j].port,
- cy_serial_driver, i, &pdev->dev);
- cy_next_channel += nchan;
-
- return 0;
-err_null:
- card->base_addr = NULL;
- free_irq(irq, card);
-err_unmap:
- iounmap(addr0);
- if (addr2)
- iounmap(addr2);
-err_reg:
- pci_release_regions(pdev);
-err_dis:
- pci_disable_device(pdev);
-err:
- return retval;
-}
-
-static void cy_pci_remove(struct pci_dev *pdev)
-{
- struct cyclades_card *cinfo = pci_get_drvdata(pdev);
- unsigned int i, channel;
-
- /* non-Z with old PLX */
- if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
- PLX_9050)
- cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
- else
-#ifndef CONFIG_CYZ_INTR
- if (!cy_is_Z(cinfo))
-#endif
- cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
- readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
- ~0x0900);
-
- iounmap(cinfo->base_addr);
- if (cinfo->ctl_addr.p9050)
- iounmap(cinfo->ctl_addr.p9050);
- if (cinfo->irq
-#ifndef CONFIG_CYZ_INTR
- && !cy_is_Z(cinfo)
-#endif /* CONFIG_CYZ_INTR */
- )
- free_irq(cinfo->irq, cinfo);
- pci_release_regions(pdev);
-
- cinfo->base_addr = NULL;
- for (channel = 0, i = cinfo->first_line; i < cinfo->first_line +
- cinfo->nports; i++, channel++) {
- tty_unregister_device(cy_serial_driver, i);
- tty_port_destroy(&cinfo->ports[channel].port);
- }
- cinfo->nports = 0;
- kfree(cinfo->ports);
-}
-
-static struct pci_driver cy_pci_driver = {
- .name = "cyclades",
- .id_table = cy_pci_dev_id,
- .probe = cy_pci_probe,
- .remove = cy_pci_remove
-};
-#endif
-
-static int cyclades_proc_show(struct seq_file *m, void *v)
-{
- struct cyclades_port *info;
- unsigned int i, j;
- __u32 cur_jifs = jiffies;
-
- seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn "
- "IdleIn Overruns Ldisc\n");
-
- /* Output one line for each known port */
- for (i = 0; i < NR_CARDS; i++)
- for (j = 0; j < cy_card[i].nports; j++) {
- info = &cy_card[i].ports[j];
-
- if (info->port.count) {
- /* XXX is the ldisc num worth this? */
- struct tty_struct *tty;
- struct tty_ldisc *ld;
- int num = 0;
- tty = tty_port_tty_get(&info->port);
- if (tty) {
- ld = tty_ldisc_ref(tty);
- if (ld) {
- num = ld->ops->num;
- tty_ldisc_deref(ld);
- }
- tty_kref_put(tty);
- }
- seq_printf(m, "%3d %8lu %10lu %8lu "
- "%10lu %8lu %9lu %6d\n", info->line,
- (cur_jifs - info->idle_stats.in_use) /
- HZ, info->idle_stats.xmit_bytes,
- (cur_jifs - info->idle_stats.xmit_idle)/
- HZ, info->idle_stats.recv_bytes,
- (cur_jifs - info->idle_stats.recv_idle)/
- HZ, info->idle_stats.overruns,
- num);
- } else
- seq_printf(m, "%3d %8lu %10lu %8lu "
- "%10lu %8lu %9lu %6ld\n",
- info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
- }
- return 0;
-}
-
-/* The serial driver boot-time initialization code!
- Hardware I/O ports are mapped to character special devices on a
- first found, first allocated manner. That is, this code searches
- for Cyclom cards in the system. As each is found, it is probed
- to discover how many chips (and thus how many ports) are present.
- These ports are mapped to the tty ports 32 and upward in monotonic
- fashion. If an 8-port card is replaced with a 16-port card, the
- port mapping on a following card will shift.
-
- This approach is different from what is used in the other serial
- device driver because the Cyclom is more properly a multiplexer,
- not just an aggregation of serial ports on one card.
-
- If there are more cards with more ports than have been
- statically allocated above, a warning is printed and the
- extra ports are ignored.
- */
-
-static const struct tty_operations cy_ops = {
- .open = cy_open,
- .close = cy_close,
- .write = cy_write,
- .put_char = cy_put_char,
- .flush_chars = cy_flush_chars,
- .write_room = cy_write_room,
- .chars_in_buffer = cy_chars_in_buffer,
- .flush_buffer = cy_flush_buffer,
- .ioctl = cy_ioctl,
- .throttle = cy_throttle,
- .unthrottle = cy_unthrottle,
- .set_termios = cy_set_termios,
- .stop = cy_stop,
- .start = cy_start,
- .hangup = cy_hangup,
- .break_ctl = cy_break,
- .wait_until_sent = cy_wait_until_sent,
- .tiocmget = cy_tiocmget,
- .tiocmset = cy_tiocmset,
- .get_icount = cy_get_icount,
- .set_serial = cy_set_serial_info,
- .get_serial = cy_get_serial_info,
- .proc_show = cyclades_proc_show,
-};
-
-static int __init cy_init(void)
-{
- unsigned int nboards;
- int retval = -ENOMEM;
-
- cy_serial_driver = alloc_tty_driver(NR_PORTS);
- if (!cy_serial_driver)
- goto err;
-
- printk(KERN_INFO "Cyclades driver " CY_VERSION "\n");
-
- /* Initialize the tty_driver structure */
-
- cy_serial_driver->driver_name = "cyclades";
- cy_serial_driver->name = "ttyC";
- cy_serial_driver->major = CYCLADES_MAJOR;
- cy_serial_driver->minor_start = 0;
- cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
- cy_serial_driver->init_termios = tty_std_termios;
- cy_serial_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_set_operations(cy_serial_driver, &cy_ops);
-
- retval = tty_register_driver(cy_serial_driver);
- if (retval) {
- printk(KERN_ERR "Couldn't register Cyclades serial driver\n");
- goto err_frtty;
- }
-
- /* the code below is responsible to find the boards. Each different
- type of board has its own detection routine. If a board is found,
- the next cy_card structure available is set by the detection
- routine. These functions are responsible for checking the
- availability of cy_card and cy_port data structures and updating
- the cy_next_channel. */
-
- /* look for isa boards */
- nboards = cy_detect_isa();
-
-#ifdef CONFIG_PCI
- /* look for pci boards */
- retval = pci_register_driver(&cy_pci_driver);
- if (retval && !nboards) {
- tty_unregister_driver(cy_serial_driver);
- goto err_frtty;
- }
-#endif
-
- return 0;
-err_frtty:
- put_tty_driver(cy_serial_driver);
-err:
- return retval;
-} /* cy_init */
-
-static void __exit cy_cleanup_module(void)
-{
- struct cyclades_card *card;
- unsigned int i, e1;
-
-#ifndef CONFIG_CYZ_INTR
- del_timer_sync(&cyz_timerlist);
-#endif /* CONFIG_CYZ_INTR */
-
- e1 = tty_unregister_driver(cy_serial_driver);
- if (e1)
- printk(KERN_ERR "failed to unregister Cyclades serial "
- "driver(%d)\n", e1);
-
-#ifdef CONFIG_PCI
- pci_unregister_driver(&cy_pci_driver);
-#endif
-
- for (i = 0; i < NR_CARDS; i++) {
- card = &cy_card[i];
- if (card->base_addr) {
- /* clear interrupt */
- cy_writeb(card->base_addr + Cy_ClrIntr, 0);
- iounmap(card->base_addr);
- if (card->ctl_addr.p9050)
- iounmap(card->ctl_addr.p9050);
- if (card->irq
-#ifndef CONFIG_CYZ_INTR
- && !cy_is_Z(card)
-#endif /* CONFIG_CYZ_INTR */
- )
- free_irq(card->irq, card);
- for (e1 = card->first_line; e1 < card->first_line +
- card->nports; e1++)
- tty_unregister_device(cy_serial_driver, e1);
- kfree(card->ports);
- }
- }
-
- put_tty_driver(cy_serial_driver);
-} /* cy_cleanup_module */
-
-module_init(cy_init);
-module_exit(cy_cleanup_module);
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CY_VERSION);
-MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
-MODULE_FIRMWARE("cyzfirm.bin");
diff --git a/drivers/tty/hvc/hvc_udbg.c b/drivers/tty/hvc/hvc_udbg.c
index a4c9913f76a0..ff0dcc56413c 100644
--- a/drivers/tty/hvc/hvc_udbg.c
+++ b/drivers/tty/hvc/hvc_udbg.c
@@ -17,7 +17,7 @@
#include "hvc_console.h"
-struct hvc_struct *hvc_udbg_dev;
+static struct hvc_struct *hvc_udbg_dev;
static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count)
{
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 9afa1dcef2c2..197988c55e0c 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -290,35 +290,11 @@ static LIST_HEAD(hvcs_structs);
static DEFINE_SPINLOCK(hvcs_structs_lock);
static DEFINE_MUTEX(hvcs_init_mutex);
-static void hvcs_unthrottle(struct tty_struct *tty);
-static void hvcs_throttle(struct tty_struct *tty);
-static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance);
-
-static int hvcs_write(struct tty_struct *tty,
- const unsigned char *buf, int count);
-static int hvcs_write_room(struct tty_struct *tty);
-static int hvcs_chars_in_buffer(struct tty_struct *tty);
-
-static int hvcs_has_pi(struct hvcs_struct *hvcsd);
-static void hvcs_set_pi(struct hvcs_partner_info *pi,
- struct hvcs_struct *hvcsd);
static int hvcs_get_pi(struct hvcs_struct *hvcsd);
static int hvcs_rescan_devices_list(void);
-static int hvcs_partner_connect(struct hvcs_struct *hvcsd);
static void hvcs_partner_free(struct hvcs_struct *hvcsd);
-static int hvcs_enable_device(struct hvcs_struct *hvcsd,
- uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
-
-static int hvcs_open(struct tty_struct *tty, struct file *filp);
-static void hvcs_close(struct tty_struct *tty, struct file *filp);
-static void hvcs_hangup(struct tty_struct * tty);
-
-static int hvcs_probe(struct vio_dev *dev,
- const struct vio_device_id *id);
-static int __init hvcs_module_init(void);
-static void __exit hvcs_module_exit(void);
static int hvcs_initialize(void);
#define HVCS_SCHED_READ 0x00000001
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
index 6dacbc5e286c..99bb2f149ff5 100644
--- a/drivers/tty/ipwireless/tty.c
+++ b/drivers/tty/ipwireless/tty.c
@@ -235,10 +235,10 @@ static int ipw_write_room(struct tty_struct *linux_tty)
/* FIXME: Exactly how is the tty object locked here .. */
if (!tty)
- return -ENODEV;
+ return 0;
if (!tty->port.count)
- return -EINVAL;
+ return 0;
room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
if (room < 0)
@@ -596,13 +596,8 @@ int ipwireless_tty_init(void)
void ipwireless_tty_release(void)
{
- int ret;
-
- ret = tty_unregister_driver(ipw_tty_driver);
+ tty_unregister_driver(ipw_tty_driver);
put_tty_driver(ipw_tty_driver);
- if (ret != 0)
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": tty_unregister_driver failed with code %d\n", ret);
}
int ipwireless_tty_is_modem(struct ipw_tty *tty)
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
deleted file mode 100644
index 3b2f9fb01aa0..000000000000
--- a/drivers/tty/isicom.c
+++ /dev/null
@@ -1,1699 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Original driver code supplied by Multi-Tech
- *
- * Changes
- * 1/9/98 alan@lxorguk.ukuu.org.uk
- * Merge to 2.0.x kernel tree
- * Obtain and use official major/minors
- * Loader switched to a misc device
- * (fixed range check bug as a side effect)
- * Printk clean up
- * 9/12/98 alan@lxorguk.ukuu.org.uk
- * Rough port to 2.1.x
- *
- * 10/6/99 sameer Merged the ISA and PCI drivers to
- * a new unified driver.
- *
- * 3/9/99 sameer Added support for ISI4616 cards.
- *
- * 16/9/99 sameer We do not force RTS low anymore.
- * This is to prevent the firmware
- * from getting confused.
- *
- * 26/10/99 sameer Cosmetic changes:The driver now
- * dumps the Port Count information
- * along with I/O address and IRQ.
- *
- * 13/12/99 sameer Fixed the problem with IRQ sharing.
- *
- * 10/5/00 sameer Fixed isicom_shutdown_board()
- * to not lower DTR on all the ports
- * when the last port on the card is
- * closed.
- *
- * 10/5/00 sameer Signal mask setup command added
- * to isicom_setup_port and
- * isicom_shutdown_port.
- *
- * 24/5/00 sameer The driver is now SMP aware.
- *
- *
- * 27/11/00 Vinayak P Risbud Fixed the Driver Crash Problem
- *
- *
- * 03/01/01 anil .s Added support for resetting the
- * internal modems on ISI cards.
- *
- * 08/02/01 anil .s Upgraded the driver for kernel
- * 2.4.x
- *
- * 11/04/01 Kevin Fixed firmware load problem with
- * ISIHP-4X card
- *
- * 30/04/01 anil .s Fixed the remote login through
- * ISI port problem. Now the link
- * does not go down before password
- * prompt.
- *
- * 03/05/01 anil .s Fixed the problem with IRQ sharing
- * among ISI-PCI cards.
- *
- * 03/05/01 anil .s Added support to display the version
- * info during insmod as well as module
- * listing by lsmod.
- *
- * 10/05/01 anil .s Done the modifications to the source
- * file and Install script so that the
- * same installation can be used for
- * 2.2.x and 2.4.x kernel.
- *
- * 06/06/01 anil .s Now we drop both dtr and rts during
- * shutdown_port as well as raise them
- * during isicom_config_port.
- *
- * 09/06/01 acme@conectiva.com.br use capable, not suser, do
- * restore_flags on failure in
- * isicom_send_break, verify put_user
- * result
- *
- * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps
- * Baud index extended to 21
- *
- * 20/03/03 ranjeeth Made to work for Linux Advanced server.
- * Taken care of license warning.
- *
- * 10/12/03 Ravindra Made to work for Fedora Core 1 of
- * Red Hat Distribution
- *
- * 06/01/05 Alan Cox Merged the ISI and base kernel strands
- * into a single 2.6 driver
- *
- * ***********************************************************
- *
- * To use this driver you also need the support package. You
- * can find this in RPM format on
- * ftp://ftp.linux.org.uk/pub/linux/alan
- *
- * You can find the original tools for this direct from Multitech
- * ftp://ftp.multitech.com/ISI-Cards/
- *
- * Having installed the cards the module options (/etc/modprobe.d/)
- *
- * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4
- *
- * Omit those entries for boards you don't have installed.
- *
- * TODO
- * Merge testing
- * 64-bit verification
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/termios.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#include <linux/pci.h>
-
-#include <linux/isicom.h>
-
-#define InterruptTheCard(base) outw(0, (base) + 0xc)
-#define ClearInterrupt(base) inw((base) + 0x0a)
-
-#ifdef DEBUG
-#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
-#else
-#define isicom_paranoia_check(a, b, c) 0
-#endif
-
-static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
-static void isicom_remove(struct pci_dev *);
-
-static const struct pci_device_id isicom_pci_tbl[] = {
- { PCI_DEVICE(VENDOR_ID, 0x2028) },
- { PCI_DEVICE(VENDOR_ID, 0x2051) },
- { PCI_DEVICE(VENDOR_ID, 0x2052) },
- { PCI_DEVICE(VENDOR_ID, 0x2053) },
- { PCI_DEVICE(VENDOR_ID, 0x2054) },
- { PCI_DEVICE(VENDOR_ID, 0x2055) },
- { PCI_DEVICE(VENDOR_ID, 0x2056) },
- { PCI_DEVICE(VENDOR_ID, 0x2057) },
- { PCI_DEVICE(VENDOR_ID, 0x2058) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
-
-static struct pci_driver isicom_driver = {
- .name = "isicom",
- .id_table = isicom_pci_tbl,
- .probe = isicom_probe,
- .remove = isicom_remove
-};
-
-static int prev_card = 3; /* start servicing isi_card[0] */
-static struct tty_driver *isicom_normal;
-
-static void isicom_tx(struct timer_list *unused);
-static void isicom_start(struct tty_struct *tty);
-
-static DEFINE_TIMER(tx, isicom_tx);
-
-/* baud index mappings from linux defns to isi */
-
-static signed char linuxb_to_isib[] = {
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
-};
-
-struct isi_board {
- unsigned long base;
- int irq;
- unsigned char port_count;
- unsigned short status;
- unsigned short port_status; /* each bit for each port */
- unsigned short shift_count;
- struct isi_port *ports;
- signed char count;
- spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */
- unsigned long flags;
- unsigned int index;
-};
-
-struct isi_port {
- unsigned short magic;
- struct tty_port port;
- u16 channel;
- u16 status;
- struct isi_board *card;
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
-};
-
-static struct isi_board isi_card[BOARD_COUNT];
-static struct isi_port isi_ports[PORT_COUNT];
-
-/*
- * Locking functions for card level locking. We need to own both
- * the kernel lock for the card and have the card in a position that
- * it wants to talk.
- */
-
-static int WaitTillCardIsFree(unsigned long base)
-{
- unsigned int count = 0;
-
- while (!(inw(base + 0xe) & 0x1) && count++ < 100)
- mdelay(1);
-
- return !(inw(base + 0xe) & 0x1);
-}
-
-static int lock_card(struct isi_board *card)
-{
- unsigned long base = card->base;
- unsigned int retries, a;
-
- for (retries = 0; retries < 10; retries++) {
- spin_lock_irqsave(&card->card_lock, card->flags);
- for (a = 0; a < 10; a++) {
- if (inw(base + 0xe) & 0x1)
- return 1;
- udelay(10);
- }
- spin_unlock_irqrestore(&card->card_lock, card->flags);
- msleep(10);
- }
- pr_warn("Failed to lock Card (0x%lx)\n", card->base);
-
- return 0; /* Failed to acquire the card! */
-}
-
-static void unlock_card(struct isi_board *card)
-{
- spin_unlock_irqrestore(&card->card_lock, card->flags);
-}
-
-/*
- * ISI Card specific ops ...
- */
-
-/* card->lock HAS to be held */
-static void raise_dtr(struct isi_port *port)
-{
- struct isi_board *card = port->card;
- unsigned long base = card->base;
- u16 channel = port->channel;
-
- if (WaitTillCardIsFree(base))
- return;
-
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0504, base);
- InterruptTheCard(base);
- port->status |= ISI_DTR;
-}
-
-/* card->lock HAS to be held */
-static void drop_dtr(struct isi_port *port)
-{
- struct isi_board *card = port->card;
- unsigned long base = card->base;
- u16 channel = port->channel;
-
- if (WaitTillCardIsFree(base))
- return;
-
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0404, base);
- InterruptTheCard(base);
- port->status &= ~ISI_DTR;
-}
-
-/* card->lock HAS to be held */
-static inline void raise_rts(struct isi_port *port)
-{
- struct isi_board *card = port->card;
- unsigned long base = card->base;
- u16 channel = port->channel;
-
- if (WaitTillCardIsFree(base))
- return;
-
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0a04, base);
- InterruptTheCard(base);
- port->status |= ISI_RTS;
-}
-
-/* card->lock HAS to be held */
-static inline void drop_rts(struct isi_port *port)
-{
- struct isi_board *card = port->card;
- unsigned long base = card->base;
- u16 channel = port->channel;
-
- if (WaitTillCardIsFree(base))
- return;
-
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0804, base);
- InterruptTheCard(base);
- port->status &= ~ISI_RTS;
-}
-
-/* card->lock MUST NOT be held */
-
-static void isicom_dtr_rts(struct tty_port *port, int on)
-{
- struct isi_port *ip = container_of(port, struct isi_port, port);
- struct isi_board *card = ip->card;
- unsigned long base = card->base;
- u16 channel = ip->channel;
-
- if (!lock_card(card))
- return;
-
- if (on) {
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0f04, base);
- InterruptTheCard(base);
- ip->status |= (ISI_DTR | ISI_RTS);
- } else {
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0C04, base);
- InterruptTheCard(base);
- ip->status &= ~(ISI_DTR | ISI_RTS);
- }
- unlock_card(card);
-}
-
-/* card->lock HAS to be held */
-static void drop_dtr_rts(struct isi_port *port)
-{
- struct isi_board *card = port->card;
- unsigned long base = card->base;
- u16 channel = port->channel;
-
- if (WaitTillCardIsFree(base))
- return;
-
- outw(0x8000 | (channel << card->shift_count) | 0x02, base);
- outw(0x0c04, base);
- InterruptTheCard(base);
- port->status &= ~(ISI_RTS | ISI_DTR);
-}
-
-/*
- * ISICOM Driver specific routines ...
- *
- */
-
-static inline int __isicom_paranoia_check(struct isi_port const *port,
- char *name, const char *routine)
-{
- if (!port) {
- pr_warn("Warning: bad isicom magic for dev %s in %s\n",
- name, routine);
- return 1;
- }
- if (port->magic != ISICOM_MAGIC) {
- pr_warn("Warning: NULL isicom port for dev %s in %s\n",
- name, routine);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Transmitter.
- *
- * We shovel data into the card buffers on a regular basis. The card
- * will do the rest of the work for us.
- */
-
-static void isicom_tx(struct timer_list *unused)
-{
- unsigned long flags, base;
- unsigned int retries;
- short count = (BOARD_COUNT-1), card;
- short txcount, wrd, residue, word_count, cnt;
- struct isi_port *port;
- struct tty_struct *tty;
-
- /* find next active board */
- card = (prev_card + 1) & 0x0003;
- while (count-- > 0) {
- if (isi_card[card].status & BOARD_ACTIVE)
- break;
- card = (card + 1) & 0x0003;
- }
- if (!(isi_card[card].status & BOARD_ACTIVE))
- goto sched_again;
-
- prev_card = card;
-
- count = isi_card[card].port_count;
- port = isi_card[card].ports;
- base = isi_card[card].base;
-
- spin_lock_irqsave(&isi_card[card].card_lock, flags);
- for (retries = 0; retries < 100; retries++) {
- if (inw(base + 0xe) & 0x1)
- break;
- udelay(2);
- }
- if (retries >= 100)
- goto unlock;
-
- tty = tty_port_tty_get(&port->port);
- if (tty == NULL)
- goto put_unlock;
-
- for (; count > 0; count--, port++) {
- /* port not active or tx disabled to force flow control */
- if (!tty_port_initialized(&port->port) ||
- !(port->status & ISI_TXOK))
- continue;
-
- txcount = min_t(short, TX_SIZE, port->xmit_cnt);
- if (txcount <= 0 || tty->stopped || tty->hw_stopped)
- continue;
-
- if (!(inw(base + 0x02) & (1 << port->channel)))
- continue;
-
- pr_debug("txing %d bytes, port%d.\n",
- txcount, port->channel + 1);
- outw((port->channel << isi_card[card].shift_count) | txcount,
- base);
- residue = NO;
- wrd = 0;
- while (1) {
- cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
- - port->xmit_tail));
- if (residue == YES) {
- residue = NO;
- if (cnt > 0) {
- wrd |= (port->port.xmit_buf[port->xmit_tail]
- << 8);
- port->xmit_tail = (port->xmit_tail + 1)
- & (SERIAL_XMIT_SIZE - 1);
- port->xmit_cnt--;
- txcount--;
- cnt--;
- outw(wrd, base);
- } else {
- outw(wrd, base);
- break;
- }
- }
- if (cnt <= 0)
- break;
- word_count = cnt >> 1;
- outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
- port->xmit_tail = (port->xmit_tail
- + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
- txcount -= (word_count << 1);
- port->xmit_cnt -= (word_count << 1);
- if (cnt & 0x0001) {
- residue = YES;
- wrd = port->port.xmit_buf[port->xmit_tail];
- port->xmit_tail = (port->xmit_tail + 1)
- & (SERIAL_XMIT_SIZE - 1);
- port->xmit_cnt--;
- txcount--;
- }
- }
-
- InterruptTheCard(base);
- if (port->xmit_cnt <= 0)
- port->status &= ~ISI_TXOK;
- if (port->xmit_cnt <= WAKEUP_CHARS)
- tty_wakeup(tty);
- }
-
-put_unlock:
- tty_kref_put(tty);
-unlock:
- spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
- /* schedule another tx for hopefully in about 10ms */
-sched_again:
- mod_timer(&tx, jiffies + msecs_to_jiffies(10));
-}
-
-/*
- * Main interrupt handler routine
- */
-
-static irqreturn_t isicom_interrupt(int irq, void *dev_id)
-{
- struct isi_board *card = dev_id;
- struct isi_port *port;
- struct tty_struct *tty;
- unsigned long base;
- u16 header, word_count, count, channel;
- short byte_count;
- unsigned char *rp;
-
- if (!card || !(card->status & FIRMWARE_LOADED))
- return IRQ_NONE;
-
- base = card->base;
-
- /* did the card interrupt us? */
- if (!(inw(base + 0x0e) & 0x02))
- return IRQ_NONE;
-
- spin_lock(&card->card_lock);
-
- /*
- * disable any interrupts from the PCI card and lower the
- * interrupt line
- */
- outw(0x8000, base+0x04);
- ClearInterrupt(base);
-
- inw(base); /* get the dummy word out */
- header = inw(base);
- channel = (header & 0x7800) >> card->shift_count;
- byte_count = header & 0xff;
-
- if (channel + 1 > card->port_count) {
- pr_warn("%s(0x%lx): %d(channel) > port_count\n",
- __func__, base, channel + 1);
- outw(0x0000, base+0x04); /* enable interrupts */
- spin_unlock(&card->card_lock);
- return IRQ_HANDLED;
- }
- port = card->ports + channel;
- if (!tty_port_initialized(&port->port)) {
- outw(0x0000, base+0x04); /* enable interrupts */
- spin_unlock(&card->card_lock);
- return IRQ_HANDLED;
- }
-
- tty = tty_port_tty_get(&port->port);
- if (tty == NULL) {
- while (byte_count > 1) {
- inw(base);
- byte_count -= 2;
- }
- if (byte_count & 0x01)
- inw(base);
- outw(0x0000, base+0x04); /* enable interrupts */
- spin_unlock(&card->card_lock);
- return IRQ_HANDLED;
- }
-
- if (header & 0x8000) { /* Status Packet */
- header = inw(base);
- switch (header & 0xff) {
- case 0: /* Change in EIA signals */
- if (tty_port_check_carrier(&port->port)) {
- if (port->status & ISI_DCD) {
- if (!(header & ISI_DCD)) {
- /* Carrier has been lost */
- pr_debug("%s: DCD->low.\n",
- __func__);
- port->status &= ~ISI_DCD;
- tty_hangup(tty);
- }
- } else if (header & ISI_DCD) {
- /* Carrier has been detected */
- pr_debug("%s: DCD->high.\n",
- __func__);
- port->status |= ISI_DCD;
- wake_up_interruptible(&port->port.open_wait);
- }
- } else {
- if (header & ISI_DCD)
- port->status |= ISI_DCD;
- else
- port->status &= ~ISI_DCD;
- }
-
- if (tty_port_cts_enabled(&port->port)) {
- if (tty->hw_stopped) {
- if (header & ISI_CTS) {
- tty->hw_stopped = 0;
- /* start tx ing */
- port->status |= (ISI_TXOK
- | ISI_CTS);
- tty_wakeup(tty);
- }
- } else if (!(header & ISI_CTS)) {
- tty->hw_stopped = 1;
- /* stop tx ing */
- port->status &= ~(ISI_TXOK | ISI_CTS);
- }
- } else {
- if (header & ISI_CTS)
- port->status |= ISI_CTS;
- else
- port->status &= ~ISI_CTS;
- }
-
- if (header & ISI_DSR)
- port->status |= ISI_DSR;
- else
- port->status &= ~ISI_DSR;
-
- if (header & ISI_RI)
- port->status |= ISI_RI;
- else
- port->status &= ~ISI_RI;
-
- break;
-
- case 1: /* Received Break !!! */
- tty_insert_flip_char(&port->port, 0, TTY_BREAK);
- if (port->port.flags & ASYNC_SAK)
- do_SAK(tty);
- tty_flip_buffer_push(&port->port);
- break;
-
- case 2: /* Statistics */
- pr_debug("%s: stats!!!\n", __func__);
- break;
-
- default:
- pr_debug("%s: Unknown code in status packet.\n",
- __func__);
- break;
- }
- } else { /* Data Packet */
- count = tty_prepare_flip_string(&port->port, &rp,
- byte_count & ~1);
- pr_debug("%s: Can rx %d of %d bytes.\n",
- __func__, count, byte_count);
- word_count = count >> 1;
- insw(base, rp, word_count);
- byte_count -= (word_count << 1);
- if (count & 0x0001) {
- tty_insert_flip_char(&port->port, inw(base) & 0xff,
- TTY_NORMAL);
- byte_count -= 2;
- }
- if (byte_count > 0) {
- pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
- __func__, base, channel + 1);
- /* drain out unread xtra data */
- while (byte_count > 0) {
- inw(base);
- byte_count -= 2;
- }
- }
- tty_flip_buffer_push(&port->port);
- }
- outw(0x0000, base+0x04); /* enable interrupts */
- spin_unlock(&card->card_lock);
- tty_kref_put(tty);
-
- return IRQ_HANDLED;
-}
-
-static void isicom_config_port(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
- unsigned long baud;
- unsigned long base = card->base;
- u16 channel_setup, channel = port->channel,
- shift_count = card->shift_count;
- unsigned char flow_ctrl;
-
- /* FIXME: Switch to new tty baud API */
- baud = C_BAUD(tty);
- if (baud & CBAUDEX) {
- baud &= ~CBAUDEX;
-
- /* if CBAUDEX bit is on and the baud is set to either 50 or 75
- * then the card is programmed for 57.6Kbps or 115Kbps
- * respectively.
- */
-
- /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
- if (baud < 1 || baud > 4)
- tty->termios.c_cflag &= ~CBAUDEX;
- else
- baud += 15;
- }
- if (baud == 15) {
-
- /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
- * by the set_serial_info ioctl ... this is done by
- * the 'setserial' utility.
- */
-
- if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- baud++; /* 57.6 Kbps */
- if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- baud += 2; /* 115 Kbps */
- if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- baud += 3; /* 230 kbps*/
- if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- baud += 4; /* 460 kbps*/
- }
- if (linuxb_to_isib[baud] == -1) {
- /* hang up */
- drop_dtr(port);
- return;
- } else
- raise_dtr(port);
-
- if (WaitTillCardIsFree(base) == 0) {
- outw(0x8000 | (channel << shift_count) | 0x03, base);
- outw(linuxb_to_isib[baud] << 8 | 0x03, base);
- channel_setup = 0;
- switch (C_CSIZE(tty)) {
- case CS5:
- channel_setup |= ISICOM_CS5;
- break;
- case CS6:
- channel_setup |= ISICOM_CS6;
- break;
- case CS7:
- channel_setup |= ISICOM_CS7;
- break;
- case CS8:
- channel_setup |= ISICOM_CS8;
- break;
- }
-
- if (C_CSTOPB(tty))
- channel_setup |= ISICOM_2SB;
- if (C_PARENB(tty)) {
- channel_setup |= ISICOM_EVPAR;
- if (C_PARODD(tty))
- channel_setup |= ISICOM_ODPAR;
- }
- outw(channel_setup, base);
- InterruptTheCard(base);
- }
- tty_port_set_check_carrier(&port->port, !C_CLOCAL(tty));
-
- /* flow control settings ...*/
- flow_ctrl = 0;
- tty_port_set_cts_flow(&port->port, C_CRTSCTS(tty));
- if (C_CRTSCTS(tty))
- flow_ctrl |= ISICOM_CTSRTS;
- if (I_IXON(tty))
- flow_ctrl |= ISICOM_RESPOND_XONXOFF;
- if (I_IXOFF(tty))
- flow_ctrl |= ISICOM_INITIATE_XONXOFF;
-
- if (WaitTillCardIsFree(base) == 0) {
- outw(0x8000 | (channel << shift_count) | 0x04, base);
- outw(flow_ctrl << 8 | 0x05, base);
- outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
- InterruptTheCard(base);
- }
-
- /* rx enabled -> enable port for rx on the card */
- if (C_CREAD(tty)) {
- card->port_status |= (1 << channel);
- outw(card->port_status, base + 0x02);
- }
-}
-
-/* open et all */
-
-static inline void isicom_setup_board(struct isi_board *bp)
-{
- int channel;
- struct isi_port *port;
-
- bp->count++;
- if (!(bp->status & BOARD_INIT)) {
- port = bp->ports;
- for (channel = 0; channel < bp->port_count; channel++, port++)
- drop_dtr_rts(port);
- }
- bp->status |= BOARD_ACTIVE | BOARD_INIT;
-}
-
-/* Activate and thus setup board are protected from races against shutdown
- by the tty_port mutex */
-
-static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
-{
- struct isi_port *port = container_of(tport, struct isi_port, port);
- struct isi_board *card = port->card;
- unsigned long flags;
-
- if (tty_port_alloc_xmit_buf(tport) < 0)
- return -ENOMEM;
-
- spin_lock_irqsave(&card->card_lock, flags);
- isicom_setup_board(card);
-
- port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
- /* discard any residual data */
- if (WaitTillCardIsFree(card->base) == 0) {
- outw(0x8000 | (port->channel << card->shift_count) | 0x02,
- card->base);
- outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
- InterruptTheCard(card->base);
- }
- isicom_config_port(tty);
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- return 0;
-}
-
-static int isicom_carrier_raised(struct tty_port *port)
-{
- struct isi_port *ip = container_of(port, struct isi_port, port);
- return (ip->status & ISI_DCD)?1 : 0;
-}
-
-static struct tty_port *isicom_find_port(struct tty_struct *tty)
-{
- struct isi_port *port;
- struct isi_board *card;
- unsigned int board;
- int line = tty->index;
-
- board = BOARD(line);
- card = &isi_card[board];
-
- if (!(card->status & FIRMWARE_LOADED))
- return NULL;
-
- /* open on a port greater than the port count for the card !!! */
- if (line > ((board * 16) + card->port_count - 1))
- return NULL;
-
- port = &isi_ports[line];
- if (isicom_paranoia_check(port, tty->name, "isicom_open"))
- return NULL;
-
- return &port->port;
-}
-
-static int isicom_open(struct tty_struct *tty, struct file *filp)
-{
- struct isi_port *port;
- struct tty_port *tport;
-
- tport = isicom_find_port(tty);
- if (tport == NULL)
- return -ENODEV;
- port = container_of(tport, struct isi_port, port);
-
- tty->driver_data = port;
- return tty_port_open(tport, tty, filp);
-}
-
-/* close et all */
-
-/* card->lock HAS to be held */
-static void isicom_shutdown_port(struct isi_port *port)
-{
- struct isi_board *card = port->card;
-
- if (--card->count < 0) {
- pr_debug("%s: bad board(0x%lx) count %d.\n",
- __func__, card->base, card->count);
- card->count = 0;
- }
- /* last port was closed, shutdown that board too */
- if (!card->count)
- card->status &= BOARD_ACTIVE;
-}
-
-static void isicom_flush_buffer(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
- unsigned long flags;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
- return;
-
- spin_lock_irqsave(&card->card_lock, flags);
- port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- tty_wakeup(tty);
-}
-
-static void isicom_shutdown(struct tty_port *port)
-{
- struct isi_port *ip = container_of(port, struct isi_port, port);
- struct isi_board *card = ip->card;
- unsigned long flags;
-
- /* indicate to the card that no more data can be received
- on this port */
- spin_lock_irqsave(&card->card_lock, flags);
- card->port_status &= ~(1 << ip->channel);
- outw(card->port_status, card->base + 0x02);
- isicom_shutdown_port(ip);
- spin_unlock_irqrestore(&card->card_lock, flags);
- tty_port_free_xmit_buf(port);
-}
-
-static void isicom_close(struct tty_struct *tty, struct file *filp)
-{
- struct isi_port *ip = tty->driver_data;
- struct tty_port *port;
-
- if (ip == NULL)
- return;
-
- port = &ip->port;
- if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
- return;
- tty_port_close(port, tty, filp);
-}
-
-/* write et all */
-static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
- int count)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
- unsigned long flags;
- int cnt, total = 0;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_write"))
- return 0;
-
- spin_lock_irqsave(&card->card_lock, flags);
-
- while (1) {
- cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
- - 1, SERIAL_XMIT_SIZE - port->xmit_head));
- if (cnt <= 0)
- break;
-
- memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
- port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
- - 1);
- port->xmit_cnt += cnt;
- buf += cnt;
- count -= cnt;
- total += cnt;
- }
- if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
- port->status |= ISI_TXOK;
- spin_unlock_irqrestore(&card->card_lock, flags);
- return total;
-}
-
-/* put_char et all */
-static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
- unsigned long flags;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
- return 0;
-
- spin_lock_irqsave(&card->card_lock, flags);
- if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
- spin_unlock_irqrestore(&card->card_lock, flags);
- return 0;
- }
-
- port->port.xmit_buf[port->xmit_head++] = ch;
- port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
- port->xmit_cnt++;
- spin_unlock_irqrestore(&card->card_lock, flags);
- return 1;
-}
-
-/* flush_chars et all */
-static void isicom_flush_chars(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
- return;
-
- if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
- !port->port.xmit_buf)
- return;
-
- /* this tells the transmitter to consider this port for
- data output to the card ... that's the best we can do. */
- port->status |= ISI_TXOK;
-}
-
-/* write_room et all */
-static int isicom_write_room(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- int free;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
- return 0;
-
- free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
- if (free < 0)
- free = 0;
- return free;
-}
-
-/* chars_in_buffer et all */
-static int isicom_chars_in_buffer(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
- return 0;
- return port->xmit_cnt;
-}
-
-/* ioctl et all */
-static int isicom_send_break(struct tty_struct *tty, int length)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
- unsigned long base = card->base;
-
- if (length == -1)
- return -EOPNOTSUPP;
-
- if (!lock_card(card))
- return -EINVAL;
-
- outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
- outw((length & 0xff) << 8 | 0x00, base);
- outw((length & 0xff00u), base);
- InterruptTheCard(base);
-
- unlock_card(card);
- return 0;
-}
-
-static int isicom_tiocmget(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- /* just send the port status */
- u16 status = port->status;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
- return -ENODEV;
-
- return ((status & ISI_RTS) ? TIOCM_RTS : 0) |
- ((status & ISI_DTR) ? TIOCM_DTR : 0) |
- ((status & ISI_DCD) ? TIOCM_CAR : 0) |
- ((status & ISI_DSR) ? TIOCM_DSR : 0) |
- ((status & ISI_CTS) ? TIOCM_CTS : 0) |
- ((status & ISI_RI ) ? TIOCM_RI : 0);
-}
-
-static int isicom_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
- struct isi_port *port = tty->driver_data;
- unsigned long flags;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
- return -ENODEV;
-
- spin_lock_irqsave(&port->card->card_lock, flags);
- if (set & TIOCM_RTS)
- raise_rts(port);
- if (set & TIOCM_DTR)
- raise_dtr(port);
-
- if (clear & TIOCM_RTS)
- drop_rts(port);
- if (clear & TIOCM_DTR)
- drop_dtr(port);
- spin_unlock_irqrestore(&port->card->card_lock, flags);
-
- return 0;
-}
-
-static int isicom_set_serial_info(struct tty_struct *tty,
- struct serial_struct *ss)
-{
- struct isi_port *port = tty->driver_data;
- int reconfig_port;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
- return -ENODEV;
-
- mutex_lock(&port->port.mutex);
- reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
- (ss->flags & ASYNC_SPD_MASK));
-
- if (!capable(CAP_SYS_ADMIN)) {
- if ((ss->close_delay != port->port.close_delay) ||
- (ss->closing_wait != port->port.closing_wait) ||
- ((ss->flags & ~ASYNC_USR_MASK) !=
- (port->port.flags & ~ASYNC_USR_MASK))) {
- mutex_unlock(&port->port.mutex);
- return -EPERM;
- }
- port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
- (ss->flags & ASYNC_USR_MASK));
- } else {
- port->port.close_delay = ss->close_delay;
- port->port.closing_wait = ss->closing_wait;
- port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
- (ss->flags & ASYNC_FLAGS));
- }
- if (reconfig_port) {
- unsigned long flags;
- spin_lock_irqsave(&port->card->card_lock, flags);
- isicom_config_port(tty);
- spin_unlock_irqrestore(&port->card->card_lock, flags);
- }
- mutex_unlock(&port->port.mutex);
- return 0;
-}
-
-static int isicom_get_serial_info(struct tty_struct *tty,
- struct serial_struct *ss)
-{
- struct isi_port *port = tty->driver_data;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
- return -ENODEV;
-
- mutex_lock(&port->port.mutex);
-/* ss->type = ? */
- ss->line = port - isi_ports;
- ss->port = port->card->base;
- ss->irq = port->card->irq;
- ss->flags = port->port.flags;
-/* ss->baud_base = ? */
- ss->close_delay = port->port.close_delay;
- ss->closing_wait = port->port.closing_wait;
- mutex_unlock(&port->port.mutex);
- return 0;
-}
-
-/* set_termios et all */
-static void isicom_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios)
-{
- struct isi_port *port = tty->driver_data;
- unsigned long flags;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
- return;
-
- if (tty->termios.c_cflag == old_termios->c_cflag &&
- tty->termios.c_iflag == old_termios->c_iflag)
- return;
-
- spin_lock_irqsave(&port->card->card_lock, flags);
- isicom_config_port(tty);
- spin_unlock_irqrestore(&port->card->card_lock, flags);
-
- if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) {
- tty->hw_stopped = 0;
- isicom_start(tty);
- }
-}
-
-/* throttle et all */
-static void isicom_throttle(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
- return;
-
- /* tell the card that this port cannot handle any more data for now */
- card->port_status &= ~(1 << port->channel);
- outw(card->port_status, card->base + 0x02);
-}
-
-/* unthrottle et all */
-static void isicom_unthrottle(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
- struct isi_board *card = port->card;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
- return;
-
- /* tell the card that this port is ready to accept more data */
- card->port_status |= (1 << port->channel);
- outw(card->port_status, card->base + 0x02);
-}
-
-/* stop et all */
-static void isicom_stop(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
- return;
-
- /* this tells the transmitter not to consider this port for
- data output to the card. */
- port->status &= ~ISI_TXOK;
-}
-
-/* start et all */
-static void isicom_start(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_start"))
- return;
-
- /* this tells the transmitter to consider this port for
- data output to the card. */
- port->status |= ISI_TXOK;
-}
-
-static void isicom_hangup(struct tty_struct *tty)
-{
- struct isi_port *port = tty->driver_data;
-
- if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
- return;
- tty_port_hangup(&port->port);
-}
-
-
-/*
- * Driver init and deinit functions
- */
-
-static const struct tty_operations isicom_ops = {
- .open = isicom_open,
- .close = isicom_close,
- .write = isicom_write,
- .put_char = isicom_put_char,
- .flush_chars = isicom_flush_chars,
- .write_room = isicom_write_room,
- .chars_in_buffer = isicom_chars_in_buffer,
- .set_termios = isicom_set_termios,
- .throttle = isicom_throttle,
- .unthrottle = isicom_unthrottle,
- .stop = isicom_stop,
- .start = isicom_start,
- .hangup = isicom_hangup,
- .flush_buffer = isicom_flush_buffer,
- .tiocmget = isicom_tiocmget,
- .tiocmset = isicom_tiocmset,
- .break_ctl = isicom_send_break,
- .get_serial = isicom_get_serial_info,
- .set_serial = isicom_set_serial_info,
-};
-
-static const struct tty_port_operations isicom_port_ops = {
- .carrier_raised = isicom_carrier_raised,
- .dtr_rts = isicom_dtr_rts,
- .activate = isicom_activate,
- .shutdown = isicom_shutdown,
-};
-
-static int reset_card(struct pci_dev *pdev,
- const unsigned int card, unsigned int *signature)
-{
- struct isi_board *board = pci_get_drvdata(pdev);
- unsigned long base = board->base;
- unsigned int sig, portcount = 0;
- int retval = 0;
-
- dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
- base);
-
- inw(base + 0x8);
-
- msleep(10);
-
- outw(0, base + 0x8); /* Reset */
-
- msleep(1000);
-
- sig = inw(base + 0x4) & 0xff;
-
- if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
- sig != 0xee) {
- dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
- "bad I/O Port Address 0x%lx).\n", card + 1, base);
- dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
- retval = -EIO;
- goto end;
- }
-
- msleep(10);
-
- portcount = inw(base + 0x2);
- if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
- portcount != 8 && portcount != 16)) {
- dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
- card + 1);
- retval = -EIO;
- goto end;
- }
-
- switch (sig) {
- case 0xa5:
- case 0xbb:
- case 0xdd:
- board->port_count = (portcount == 4) ? 4 : 8;
- board->shift_count = 12;
- break;
- case 0xcc:
- case 0xee:
- board->port_count = 16;
- board->shift_count = 11;
- break;
- }
- dev_info(&pdev->dev, "-Done\n");
- *signature = sig;
-
-end:
- return retval;
-}
-
-static int load_firmware(struct pci_dev *pdev,
- const unsigned int index, const unsigned int signature)
-{
- struct isi_board *board = pci_get_drvdata(pdev);
- const struct firmware *fw;
- unsigned long base = board->base;
- unsigned int a;
- u16 word_count, status;
- int retval = -EIO;
- char *name;
- u8 *data;
-
- struct stframe {
- u16 addr;
- u16 count;
- u8 data[0];
- } *frame;
-
- switch (signature) {
- case 0xa5:
- name = "isi608.bin";
- break;
- case 0xbb:
- name = "isi608em.bin";
- break;
- case 0xcc:
- name = "isi616em.bin";
- break;
- case 0xdd:
- name = "isi4608.bin";
- break;
- case 0xee:
- name = "isi4616.bin";
- break;
- default:
- dev_err(&pdev->dev, "Unknown signature.\n");
- goto end;
- }
-
- retval = request_firmware(&fw, name, &pdev->dev);
- if (retval)
- goto end;
-
- retval = -EIO;
-
- for (frame = (struct stframe *)fw->data;
- frame < (struct stframe *)(fw->data + fw->size);
- frame = (struct stframe *)((u8 *)(frame + 1) +
- frame->count)) {
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- outw(0xf0, base); /* start upload sequence */
- outw(0x00, base);
- outw(frame->addr, base); /* lsb of address */
-
- word_count = frame->count / 2 + frame->count % 2;
- outw(word_count, base);
- InterruptTheCard(base);
-
- udelay(100); /* 0x2f */
-
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- status = inw(base + 0x4);
- if (status != 0) {
- dev_warn(&pdev->dev, "Card%d rejected load header:\n"
- "Address:0x%x\n"
- "Count:0x%x\n"
- "Status:0x%x\n",
- index + 1, frame->addr, frame->count, status);
- goto errrelfw;
- }
- outsw(base, frame->data, word_count);
-
- InterruptTheCard(base);
-
- udelay(50); /* 0x0f */
-
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- status = inw(base + 0x4);
- if (status != 0) {
- dev_err(&pdev->dev, "Card%d got out of sync.Card "
- "Status:0x%x\n", index + 1, status);
- goto errrelfw;
- }
- }
-
-/* XXX: should we test it by reading it back and comparing with original like
- * in load firmware package? */
- for (frame = (struct stframe *)fw->data;
- frame < (struct stframe *)(fw->data + fw->size);
- frame = (struct stframe *)((u8 *)(frame + 1) +
- frame->count)) {
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- outw(0xf1, base); /* start download sequence */
- outw(0x00, base);
- outw(frame->addr, base); /* lsb of address */
-
- word_count = (frame->count >> 1) + frame->count % 2;
- outw(word_count + 1, base);
- InterruptTheCard(base);
-
- udelay(50); /* 0xf */
-
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- status = inw(base + 0x4);
- if (status != 0) {
- dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
- "Address:0x%x\n"
- "Count:0x%x\n"
- "Status: 0x%x\n",
- index + 1, frame->addr, frame->count, status);
- goto errrelfw;
- }
-
- data = kmalloc_array(word_count, 2, GFP_KERNEL);
- if (data == NULL) {
- dev_err(&pdev->dev, "Card%d, firmware upload "
- "failed, not enough memory\n", index + 1);
- goto errrelfw;
- }
- inw(base);
- insw(base, data, word_count);
- InterruptTheCard(base);
-
- for (a = 0; a < frame->count; a++)
- if (data[a] != frame->data[a]) {
- kfree(data);
- dev_err(&pdev->dev, "Card%d, firmware upload "
- "failed\n", index + 1);
- goto errrelfw;
- }
- kfree(data);
-
- udelay(50); /* 0xf */
-
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- status = inw(base + 0x4);
- if (status != 0) {
- dev_err(&pdev->dev, "Card%d verify got out of sync. "
- "Card Status:0x%x\n", index + 1, status);
- goto errrelfw;
- }
- }
-
- /* xfer ctrl */
- if (WaitTillCardIsFree(base))
- goto errrelfw;
-
- outw(0xf2, base);
- outw(0x800, base);
- outw(0x0, base);
- outw(0x0, base);
- InterruptTheCard(base);
- outw(0x0, base + 0x4); /* for ISI4608 cards */
-
- board->status |= FIRMWARE_LOADED;
- retval = 0;
-
-errrelfw:
- release_firmware(fw);
-end:
- return retval;
-}
-
-/*
- * Insmod can set static symbols so keep these static
- */
-static unsigned int card_count;
-
-static int isicom_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- unsigned int signature, index;
- int retval = -EPERM;
- struct isi_board *board = NULL;
-
- if (card_count >= BOARD_COUNT)
- goto err;
-
- retval = pci_enable_device(pdev);
- if (retval) {
- dev_err(&pdev->dev, "failed to enable\n");
- goto err;
- }
-
- dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
-
- /* allot the first empty slot in the array */
- for (index = 0; index < BOARD_COUNT; index++) {
- if (isi_card[index].base == 0) {
- board = &isi_card[index];
- break;
- }
- }
- if (index == BOARD_COUNT) {
- retval = -ENODEV;
- goto err_disable;
- }
-
- board->index = index;
- board->base = pci_resource_start(pdev, 3);
- board->irq = pdev->irq;
- card_count++;
-
- pci_set_drvdata(pdev, board);
-
- retval = pci_request_region(pdev, 3, ISICOM_NAME);
- if (retval) {
- dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
- "will be disabled.\n", board->base, board->base + 15,
- index + 1);
- retval = -EBUSY;
- goto errdec;
- }
-
- retval = request_irq(board->irq, isicom_interrupt,
- IRQF_SHARED, ISICOM_NAME, board);
- if (retval < 0) {
- dev_err(&pdev->dev, "Could not install handler at Irq %d. "
- "Card%d will be disabled.\n", board->irq, index + 1);
- goto errunrr;
- }
-
- retval = reset_card(pdev, index, &signature);
- if (retval < 0)
- goto errunri;
-
- retval = load_firmware(pdev, index, signature);
- if (retval < 0)
- goto errunri;
-
- for (index = 0; index < board->port_count; index++) {
- struct tty_port *tport = &board->ports[index].port;
- tty_port_init(tport);
- tport->ops = &isicom_port_ops;
- tport->close_delay = 50 * HZ/100;
- tport->closing_wait = 3000 * HZ/100;
- tty_port_register_device(tport, isicom_normal,
- board->index * 16 + index, &pdev->dev);
- }
-
- return 0;
-
-errunri:
- free_irq(board->irq, board);
-errunrr:
- pci_release_region(pdev, 3);
-errdec:
- board->base = 0;
- card_count--;
-err_disable:
- pci_disable_device(pdev);
-err:
- return retval;
-}
-
-static void isicom_remove(struct pci_dev *pdev)
-{
- struct isi_board *board = pci_get_drvdata(pdev);
- unsigned int i;
-
- for (i = 0; i < board->port_count; i++) {
- tty_unregister_device(isicom_normal, board->index * 16 + i);
- tty_port_destroy(&board->ports[i].port);
- }
-
- free_irq(board->irq, board);
- pci_release_region(pdev, 3);
- board->base = 0;
- card_count--;
- pci_disable_device(pdev);
-}
-
-static int __init isicom_init(void)
-{
- int retval, idx, channel;
- struct isi_port *port;
-
- for (idx = 0; idx < BOARD_COUNT; idx++) {
- port = &isi_ports[idx * 16];
- isi_card[idx].ports = port;
- spin_lock_init(&isi_card[idx].card_lock);
- for (channel = 0; channel < 16; channel++, port++) {
- port->magic = ISICOM_MAGIC;
- port->card = &isi_card[idx];
- port->channel = channel;
- port->status = 0;
- /* . . . */
- }
- isi_card[idx].base = 0;
- isi_card[idx].irq = 0;
- }
-
- /* tty driver structure initialization */
- isicom_normal = alloc_tty_driver(PORT_COUNT);
- if (!isicom_normal) {
- retval = -ENOMEM;
- goto error;
- }
-
- isicom_normal->name = "ttyM";
- isicom_normal->major = ISICOM_NMAJOR;
- isicom_normal->minor_start = 0;
- isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
- isicom_normal->subtype = SERIAL_TYPE_NORMAL;
- isicom_normal->init_termios = tty_std_termios;
- isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
- CLOCAL;
- isicom_normal->flags = TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
- tty_set_operations(isicom_normal, &isicom_ops);
-
- retval = tty_register_driver(isicom_normal);
- if (retval) {
- pr_debug("Couldn't register the dialin driver\n");
- goto err_puttty;
- }
-
- retval = pci_register_driver(&isicom_driver);
- if (retval < 0) {
- pr_err("Unable to register pci driver.\n");
- goto err_unrtty;
- }
-
- mod_timer(&tx, jiffies + 1);
-
- return 0;
-err_unrtty:
- tty_unregister_driver(isicom_normal);
-err_puttty:
- put_tty_driver(isicom_normal);
-error:
- return retval;
-}
-
-static void __exit isicom_exit(void)
-{
- del_timer_sync(&tx);
-
- pci_unregister_driver(&isicom_driver);
- tty_unregister_driver(isicom_normal);
- put_tty_driver(isicom_normal);
-}
-
-module_init(isicom_init);
-module_exit(isicom_exit);
-
-MODULE_AUTHOR("MultiTech");
-MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("isi608.bin");
-MODULE_FIRMWARE("isi608em.bin");
-MODULE_FIRMWARE("isi616em.bin");
-MODULE_FIRMWARE("isi4608.bin");
-MODULE_FIRMWARE("isi4616.bin");
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index 9f13f7d49dd7..4d4f15b5cd29 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -1118,9 +1118,7 @@ static void __exit moxa_exit(void)
del_timer_sync(&moxaTimer);
- if (tty_unregister_driver(moxaDriver))
- printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
- "serial driver\n");
+ tty_unregister_driver(moxaDriver);
put_tty_driver(moxaDriver);
}
@@ -2040,7 +2038,7 @@ static int moxa_get_serial_info(struct tty_struct *tty,
ss->line = info->port.tty->index,
ss->flags = info->port.flags,
ss->baud_base = 921600,
- ss->close_delay = info->port.close_delay;
+ ss->close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
mutex_unlock(&info->port.mutex);
return 0;
}
@@ -2050,30 +2048,31 @@ static int moxa_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct moxa_port *info = tty->driver_data;
+ unsigned int close_delay;
if (tty->index == MAX_PORTS)
return -EINVAL;
if (!info)
return -ENODEV;
- if (ss->irq != 0 || ss->port != 0 ||
- ss->custom_divisor != 0 ||
- ss->baud_base != 921600)
- return -EPERM;
+ close_delay = msecs_to_jiffies(ss->close_delay * 10);
mutex_lock(&info->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
- if (((ss->flags & ~ASYNC_USR_MASK) !=
+ if (close_delay != info->port.close_delay ||
+ ss->type != info->type ||
+ ((ss->flags & ~ASYNC_USR_MASK) !=
(info->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&info->port.mutex);
return -EPERM;
}
- }
- info->port.close_delay = ss->close_delay * HZ / 100;
+ } else {
+ info->port.close_delay = close_delay;
- MoxaSetFifo(info, ss->type == PORT_16550A);
+ MoxaSetFifo(info, ss->type == PORT_16550A);
- info->type = ss->type;
+ info->type = ss->type;
+ }
mutex_unlock(&info->port.mutex);
return 0;
}
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 4203b64bccdb..16a852ecbe8a 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -1208,19 +1208,26 @@ static int mxser_get_serial_info(struct tty_struct *tty,
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
+ unsigned int closing_wait, close_delay;
if (tty->index == MXSER_PORTS)
return -ENOTTY;
mutex_lock(&port->mutex);
+
+ close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
+ closing_wait = info->port.closing_wait;
+ if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ closing_wait = jiffies_to_msecs(closing_wait) / 10;
+
ss->type = info->type,
ss->line = tty->index,
ss->port = info->ioaddr,
ss->irq = info->board->irq,
ss->flags = info->port.flags,
ss->baud_base = info->baud_base,
- ss->close_delay = info->port.close_delay,
- ss->closing_wait = info->port.closing_wait,
+ ss->close_delay = close_delay;
+ ss->closing_wait = closing_wait;
ss->custom_divisor = info->custom_divisor,
mutex_unlock(&port->mutex);
return 0;
@@ -1233,7 +1240,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
struct tty_port *port = &info->port;
speed_t baud;
unsigned long sl_flags;
- unsigned int flags;
+ unsigned int flags, close_delay, closing_wait;
int retval = 0;
if (tty->index == MXSER_PORTS)
@@ -1255,9 +1262,15 @@ static int mxser_set_serial_info(struct tty_struct *tty,
flags = port->flags & ASYNC_SPD_MASK;
+ close_delay = msecs_to_jiffies(ss->close_delay * 10);
+ closing_wait = ss->closing_wait;
+ if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ closing_wait = msecs_to_jiffies(closing_wait * 10);
+
if (!capable(CAP_SYS_ADMIN)) {
if ((ss->baud_base != info->baud_base) ||
- (ss->close_delay != info->port.close_delay) ||
+ (close_delay != info->port.close_delay) ||
+ (closing_wait != info->port.closing_wait) ||
((ss->flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->mutex);
return -EPERM;
@@ -1271,8 +1284,8 @@ static int mxser_set_serial_info(struct tty_struct *tty,
*/
port->flags = ((port->flags & ~ASYNC_FLAGS) |
(ss->flags & ASYNC_FLAGS));
- port->close_delay = ss->close_delay * HZ / 100;
- port->closing_wait = ss->closing_wait * HZ / 100;
+ port->close_delay = close_delay;
+ port->closing_wait = closing_wait;
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
(ss->baud_base != info->baud_base ||
ss->custom_divisor !=
@@ -1284,11 +1297,11 @@ static int mxser_set_serial_info(struct tty_struct *tty,
baud = ss->baud_base / ss->custom_divisor;
tty_encode_baud_rate(tty, baud, baud);
}
- }
- info->type = ss->type;
+ info->type = ss->type;
- process_txrx_fifo(info);
+ process_txrx_fifo(info);
+ }
if (tty_port_initialized(port)) {
if (flags != (port->flags & ASYNC_SPD_MASK)) {
@@ -2142,14 +2155,7 @@ end_intr:
port->mon_data.rxcnt += cnt;
port->mon_data.up_rxcnt += cnt;
- /*
- * We are called from an interrupt context with &port->slock
- * being held. Drop it temporarily in order to prevent
- * recursive locking.
- */
- spin_unlock(&port->slock);
tty_flip_buffer_push(&port->port);
- spin_lock(&port->slock);
}
static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 51dafc06f541..5fea02cfb0cc 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -50,6 +50,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/gsmmux.h>
+#include "tty.h"
static int debug;
module_param(debug, int, 0600);
@@ -266,7 +267,7 @@ struct gsm_mux {
#define MAX_MUX 4 /* 256 minors */
static struct gsm_mux *gsm_mux[MAX_MUX]; /* GSM muxes */
-static spinlock_t gsm_mux_lock;
+static DEFINE_SPINLOCK(gsm_mux_lock);
static struct tty_driver *gsm_tty_driver;
@@ -2384,8 +2385,18 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
/* Don't register device 0 - this is the control channel and not
a usable tty interface */
base = mux_num_to_base(gsm); /* Base for this MUX */
- for (i = 1; i < NUM_DLCI; i++)
- tty_register_device(gsm_tty_driver, base + i, NULL);
+ for (i = 1; i < NUM_DLCI; i++) {
+ struct device *dev;
+
+ dev = tty_register_device(gsm_tty_driver,
+ base + i, NULL);
+ if (IS_ERR(dev)) {
+ for (i--; i >= 1; i--)
+ tty_unregister_device(gsm_tty_driver,
+ base + i);
+ return PTR_ERR(dev);
+ }
+ }
}
return ret;
}
@@ -2416,27 +2427,24 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
struct gsm_mux *gsm = tty->disc_data;
- const unsigned char *dp;
- char *f;
- int i;
char flags = TTY_NORMAL;
if (debug & 4)
print_hex_dump_bytes("gsmld_receive: ", DUMP_PREFIX_OFFSET,
cp, count);
- for (i = count, dp = cp, f = fp; i; i--, dp++) {
- if (f)
- flags = *f++;
+ for (; count; count--, cp++) {
+ if (fp)
+ flags = *fp++;
switch (flags) {
case TTY_NORMAL:
- gsm->receive(gsm, *dp);
+ gsm->receive(gsm, *cp);
break;
case TTY_OVERRUN:
case TTY_BREAK:
case TTY_PARITY:
case TTY_FRAME:
- gsm_error(gsm, *dp, flags);
+ gsm_error(gsm, *cp, flags);
break;
default:
WARN_ONCE(1, "%s: unknown flag %d\n",
@@ -2849,7 +2857,6 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
/* Line discipline for real tty */
static struct tty_ldisc_ops tty_ldisc_packet = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "n_gsm",
.open = gsmld_open,
.close = gsmld_close,
@@ -3052,7 +3059,7 @@ static int gsmtty_write_room(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
if (dlci->state == DLCI_CLOSED)
- return -EINVAL;
+ return 0;
return TX_SIZE - kfifo_len(&dlci->fifo);
}
@@ -3060,7 +3067,7 @@ static int gsmtty_chars_in_buffer(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
if (dlci->state == DLCI_CLOSED)
- return -EINVAL;
+ return 0;
return kfifo_len(&dlci->fifo);
}
@@ -3261,8 +3268,6 @@ static int __init gsm_init(void)
gsm_tty_driver->init_termios.c_lflag &= ~ECHO;
tty_set_operations(gsm_tty_driver, &gsmtty_ops);
- spin_lock_init(&gsm_mux_lock);
-
if (tty_register_driver(gsm_tty_driver)) {
put_tty_driver(gsm_tty_driver);
tty_unregister_ldisc(N_GSM0710);
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index 1363e659dc1d..b0f33e8ac819 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -100,6 +100,7 @@
#include <asm/termios.h>
#include <linux/uaccess.h>
+#include "tty.h"
/*
* Buffers for individual HDLC frames
@@ -787,7 +788,6 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
static struct tty_ldisc_ops n_hdlc_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "hdlc",
.open = n_hdlc_tty_open,
.close = n_hdlc_tty_close,
diff --git a/drivers/tty/n_null.c b/drivers/tty/n_null.c
index ce03ae78f5c6..b8f67b5f1ef8 100644
--- a/drivers/tty/n_null.c
+++ b/drivers/tty/n_null.c
@@ -40,7 +40,6 @@ static void n_null_receivebuf(struct tty_struct *tty,
static struct tty_ldisc_ops null_ldisc = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "n_null",
.open = n_null_open,
.close = n_null_close,
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 3161f0a535e3..2eb76ea1d88d 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -146,7 +146,6 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
.owner = THIS_MODULE,
- .magic = TTY_LDISC_MAGIC,
.name = "R3964",
.open = r3964_open,
.close = r3964_close,
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 87ec15dbe10d..9686c5d10571 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -49,6 +49,7 @@
#include <linux/module.h>
#include <linux/ratelimit.h>
#include <linux/vmalloc.h>
+#include "tty.h"
/*
* Until this number of characters is queued in the xmit buffer, select will
@@ -2488,7 +2489,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
}
static struct tty_ldisc_ops n_tty_ops = {
- .magic = TTY_LDISC_MAGIC,
+ .owner = THIS_MODULE,
.name = "n_tty",
.open = n_tty_open,
.close = n_tty_close,
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index 861e95043191..9a2d78ace49b 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -47,9 +47,6 @@
#include <linux/delay.h>
-
-#define VERSION_STRING DRIVER_DESC " 2.1d"
-
/* Default debug printout level */
#define NOZOMI_DEBUG_LEVEL 0x00
static int debug = NOZOMI_DEBUG_LEVEL;
@@ -89,7 +86,6 @@ do { \
/* Defines */
#define NOZOMI_NAME "nozomi"
#define NOZOMI_NAME_TTY "nozomi_tty"
-#define DRIVER_DESC "Nozomi driver"
#define NTTY_TTY_MAXMINORS 256
#define NTTY_FIFO_BUFFER_SIZE 8192
@@ -359,12 +355,6 @@ struct nozomi {
u32 open_ttys;
};
-/* This is a data packet that is read or written to/from card */
-struct buffer {
- u32 size; /* size is the length of the data buffer */
- u8 *data;
-} __attribute__ ((packed));
-
/* Global variables */
static const struct pci_device_id nozomi_pci_tbl[] = {
{PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
@@ -787,7 +777,6 @@ static int receive_data(enum port_type index, struct nozomi *dc)
int i, ret;
size = __le32_to_cpu(readl(addr));
- /* DBG1( "%d bytes port: %d", size, index); */
if (tty && tty_throttled(tty)) {
DBG1("No room in tty, don't read data, don't ack interrupt, "
@@ -1318,8 +1307,6 @@ static int nozomi_card_init(struct pci_dev *pdev,
int ndev_idx;
int i;
- dev_dbg(&pdev->dev, "Init, new card found\n");
-
for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
if (!ndevs[ndev_idx])
break;
@@ -1453,8 +1440,6 @@ static void tty_exit(struct nozomi *dc)
{
unsigned int i;
- DBG1(" ");
-
for (i = 0; i < MAX_PORT; ++i)
tty_port_tty_hangup(&dc->port[i].port, false);
@@ -1619,8 +1604,6 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
struct port *port = tty->driver_data;
unsigned long flags;
- /* DBG1( "WRITEx: %d, index = %d", count, index); */
-
if (!dc || !port)
return -ENODEV;
@@ -1746,8 +1729,6 @@ static int ntty_ioctl(struct tty_struct *tty,
struct port *port = tty->driver_data;
int rval = -ENOIOCTLCMD;
- DBG1("******** IOCTL, cmd: %d", cmd);
-
switch (cmd) {
case TIOCMIWAIT: {
struct async_icount cprev = port->tty_icount;
@@ -1773,7 +1754,6 @@ static void ntty_unthrottle(struct tty_struct *tty)
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;
- DBG1("UNTHROTTLE");
spin_lock_irqsave(&dc->spin_mutex, flags);
enable_transmit_dl(tty->index % MAX_PORT, dc);
set_rts(tty, 1);
@@ -1790,7 +1770,6 @@ static void ntty_throttle(struct tty_struct *tty)
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;
- DBG1("THROTTLE");
spin_lock_irqsave(&dc->spin_mutex, flags);
set_rts(tty, 0);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
@@ -1847,8 +1826,6 @@ static __init int nozomi_init(void)
{
int ret;
- printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
-
ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
if (!ntty_driver)
return -ENOMEM;
@@ -1888,7 +1865,6 @@ free_tty:
static __exit void nozomi_exit(void)
{
- printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
pci_unregister_driver(&nozomi_driver);
tty_unregister_driver(ntty_driver);
put_tty_driver(ntty_driver);
@@ -1898,4 +1874,4 @@ module_init(nozomi_init);
module_exit(nozomi_exit);
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_DESCRIPTION("Nozomi driver");
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 5e2374580e27..9b5d4ae5d8f2 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -29,6 +29,7 @@
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/compat.h>
+#include "tty.h"
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
@@ -159,6 +160,7 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
static int pty_set_lock(struct tty_struct *tty, int __user *arg)
{
int val;
+
if (get_user(val, arg))
return -EFAULT;
if (val)
@@ -171,6 +173,7 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
static int pty_get_lock(struct tty_struct *tty, int __user *arg)
{
int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
+
return put_user(locked, arg);
}
@@ -200,6 +203,7 @@ static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
{
int pktmode = tty->packet;
+
return put_user(pktmode, arg);
}
@@ -463,6 +467,7 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
{
struct tty_struct *pair = tty->link;
+
driver->ttys[tty->index] = NULL;
if (pair)
pair->driver->ttys[pair->index] = NULL;
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
deleted file mode 100644
index 2540b2e4c8e8..000000000000
--- a/drivers/tty/rocket.c
+++ /dev/null
@@ -1,3127 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
-/*
- * RocketPort device driver for Linux
- *
- * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
- *
- * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc.
- */
-
-/*
- * Kernel Synchronization:
- *
- * This driver has 2 kernel control paths - exception handlers (calls into the driver
- * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts
- * are not used.
- *
- * Critical data:
- * - rp_table[], accessed through passed "info" pointers, is a global (static) array of
- * serial port state information and the xmit_buf circular buffer. Protected by
- * a per port spinlock.
- * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there
- * is data to be transmitted. Protected by atomic bit operations.
- * - rp_num_ports, int indicating number of open ports, protected by atomic operations.
- *
- * rp_write() and rp_write_char() functions use a per port semaphore to protect against
- * simultaneous access to the same port by more than one process.
- */
-
-/****** Defines ******/
-#define ROCKET_PARANOIA_CHECK
-#define ROCKET_DISABLE_SIMUSAGE
-
-#undef ROCKET_SOFT_FLOW
-#undef ROCKET_DEBUG_OPEN
-#undef ROCKET_DEBUG_INTR
-#undef ROCKET_DEBUG_WRITE
-#undef ROCKET_DEBUG_FLOW
-#undef ROCKET_DEBUG_THROTTLE
-#undef ROCKET_DEBUG_WAIT_UNTIL_SENT
-#undef ROCKET_DEBUG_RECEIVE
-#undef ROCKET_DEBUG_HANGUP
-#undef REV_PCI_ORDER
-#undef ROCKET_DEBUG_IO
-
-#define POLL_PERIOD (HZ/100) /* Polling period .01 seconds (10ms) */
-
-/****** Kernel includes ******/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mutex.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/wait.h>
-#include <linux/pci.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-#include <asm/unaligned.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-
-/****** RocketPort includes ******/
-
-#include "rocket_int.h"
-#include "rocket.h"
-
-#define ROCKET_VERSION "2.09"
-#define ROCKET_DATE "12-June-2003"
-
-/****** RocketPort Local Variables ******/
-
-static void rp_do_poll(struct timer_list *unused);
-
-static struct tty_driver *rocket_driver;
-
-static struct rocket_version driver_version = {
- ROCKET_VERSION, ROCKET_DATE
-};
-
-static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of serial port state information. */
-static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */
- /* eg. Bit 0 indicates port 0 has xmit data, ... */
-static atomic_t rp_num_ports_open; /* Number of serial ports open */
-static DEFINE_TIMER(rocket_timer, rp_do_poll);
-
-static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */
-static unsigned long board2;
-static unsigned long board3;
-static unsigned long board4;
-static unsigned long controller;
-static bool support_low_speed;
-static unsigned long modem1;
-static unsigned long modem2;
-static unsigned long modem3;
-static unsigned long modem4;
-static unsigned long pc104_1[8];
-static unsigned long pc104_2[8];
-static unsigned long pc104_3[8];
-static unsigned long pc104_4[8];
-static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
-
-static int rp_baud_base[NUM_BOARDS]; /* Board config info (Someday make a per-board structure) */
-static unsigned long rcktpt_io_addr[NUM_BOARDS];
-static int rcktpt_type[NUM_BOARDS];
-static int is_PCI[NUM_BOARDS];
-static rocketModel_t rocketModel[NUM_BOARDS];
-static int max_board;
-static const struct tty_port_operations rocket_port_ops;
-
-/*
- * The following arrays define the interrupt bits corresponding to each AIOP.
- * These bits are different between the ISA and regular PCI boards and the
- * Universal PCI boards.
- */
-
-static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
- AIOP_INTR_BIT_0,
- AIOP_INTR_BIT_1,
- AIOP_INTR_BIT_2,
- AIOP_INTR_BIT_3
-};
-
-#ifdef CONFIG_PCI
-static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
- UPCI_AIOP_INTR_BIT_0,
- UPCI_AIOP_INTR_BIT_1,
- UPCI_AIOP_INTR_BIT_2,
- UPCI_AIOP_INTR_BIT_3
-};
-#endif
-
-static Byte_t RData[RDATASIZE] = {
- 0x00, 0x09, 0xf6, 0x82,
- 0x02, 0x09, 0x86, 0xfb,
- 0x04, 0x09, 0x00, 0x0a,
- 0x06, 0x09, 0x01, 0x0a,
- 0x08, 0x09, 0x8a, 0x13,
- 0x0a, 0x09, 0xc5, 0x11,
- 0x0c, 0x09, 0x86, 0x85,
- 0x0e, 0x09, 0x20, 0x0a,
- 0x10, 0x09, 0x21, 0x0a,
- 0x12, 0x09, 0x41, 0xff,
- 0x14, 0x09, 0x82, 0x00,
- 0x16, 0x09, 0x82, 0x7b,
- 0x18, 0x09, 0x8a, 0x7d,
- 0x1a, 0x09, 0x88, 0x81,
- 0x1c, 0x09, 0x86, 0x7a,
- 0x1e, 0x09, 0x84, 0x81,
- 0x20, 0x09, 0x82, 0x7c,
- 0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE] = {
- 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
- 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
- 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
- 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
- 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
- 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
- 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
- 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
- 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
- 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
- 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
- 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
- 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
-};
-
-static CONTROLLER_T sController[CTL_SIZE] = {
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
-};
-
-static Byte_t sBitMapClrTbl[8] = {
- 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
-};
-
-static Byte_t sBitMapSetTbl[8] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-static int sClockPrescale = 0x14;
-
-/*
- * Line number is the ttySIx number (x), the Minor number. We
- * assign them sequentially, starting at zero. The following
- * array keeps track of the line number assigned to a given board/aiop/channel.
- */
-static unsigned char lineNumbers[MAX_RP_PORTS];
-static unsigned long nextLineNumber;
-
-/***** RocketPort Static Prototypes *********/
-static int __init init_ISA(int i);
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void rp_flush_buffer(struct tty_struct *tty);
-static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
-static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
-static void rp_start(struct tty_struct *tty);
-static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
- int ChanNum);
-static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
-static void sFlushRxFIFO(CHANNEL_T * ChP);
-static void sFlushTxFIFO(CHANNEL_T * ChP);
-static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
-static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
-static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
-static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
-static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
- ByteIO_t * AiopIOList, int AiopIOListSize,
- int IRQNum, Byte_t Frequency, int PeriodicOnly);
-static int sReadAiopID(ByteIO_t io);
-static int sReadAiopNumChan(WordIO_t io);
-
-MODULE_AUTHOR("Theodore Ts'o");
-MODULE_DESCRIPTION("Comtrol RocketPort driver");
-module_param_hw(board1, ulong, ioport, 0);
-MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
-module_param_hw(board2, ulong, ioport, 0);
-MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
-module_param_hw(board3, ulong, ioport, 0);
-MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
-module_param_hw(board4, ulong, ioport, 0);
-MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
-module_param_hw(controller, ulong, ioport, 0);
-MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
-module_param(support_low_speed, bool, 0);
-MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
-module_param(modem1, ulong, 0);
-MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
-module_param(modem2, ulong, 0);
-MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
-module_param(modem3, ulong, 0);
-MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
-module_param(modem4, ulong, 0);
-MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
-module_param_array(pc104_1, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
-module_param_array(pc104_2, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
-module_param_array(pc104_3, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
-module_param_array(pc104_4, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
-
-static int __init rp_init(void);
-static void rp_cleanup_module(void);
-
-module_init(rp_init);
-module_exit(rp_cleanup_module);
-
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*************************************************************************/
-/* Module code starts here */
-
-static inline int rocket_paranoia_check(struct r_port *info,
- const char *routine)
-{
-#ifdef ROCKET_PARANOIA_CHECK
- if (!info)
- return 1;
- if (info->magic != RPORT_MAGIC) {
- printk(KERN_WARNING "Warning: bad magic number for rocketport "
- "struct in %s\n", routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-
-/* Serial port receive data function. Called (from timer poll) when an AIOPIC signals
- * that receive data is present on a serial port. Pulls data from FIFO, moves it into the
- * tty layer.
- */
-static void rp_do_receive(struct r_port *info, CHANNEL_t *cp,
- unsigned int ChanStatus)
-{
- unsigned int CharNStat;
- int ToRecv, wRecv, space;
- unsigned char *cbuf;
-
- ToRecv = sGetRxCnt(cp);
-#ifdef ROCKET_DEBUG_INTR
- printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv);
-#endif
- if (ToRecv == 0)
- return;
-
- /*
- * if status indicates there are errored characters in the
- * FIFO, then enter status mode (a word in FIFO holds
- * character and status).
- */
- if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
- if (!(ChanStatus & STATMODE)) {
-#ifdef ROCKET_DEBUG_RECEIVE
- printk(KERN_INFO "Entering STATMODE...\n");
-#endif
- ChanStatus |= STATMODE;
- sEnRxStatusMode(cp);
- }
- }
-
- /*
- * if we previously entered status mode, then read down the
- * FIFO one word at a time, pulling apart the character and
- * the status. Update error counters depending on status
- */
- if (ChanStatus & STATMODE) {
-#ifdef ROCKET_DEBUG_RECEIVE
- printk(KERN_INFO "Ignore %x, read %x...\n",
- info->ignore_status_mask, info->read_status_mask);
-#endif
- while (ToRecv) {
- char flag;
-
- CharNStat = sInW(sGetTxRxDataIO(cp));
-#ifdef ROCKET_DEBUG_RECEIVE
- printk(KERN_INFO "%x...\n", CharNStat);
-#endif
- if (CharNStat & STMBREAKH)
- CharNStat &= ~(STMFRAMEH | STMPARITYH);
- if (CharNStat & info->ignore_status_mask) {
- ToRecv--;
- continue;
- }
- CharNStat &= info->read_status_mask;
- if (CharNStat & STMBREAKH)
- flag = TTY_BREAK;
- else if (CharNStat & STMPARITYH)
- flag = TTY_PARITY;
- else if (CharNStat & STMFRAMEH)
- flag = TTY_FRAME;
- else if (CharNStat & STMRCVROVRH)
- flag = TTY_OVERRUN;
- else
- flag = TTY_NORMAL;
- tty_insert_flip_char(&info->port, CharNStat & 0xff,
- flag);
- ToRecv--;
- }
-
- /*
- * after we've emptied the FIFO in status mode, turn
- * status mode back off
- */
- if (sGetRxCnt(cp) == 0) {
-#ifdef ROCKET_DEBUG_RECEIVE
- printk(KERN_INFO "Status mode off.\n");
-#endif
- sDisRxStatusMode(cp);
- }
- } else {
- /*
- * we aren't in status mode, so read down the FIFO two
- * characters at time by doing repeated word IO
- * transfer.
- */
- space = tty_prepare_flip_string(&info->port, &cbuf, ToRecv);
- if (space < ToRecv) {
-#ifdef ROCKET_DEBUG_RECEIVE
- printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
-#endif
- if (space <= 0)
- return;
- ToRecv = space;
- }
- wRecv = ToRecv >> 1;
- if (wRecv)
- sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
- if (ToRecv & 1)
- cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
- }
- /* Push the data up to the tty layer */
- tty_flip_buffer_push(&info->port);
-}
-
-/*
- * Serial port transmit data function. Called from the timer polling loop as a
- * result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
- * to be sent out the serial port. Data is buffered in rp_table[line].xmit_buf, it is
- * moved to the port's xmit FIFO. *info is critical data, protected by spinlocks.
- */
-static void rp_do_transmit(struct r_port *info)
-{
- int c;
- CHANNEL_t *cp = &info->channel;
- struct tty_struct *tty;
- unsigned long flags;
-
-#ifdef ROCKET_DEBUG_INTR
- printk(KERN_DEBUG "%s\n", __func__);
-#endif
- if (!info)
- return;
- tty = tty_port_tty_get(&info->port);
-
- if (tty == NULL) {
- printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__);
- clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
- return;
- }
-
- spin_lock_irqsave(&info->slock, flags);
- info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
- /* Loop sending data to FIFO until done or FIFO full */
- while (1) {
- if (tty->stopped)
- break;
- c = min(info->xmit_fifo_room, info->xmit_cnt);
- c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
- if (c <= 0 || info->xmit_fifo_room <= 0)
- break;
- sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
- if (c & 1)
- sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
- info->xmit_tail += c;
- info->xmit_tail &= XMIT_BUF_SIZE - 1;
- info->xmit_cnt -= c;
- info->xmit_fifo_room -= c;
-#ifdef ROCKET_DEBUG_INTR
- printk(KERN_INFO "tx %d chars...\n", c);
-#endif
- }
-
- if (info->xmit_cnt == 0)
- clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
- if (info->xmit_cnt < WAKEUP_CHARS) {
- tty_wakeup(tty);
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
- wake_up_interruptible(&tty->poll_wait);
-#endif
- }
-
- spin_unlock_irqrestore(&info->slock, flags);
- tty_kref_put(tty);
-
-#ifdef ROCKET_DEBUG_INTR
- printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head,
- info->xmit_tail, info->xmit_fifo_room);
-#endif
-}
-
-/*
- * Called when a serial port signals it has read data in it's RX FIFO.
- * It checks what interrupts are pending and services them, including
- * receiving serial data.
- */
-static void rp_handle_port(struct r_port *info)
-{
- CHANNEL_t *cp;
- unsigned int IntMask, ChanStatus;
-
- if (!info)
- return;
-
- if (!tty_port_initialized(&info->port)) {
- printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
- "info->flags & NOT_INIT\n");
- return;
- }
-
- cp = &info->channel;
-
- IntMask = sGetChanIntID(cp) & info->intmask;
-#ifdef ROCKET_DEBUG_INTR
- printk(KERN_INFO "rp_interrupt %02x...\n", IntMask);
-#endif
- ChanStatus = sGetChanStatus(cp);
- if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */
- rp_do_receive(info, cp, ChanStatus);
- }
- if (IntMask & DELTA_CD) { /* CD change */
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
- printk(KERN_INFO "ttyR%d CD now %s...\n", info->line,
- (ChanStatus & CD_ACT) ? "on" : "off");
-#endif
- if (!(ChanStatus & CD_ACT) && info->cd_status) {
-#ifdef ROCKET_DEBUG_HANGUP
- printk(KERN_INFO "CD drop, calling hangup.\n");
-#endif
- tty_port_tty_hangup(&info->port, false);
- }
- info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
- wake_up_interruptible(&info->port.open_wait);
- }
-#ifdef ROCKET_DEBUG_INTR
- if (IntMask & DELTA_CTS) { /* CTS change */
- printk(KERN_INFO "CTS change...\n");
- }
- if (IntMask & DELTA_DSR) { /* DSR change */
- printk(KERN_INFO "DSR change...\n");
- }
-#endif
-}
-
-/*
- * The top level polling routine. Repeats every 1/100 HZ (10ms).
- */
-static void rp_do_poll(struct timer_list *unused)
-{
- CONTROLLER_t *ctlp;
- int ctrl, aiop, ch, line;
- unsigned int xmitmask, i;
- unsigned int CtlMask;
- unsigned char AiopMask;
- Word_t bit;
-
- /* Walk through all the boards (ctrl's) */
- for (ctrl = 0; ctrl < max_board; ctrl++) {
- if (rcktpt_io_addr[ctrl] <= 0)
- continue;
-
- /* Get a ptr to the board's control struct */
- ctlp = sCtlNumToCtlPtr(ctrl);
-
- /* Get the interrupt status from the board */
-#ifdef CONFIG_PCI
- if (ctlp->BusType == isPCI)
- CtlMask = sPCIGetControllerIntStatus(ctlp);
- else
-#endif
- CtlMask = sGetControllerIntStatus(ctlp);
-
- /* Check if any AIOP read bits are set */
- for (aiop = 0; CtlMask; aiop++) {
- bit = ctlp->AiopIntrBits[aiop];
- if (CtlMask & bit) {
- CtlMask &= ~bit;
- AiopMask = sGetAiopIntStatus(ctlp, aiop);
-
- /* Check if any port read bits are set */
- for (ch = 0; AiopMask; AiopMask >>= 1, ch++) {
- if (AiopMask & 1) {
-
- /* Get the line number (/dev/ttyRx number). */
- /* Read the data from the port. */
- line = GetLineNumber(ctrl, aiop, ch);
- rp_handle_port(rp_table[line]);
- }
- }
- }
- }
-
- xmitmask = xmit_flags[ctrl];
-
- /*
- * xmit_flags contains bit-significant flags, indicating there is data
- * to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port
- * 1, ... (32 total possible). The variable i has the aiop and ch
- * numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
- */
- if (xmitmask) {
- for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
- if (xmitmask & (1 << i)) {
- aiop = (i & 0x18) >> 3;
- ch = i & 0x07;
- line = GetLineNumber(ctrl, aiop, ch);
- rp_do_transmit(rp_table[line]);
- }
- }
- }
- }
-
- /*
- * Reset the timer so we get called at the next clock tick (10ms).
- */
- if (atomic_read(&rp_num_ports_open))
- mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-}
-
-/*
- * Initializes the r_port structure for a port, as well as enabling the port on
- * the board.
- * Inputs: board, aiop, chan numbers
- */
-static void __init
-init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
-{
- unsigned rocketMode;
- struct r_port *info;
- int line;
- CONTROLLER_T *ctlp;
-
- /* Get the next available line number */
- line = SetLineNumber(board, aiop, chan);
-
- ctlp = sCtlNumToCtlPtr(board);
-
- /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
- info = kzalloc(sizeof (struct r_port), GFP_KERNEL);
- if (!info) {
- printk(KERN_ERR "Couldn't allocate info struct for line #%d\n",
- line);
- return;
- }
-
- info->magic = RPORT_MAGIC;
- info->line = line;
- info->ctlp = ctlp;
- info->board = board;
- info->aiop = aiop;
- info->chan = chan;
- tty_port_init(&info->port);
- info->port.ops = &rocket_port_ops;
- info->flags &= ~ROCKET_MODE_MASK;
- if (board < ARRAY_SIZE(pc104) && line < ARRAY_SIZE(pc104_1))
- switch (pc104[board][line]) {
- case 422:
- info->flags |= ROCKET_MODE_RS422;
- break;
- case 485:
- info->flags |= ROCKET_MODE_RS485;
- break;
- case 232:
- default:
- info->flags |= ROCKET_MODE_RS232;
- break;
- }
- else
- info->flags |= ROCKET_MODE_RS232;
-
- info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
- if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
- printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
- board, aiop, chan);
- tty_port_destroy(&info->port);
- kfree(info);
- return;
- }
-
- rocketMode = info->flags & ROCKET_MODE_MASK;
-
- if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
- sEnRTSToggle(&info->channel);
- else
- sDisRTSToggle(&info->channel);
-
- if (ctlp->boardType == ROCKET_TYPE_PC104) {
- switch (rocketMode) {
- case ROCKET_MODE_RS485:
- sSetInterfaceMode(&info->channel, InterfaceModeRS485);
- break;
- case ROCKET_MODE_RS422:
- sSetInterfaceMode(&info->channel, InterfaceModeRS422);
- break;
- case ROCKET_MODE_RS232:
- default:
- if (info->flags & ROCKET_RTS_TOGGLE)
- sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
- else
- sSetInterfaceMode(&info->channel, InterfaceModeRS232);
- break;
- }
- }
- spin_lock_init(&info->slock);
- mutex_init(&info->write_mtx);
- rp_table[line] = info;
- tty_port_register_device(&info->port, rocket_driver, line,
- pci_dev ? &pci_dev->dev : NULL);
-}
-
-/*
- * Configures a rocketport port according to its termio settings. Called from
- * user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
- */
-static void configure_r_port(struct tty_struct *tty, struct r_port *info,
- struct ktermios *old_termios)
-{
- unsigned cflag;
- unsigned long flags;
- unsigned rocketMode;
- int bits, baud, divisor;
- CHANNEL_t *cp;
- struct ktermios *t = &tty->termios;
-
- cp = &info->channel;
- cflag = t->c_cflag;
-
- /* Byte size and parity */
- if ((cflag & CSIZE) == CS8) {
- sSetData8(cp);
- bits = 10;
- } else {
- sSetData7(cp);
- bits = 9;
- }
- if (cflag & CSTOPB) {
- sSetStop2(cp);
- bits++;
- } else {
- sSetStop1(cp);
- }
-
- if (cflag & PARENB) {
- sEnParity(cp);
- bits++;
- if (cflag & PARODD) {
- sSetOddParity(cp);
- } else {
- sSetEvenParity(cp);
- }
- } else {
- sDisParity(cp);
- }
-
- /* baud rate */
- baud = tty_get_baud_rate(tty);
- if (!baud)
- baud = 9600;
- divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
- if ((divisor >= 8192 || divisor < 0) && old_termios) {
- baud = tty_termios_baud_rate(old_termios);
- if (!baud)
- baud = 9600;
- divisor = (rp_baud_base[info->board] / baud) - 1;
- }
- if (divisor >= 8192 || divisor < 0) {
- baud = 9600;
- divisor = (rp_baud_base[info->board] / baud) - 1;
- }
- info->cps = baud / bits;
- sSetBaud(cp, divisor);
-
- /* FIXME: Should really back compute a baud rate from the divisor */
- tty_encode_baud_rate(tty, baud, baud);
-
- if (cflag & CRTSCTS) {
- info->intmask |= DELTA_CTS;
- sEnCTSFlowCtl(cp);
- } else {
- info->intmask &= ~DELTA_CTS;
- sDisCTSFlowCtl(cp);
- }
- if (cflag & CLOCAL) {
- info->intmask &= ~DELTA_CD;
- } else {
- spin_lock_irqsave(&info->slock, flags);
- if (sGetChanStatus(cp) & CD_ACT)
- info->cd_status = 1;
- else
- info->cd_status = 0;
- info->intmask |= DELTA_CD;
- spin_unlock_irqrestore(&info->slock, flags);
- }
-
- /*
- * Handle software flow control in the board
- */
-#ifdef ROCKET_SOFT_FLOW
- if (I_IXON(tty)) {
- sEnTxSoftFlowCtl(cp);
- if (I_IXANY(tty)) {
- sEnIXANY(cp);
- } else {
- sDisIXANY(cp);
- }
- sSetTxXONChar(cp, START_CHAR(tty));
- sSetTxXOFFChar(cp, STOP_CHAR(tty));
- } else {
- sDisTxSoftFlowCtl(cp);
- sDisIXANY(cp);
- sClrTxXOFF(cp);
- }
-#endif
-
- /*
- * Set up ignore/read mask words
- */
- info->read_status_mask = STMRCVROVRH | 0xFF;
- if (I_INPCK(tty))
- info->read_status_mask |= STMFRAMEH | STMPARITYH;
- if (I_BRKINT(tty) || I_PARMRK(tty))
- info->read_status_mask |= STMBREAKH;
-
- /*
- * Characters to ignore
- */
- info->ignore_status_mask = 0;
- if (I_IGNPAR(tty))
- info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
- if (I_IGNBRK(tty)) {
- info->ignore_status_mask |= STMBREAKH;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too. (For real raw support).
- */
- if (I_IGNPAR(tty))
- info->ignore_status_mask |= STMRCVROVRH;
- }
-
- rocketMode = info->flags & ROCKET_MODE_MASK;
-
- if ((info->flags & ROCKET_RTS_TOGGLE)
- || (rocketMode == ROCKET_MODE_RS485))
- sEnRTSToggle(cp);
- else
- sDisRTSToggle(cp);
-
- sSetRTS(&info->channel);
-
- if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
- switch (rocketMode) {
- case ROCKET_MODE_RS485:
- sSetInterfaceMode(cp, InterfaceModeRS485);
- break;
- case ROCKET_MODE_RS422:
- sSetInterfaceMode(cp, InterfaceModeRS422);
- break;
- case ROCKET_MODE_RS232:
- default:
- if (info->flags & ROCKET_RTS_TOGGLE)
- sSetInterfaceMode(cp, InterfaceModeRS232T);
- else
- sSetInterfaceMode(cp, InterfaceModeRS232);
- break;
- }
- }
-}
-
-static int carrier_raised(struct tty_port *port)
-{
- struct r_port *info = container_of(port, struct r_port, port);
- return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
-}
-
-static void dtr_rts(struct tty_port *port, int on)
-{
- struct r_port *info = container_of(port, struct r_port, port);
- if (on) {
- sSetDTR(&info->channel);
- sSetRTS(&info->channel);
- } else {
- sClrDTR(&info->channel);
- sClrRTS(&info->channel);
- }
-}
-
-/*
- * Exception handler that opens a serial port. Creates xmit_buf storage, fills in
- * port's r_port struct. Initializes the port hardware.
- */
-static int rp_open(struct tty_struct *tty, struct file *filp)
-{
- struct r_port *info;
- struct tty_port *port;
- int retval;
- CHANNEL_t *cp;
- unsigned long page;
-
- info = rp_table[tty->index];
- if (info == NULL)
- return -ENXIO;
- port = &info->port;
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- /*
- * We must not sleep from here until the port is marked fully in use.
- */
- if (info->xmit_buf)
- free_page(page);
- else
- info->xmit_buf = (unsigned char *) page;
-
- tty->driver_data = info;
- tty_port_tty_set(port, tty);
-
- if (port->count++ == 0) {
- atomic_inc(&rp_num_ports_open);
-
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "rocket mod++ = %d...\n",
- atomic_read(&rp_num_ports_open));
-#endif
- }
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count);
-#endif
-
- /*
- * Info->count is now 1; so it's safe to sleep now.
- */
- if (!tty_port_initialized(port)) {
- cp = &info->channel;
- sSetRxTrigger(cp, TRIG_1);
- if (sGetChanStatus(cp) & CD_ACT)
- info->cd_status = 1;
- else
- info->cd_status = 0;
- sDisRxStatusMode(cp);
- sFlushRxFIFO(cp);
- sFlushTxFIFO(cp);
-
- sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
- sSetRxTrigger(cp, TRIG_1);
-
- sGetChanStatus(cp);
- sDisRxStatusMode(cp);
- sClrTxXOFF(cp);
-
- sDisCTSFlowCtl(cp);
- sDisTxSoftFlowCtl(cp);
-
- sEnRxFIFO(cp);
- sEnTransmit(cp);
-
- tty_port_set_initialized(&info->port, 1);
-
- configure_r_port(tty, info, NULL);
- if (C_BAUD(tty)) {
- sSetDTR(cp);
- sSetRTS(cp);
- }
- }
- /* Starts (or resets) the maint polling loop */
- mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-
- retval = tty_port_block_til_ready(port, tty, filp);
- if (retval) {
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
-#endif
- return retval;
- }
- return 0;
-}
-
-/*
- * Exception handler that closes a serial port. info->port.count is considered critical.
- */
-static void rp_close(struct tty_struct *tty, struct file *filp)
-{
- struct r_port *info = tty->driver_data;
- struct tty_port *port = &info->port;
- int timeout;
- CHANNEL_t *cp;
-
- if (rocket_paranoia_check(info, "rp_close"))
- return;
-
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count);
-#endif
-
- if (tty_port_close_start(port, tty, filp) == 0)
- return;
-
- mutex_lock(&port->mutex);
- cp = &info->channel;
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
- if (timeout == 0)
- timeout = 1;
- rp_wait_until_sent(tty, timeout);
- clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
- sDisTransmit(cp);
- sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
- sDisCTSFlowCtl(cp);
- sDisTxSoftFlowCtl(cp);
- sClrTxXOFF(cp);
- sFlushRxFIFO(cp);
- sFlushTxFIFO(cp);
- sClrRTS(cp);
- if (C_HUPCL(tty))
- sClrDTR(cp);
-
- rp_flush_buffer(tty);
-
- tty_ldisc_flush(tty);
-
- clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
- /* We can't yet use tty_port_close_end as the buffer handling in this
- driver is a bit different to the usual */
-
- if (port->blocked_open) {
- if (port->close_delay) {
- msleep_interruptible(jiffies_to_msecs(port->close_delay));
- }
- wake_up_interruptible(&port->open_wait);
- } else {
- if (info->xmit_buf) {
- free_page((unsigned long) info->xmit_buf);
- info->xmit_buf = NULL;
- }
- }
- spin_lock_irq(&port->lock);
- tty->closing = 0;
- spin_unlock_irq(&port->lock);
- tty_port_set_initialized(port, 0);
- tty_port_set_active(port, 0);
- mutex_unlock(&port->mutex);
- tty_port_tty_set(port, NULL);
-
- atomic_dec(&rp_num_ports_open);
-
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "rocket mod-- = %d...\n",
- atomic_read(&rp_num_ports_open));
- printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
-#endif
-
-}
-
-static void rp_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios)
-{
- struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
- unsigned cflag;
-
- if (rocket_paranoia_check(info, "rp_set_termios"))
- return;
-
- cflag = tty->termios.c_cflag;
-
- /*
- * This driver doesn't support CS5 or CS6
- */
- if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
- tty->termios.c_cflag =
- ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
- /* Or CMSPAR */
- tty->termios.c_cflag &= ~CMSPAR;
-
- configure_r_port(tty, info, old_termios);
-
- cp = &info->channel;
-
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) {
- sClrDTR(cp);
- sClrRTS(cp);
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) {
- sSetRTS(cp);
- sSetDTR(cp);
- }
-
- if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty))
- rp_start(tty);
-}
-
-static int rp_break(struct tty_struct *tty, int break_state)
-{
- struct r_port *info = tty->driver_data;
- unsigned long flags;
-
- if (rocket_paranoia_check(info, "rp_break"))
- return -EINVAL;
-
- spin_lock_irqsave(&info->slock, flags);
- if (break_state == -1)
- sSendBreak(&info->channel);
- else
- sClrBreak(&info->channel);
- spin_unlock_irqrestore(&info->slock, flags);
- return 0;
-}
-
-/*
- * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
- * the UPCI boards was added, it was decided to make this a function because
- * the macro was getting too complicated. All cases except the first one
- * (UPCIRingInd) are taken directly from the original macro.
- */
-static int sGetChanRI(CHANNEL_T * ChP)
-{
- CONTROLLER_t *CtlP = ChP->CtlP;
- int ChanNum = ChP->ChanNum;
- int RingInd = 0;
-
- if (CtlP->UPCIRingInd)
- RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
- else if (CtlP->AltChanRingIndicator)
- RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
- else if (CtlP->boardType == ROCKET_TYPE_PC104)
- RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
-
- return RingInd;
-}
-
-/********************************************************************************************/
-/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */
-
-/*
- * Returns the state of the serial modem control lines. These next 2 functions
- * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
- */
-static int rp_tiocmget(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
- unsigned int control, result, ChanStatus;
-
- ChanStatus = sGetChanStatusLo(&info->channel);
- control = info->channel.TxControl[3];
- result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
- ((control & SET_DTR) ? TIOCM_DTR : 0) |
- ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
- (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
- ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
- ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
-
- return result;
-}
-
-/*
- * Sets the modem control lines
- */
-static int rp_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
- struct r_port *info = tty->driver_data;
-
- if (set & TIOCM_RTS)
- info->channel.TxControl[3] |= SET_RTS;
- if (set & TIOCM_DTR)
- info->channel.TxControl[3] |= SET_DTR;
- if (clear & TIOCM_RTS)
- info->channel.TxControl[3] &= ~SET_RTS;
- if (clear & TIOCM_DTR)
- info->channel.TxControl[3] &= ~SET_DTR;
-
- out32(info->channel.IndexAddr, info->channel.TxControl);
- return 0;
-}
-
-static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
-{
- struct rocket_config tmp;
-
- memset(&tmp, 0, sizeof (tmp));
- mutex_lock(&info->port.mutex);
- tmp.line = info->line;
- tmp.flags = info->flags;
- tmp.close_delay = info->port.close_delay;
- tmp.closing_wait = info->port.closing_wait;
- tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
- mutex_unlock(&info->port.mutex);
-
- if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
- return -EFAULT;
- return 0;
-}
-
-static int set_config(struct tty_struct *tty, struct r_port *info,
- struct rocket_config __user *new_info)
-{
- struct rocket_config new_serial;
-
- if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
- return -EFAULT;
-
- mutex_lock(&info->port.mutex);
- if (!capable(CAP_SYS_ADMIN))
- {
- if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) {
- mutex_unlock(&info->port.mutex);
- return -EPERM;
- }
- info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
- mutex_unlock(&info->port.mutex);
- return 0;
- }
-
- if ((new_serial.flags ^ info->flags) & ROCKET_SPD_MASK) {
- /* warn about deprecation, unless clearing */
- if (new_serial.flags & ROCKET_SPD_MASK)
- dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
- }
-
- info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
- info->port.close_delay = new_serial.close_delay;
- info->port.closing_wait = new_serial.closing_wait;
-
- mutex_unlock(&info->port.mutex);
-
- configure_r_port(tty, info, NULL);
- return 0;
-}
-
-/*
- * This function fills in a rocket_ports struct with information
- * about what boards/ports are in the system. This info is passed
- * to user space. See setrocket.c where the info is used to create
- * the /dev/ttyRx ports.
- */
-static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
-{
- struct rocket_ports *tmp;
- int board, ret = 0;
-
- tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
- if (!tmp)
- return -ENOMEM;
-
- tmp->tty_major = rocket_driver->major;
-
- for (board = 0; board < 4; board++) {
- tmp->rocketModel[board].model = rocketModel[board].model;
- strcpy(tmp->rocketModel[board].modelString,
- rocketModel[board].modelString);
- tmp->rocketModel[board].numPorts = rocketModel[board].numPorts;
- tmp->rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
- tmp->rocketModel[board].startingPortNumber =
- rocketModel[board].startingPortNumber;
- }
- if (copy_to_user(retports, tmp, sizeof(*retports)))
- ret = -EFAULT;
- kfree(tmp);
- return ret;
-}
-
-static int reset_rm2(struct r_port *info, void __user *arg)
-{
- int reset;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if (copy_from_user(&reset, arg, sizeof (int)))
- return -EFAULT;
- if (reset)
- reset = 1;
-
- if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
- rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
- return -EINVAL;
-
- if (info->ctlp->BusType == isISA)
- sModemReset(info->ctlp, info->chan, reset);
- else
- sPCIModemReset(info->ctlp, info->chan, reset);
-
- return 0;
-}
-
-static int get_version(struct r_port *info, struct rocket_version __user *retvers)
-{
- if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
- return -EFAULT;
- return 0;
-}
-
-/* IOCTL call handler into the driver */
-static int rp_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg)
-{
- struct r_port *info = tty->driver_data;
- void __user *argp = (void __user *)arg;
- int ret = 0;
-
- if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
- return -ENXIO;
-
- switch (cmd) {
- case RCKP_GET_CONFIG:
- dev_warn_ratelimited(tty->dev,
- "RCKP_GET_CONFIG option is deprecated\n");
- ret = get_config(info, argp);
- break;
- case RCKP_SET_CONFIG:
- dev_warn_ratelimited(tty->dev,
- "RCKP_SET_CONFIG option is deprecated\n");
- ret = set_config(tty, info, argp);
- break;
- case RCKP_GET_PORTS:
- dev_warn_ratelimited(tty->dev,
- "RCKP_GET_PORTS option is deprecated\n");
- ret = get_ports(info, argp);
- break;
- case RCKP_RESET_RM2:
- dev_warn_ratelimited(tty->dev,
- "RCKP_RESET_RM2 option is deprecated\n");
- ret = reset_rm2(info, argp);
- break;
- case RCKP_GET_VERSION:
- dev_warn_ratelimited(tty->dev,
- "RCKP_GET_VERSION option is deprecated\n");
- ret = get_version(info, argp);
- break;
- default:
- ret = -ENOIOCTLCMD;
- }
- return ret;
-}
-
-static void rp_send_xchar(struct tty_struct *tty, char ch)
-{
- struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
-
- if (rocket_paranoia_check(info, "rp_send_xchar"))
- return;
-
- cp = &info->channel;
- if (sGetTxCnt(cp))
- sWriteTxPrioByte(cp, ch);
- else
- sWriteTxByte(sGetTxRxDataIO(cp), ch);
-}
-
-static void rp_throttle(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_THROTTLE
- printk(KERN_INFO "throttle %s ....\n", tty->name);
-#endif
-
- if (rocket_paranoia_check(info, "rp_throttle"))
- return;
-
- if (I_IXOFF(tty))
- rp_send_xchar(tty, STOP_CHAR(tty));
-
- sClrRTS(&info->channel);
-}
-
-static void rp_unthrottle(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
-#ifdef ROCKET_DEBUG_THROTTLE
- printk(KERN_INFO "unthrottle %s ....\n", tty->name);
-#endif
-
- if (rocket_paranoia_check(info, "rp_unthrottle"))
- return;
-
- if (I_IXOFF(tty))
- rp_send_xchar(tty, START_CHAR(tty));
-
- sSetRTS(&info->channel);
-}
-
-/*
- * ------------------------------------------------------------
- * rp_stop() and rp_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rp_stop(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_FLOW
- printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
- info->xmit_cnt, info->xmit_fifo_room);
-#endif
-
- if (rocket_paranoia_check(info, "rp_stop"))
- return;
-
- if (sGetTxCnt(&info->channel))
- sDisTransmit(&info->channel);
-}
-
-static void rp_start(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_FLOW
- printk(KERN_INFO "start %s: %d %d....\n", tty->name,
- info->xmit_cnt, info->xmit_fifo_room);
-#endif
-
- if (rocket_paranoia_check(info, "rp_stop"))
- return;
-
- sEnTransmit(&info->channel);
- set_bit((info->aiop * 8) + info->chan,
- (void *) &xmit_flags[info->board]);
-}
-
-/*
- * rp_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
- unsigned long orig_jiffies;
- int check_time, exit_time;
- int txcnt;
-
- if (rocket_paranoia_check(info, "rp_wait_until_sent"))
- return;
-
- cp = &info->channel;
-
- orig_jiffies = jiffies;
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
- printk(KERN_INFO "In %s(%d) (jiff=%lu)...\n", __func__, timeout,
- jiffies);
- printk(KERN_INFO "cps=%d...\n", info->cps);
-#endif
- while (1) {
- txcnt = sGetTxCnt(cp);
- if (!txcnt) {
- if (sGetChanStatusLo(cp) & TXSHRMT)
- break;
- check_time = (HZ / info->cps) / 5;
- } else {
- check_time = HZ * txcnt / info->cps;
- }
- if (timeout) {
- exit_time = orig_jiffies + timeout - jiffies;
- if (exit_time <= 0)
- break;
- if (exit_time < check_time)
- check_time = exit_time;
- }
- if (check_time == 0)
- check_time = 1;
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
- printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt,
- jiffies, check_time);
-#endif
- msleep_interruptible(jiffies_to_msecs(check_time));
- if (signal_pending(current))
- break;
- }
- __set_current_state(TASK_RUNNING);
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
- printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
-#endif
-}
-
-/*
- * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rp_hangup(struct tty_struct *tty)
-{
- CHANNEL_t *cp;
- struct r_port *info = tty->driver_data;
- unsigned long flags;
-
- if (rocket_paranoia_check(info, "rp_hangup"))
- return;
-
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
- printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
-#endif
- rp_flush_buffer(tty);
- spin_lock_irqsave(&info->port.lock, flags);
- if (info->port.count)
- atomic_dec(&rp_num_ports_open);
- clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
- spin_unlock_irqrestore(&info->port.lock, flags);
-
- tty_port_hangup(&info->port);
-
- cp = &info->channel;
- sDisRxFIFO(cp);
- sDisTransmit(cp);
- sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
- sDisCTSFlowCtl(cp);
- sDisTxSoftFlowCtl(cp);
- sClrTxXOFF(cp);
- tty_port_set_initialized(&info->port, 0);
-
- wake_up_interruptible(&info->port.open_wait);
-}
-
-/*
- * Exception handler - write char routine. The RocketPort driver uses a
- * double-buffering strategy, with the twist that if the in-memory CPU
- * buffer is empty, and there's space in the transmit FIFO, the
- * writing routines will write directly to transmit FIFO.
- * Write buffer and counters protected by spinlocks
- */
-static int rp_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
- unsigned long flags;
-
- if (rocket_paranoia_check(info, "rp_put_char"))
- return 0;
-
- /*
- * Grab the port write mutex, locking out other processes that try to
- * write to this port
- */
- mutex_lock(&info->write_mtx);
-
-#ifdef ROCKET_DEBUG_WRITE
- printk(KERN_INFO "rp_put_char %c...\n", ch);
-#endif
-
- spin_lock_irqsave(&info->slock, flags);
- cp = &info->channel;
-
- if (!tty->stopped && info->xmit_fifo_room == 0)
- info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
- if (tty->stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
- info->xmit_buf[info->xmit_head++] = ch;
- info->xmit_head &= XMIT_BUF_SIZE - 1;
- info->xmit_cnt++;
- set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
- } else {
- sOutB(sGetTxRxDataIO(cp), ch);
- info->xmit_fifo_room--;
- }
- spin_unlock_irqrestore(&info->slock, flags);
- mutex_unlock(&info->write_mtx);
- return 1;
-}
-
-/*
- * Exception handler - write routine, called when user app writes to the device.
- * A per port write mutex is used to protect from another process writing to
- * this port at the same time. This other process could be running on the other CPU
- * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out).
- * Spinlocks protect the info xmit members.
- */
-static int rp_write(struct tty_struct *tty,
- const unsigned char *buf, int count)
-{
- struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
- const unsigned char *b;
- int c, retval = 0;
- unsigned long flags;
-
- if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
- return 0;
-
- if (mutex_lock_interruptible(&info->write_mtx))
- return -ERESTARTSYS;
-
-#ifdef ROCKET_DEBUG_WRITE
- printk(KERN_INFO "rp_write %d chars...\n", count);
-#endif
- cp = &info->channel;
-
- if (!tty->stopped && info->xmit_fifo_room < count)
- info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
- /*
- * If the write queue for the port is empty, and there is FIFO space, stuff bytes
- * into FIFO. Use the write queue for temp storage.
- */
- if (!tty->stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
- c = min(count, info->xmit_fifo_room);
- b = buf;
-
- /* Push data into FIFO, 2 bytes at a time */
- sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
-
- /* If there is a byte remaining, write it */
- if (c & 1)
- sOutB(sGetTxRxDataIO(cp), b[c - 1]);
-
- retval += c;
- buf += c;
- count -= c;
-
- spin_lock_irqsave(&info->slock, flags);
- info->xmit_fifo_room -= c;
- spin_unlock_irqrestore(&info->slock, flags);
- }
-
- /* If count is zero, we wrote it all and are done */
- if (!count)
- goto end;
-
- /* Write remaining data into the port's xmit_buf */
- while (1) {
- /* Hung up ? */
- if (!tty_port_active(&info->port))
- goto end;
- c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
- c = min(c, XMIT_BUF_SIZE - info->xmit_head);
- if (c <= 0)
- break;
-
- b = buf;
- memcpy(info->xmit_buf + info->xmit_head, b, c);
-
- spin_lock_irqsave(&info->slock, flags);
- info->xmit_head =
- (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
- info->xmit_cnt += c;
- spin_unlock_irqrestore(&info->slock, flags);
-
- buf += c;
- count -= c;
- retval += c;
- }
-
- if ((retval > 0) && !tty->stopped)
- set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-end:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- tty_wakeup(tty);
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
- wake_up_interruptible(&tty->poll_wait);
-#endif
- }
- mutex_unlock(&info->write_mtx);
- return retval;
-}
-
-/*
- * Return the number of characters that can be sent. We estimate
- * only using the in-memory transmit buffer only, and ignore the
- * potential space in the transmit FIFO.
- */
-static int rp_write_room(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
- int ret;
-
- if (rocket_paranoia_check(info, "rp_write_room"))
- return 0;
-
- ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
- if (ret < 0)
- ret = 0;
-#ifdef ROCKET_DEBUG_WRITE
- printk(KERN_INFO "rp_write_room returns %d...\n", ret);
-#endif
- return ret;
-}
-
-/*
- * Return the number of characters in the buffer. Again, this only
- * counts those characters in the in-memory transmit buffer.
- */
-static int rp_chars_in_buffer(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
-
- if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
- return 0;
-
-#ifdef ROCKET_DEBUG_WRITE
- printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
-#endif
- return info->xmit_cnt;
-}
-
-/*
- * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
- * r_port struct for the port. Note that spinlock are used to protect info members,
- * do not call this function if the spinlock is already held.
- */
-static void rp_flush_buffer(struct tty_struct *tty)
-{
- struct r_port *info = tty->driver_data;
- CHANNEL_t *cp;
- unsigned long flags;
-
- if (rocket_paranoia_check(info, "rp_flush_buffer"))
- return;
-
- spin_lock_irqsave(&info->slock, flags);
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- spin_unlock_irqrestore(&info->slock, flags);
-
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
- wake_up_interruptible(&tty->poll_wait);
-#endif
- tty_wakeup(tty);
-
- cp = &info->channel;
- sFlushTxFIFO(cp);
-}
-
-#ifdef CONFIG_PCI
-
-static const struct pci_device_id rocket_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4QUAD) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8OCTA) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8OCTA) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP8INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8J) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4J) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP8SNI) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP16SNI) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP16INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP16INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_CRP16INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP32INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_URP32INTF) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RPP4) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RPP8) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP2_232) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP2_422) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP6M) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_RP4M) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_UPCI_RM3_8PORT) },
- { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_DEVICE_ID_UPCI_RM3_4PORT) },
- { }
-};
-MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
-
-/* Resets the speaker controller on RocketModem II and III devices */
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
-{
- ByteIO_t addr;
-
- /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
- if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
- addr = CtlP->AiopIO[0] + 0x4F;
- sOutB(addr, 0);
- }
-
- /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
- if ((model == MODEL_UPCI_RM3_8PORT)
- || (model == MODEL_UPCI_RM3_4PORT)) {
- addr = CtlP->AiopIO[0] + 0x88;
- sOutB(addr, 0);
- }
-}
-
-/***************************************************************************
-Function: sPCIInitController
-Purpose: Initialization of controller global registers and controller
- structure.
-Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
- IRQNum,Frequency,PeriodicOnly)
- CONTROLLER_T *CtlP; Ptr to controller structure
- int CtlNum; Controller number
- ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
- This list must be in the order the AIOPs will be found on the
- controller. Once an AIOP in the list is not found, it is
- assumed that there are no more AIOPs on the controller.
- int AiopIOListSize; Number of addresses in AiopIOList
- int IRQNum; Interrupt Request number. Can be any of the following:
- 0: Disable global interrupts
- 3: IRQ 3
- 4: IRQ 4
- 5: IRQ 5
- 9: IRQ 9
- 10: IRQ 10
- 11: IRQ 11
- 12: IRQ 12
- 15: IRQ 15
- Byte_t Frequency: A flag identifying the frequency
- of the periodic interrupt, can be any one of the following:
- FREQ_DIS - periodic interrupt disabled
- FREQ_137HZ - 137 Hertz
- FREQ_69HZ - 69 Hertz
- FREQ_34HZ - 34 Hertz
- FREQ_17HZ - 17 Hertz
- FREQ_9HZ - 9 Hertz
- FREQ_4HZ - 4 Hertz
- If IRQNum is set to 0 the Frequency parameter is
- overidden, it is forced to a value of FREQ_DIS.
- int PeriodicOnly: 1 if all interrupts except the periodic
- interrupt are to be blocked.
- 0 is both the periodic interrupt and
- other channel interrupts are allowed.
- If IRQNum is set to 0 the PeriodicOnly parameter is
- overidden, it is forced to a value of 0.
-Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
- initialization failed.
-
-Comments:
- If periodic interrupts are to be disabled but AIOP interrupts
- are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
- If interrupts are to be completely disabled set IRQNum to 0.
-
- Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
- invalid combination.
-
- This function performs initialization of global interrupt modes,
- but it does not actually enable global interrupts. To enable
- and disable global interrupts use functions sEnGlobalInt() and
- sDisGlobalInt(). Enabling of global interrupts is normally not
- done until all other initializations are complete.
-
- Even if interrupts are globally enabled, they must also be
- individually enabled for each channel that is to generate
- interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
- No context switches are allowed while executing this function.
-
- After this function all AIOPs on the controller are disabled,
- they can be enabled with sEnAiop().
-*/
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
- ByteIO_t * AiopIOList, int AiopIOListSize,
- WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
- int PeriodicOnly, int altChanRingIndicator,
- int UPCIRingInd)
-{
- int i;
- ByteIO_t io;
-
- CtlP->AltChanRingIndicator = altChanRingIndicator;
- CtlP->UPCIRingInd = UPCIRingInd;
- CtlP->CtlNum = CtlNum;
- CtlP->CtlID = CTLID_0001; /* controller release 1 */
- CtlP->BusType = isPCI; /* controller release 1 */
-
- if (ConfigIO) {
- CtlP->isUPCI = 1;
- CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
- CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
- CtlP->AiopIntrBits = upci_aiop_intr_bits;
- } else {
- CtlP->isUPCI = 0;
- CtlP->PCIIO =
- (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
- CtlP->AiopIntrBits = aiop_intr_bits;
- }
-
- sPCIControllerEOI(CtlP); /* clear EOI if warm init */
- /* Init AIOPs */
- CtlP->NumAiop = 0;
- for (i = 0; i < AiopIOListSize; i++) {
- io = AiopIOList[i];
- CtlP->AiopIO[i] = (WordIO_t) io;
- CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-
- CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
- if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
- break; /* done looking for AIOPs */
-
- CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
- sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
- sOutB(io + _INDX_DATA, sClockPrescale);
- CtlP->NumAiop++; /* bump count of AIOPs */
- }
-
- if (CtlP->NumAiop == 0)
- return (-1);
- else
- return (CtlP->NumAiop);
-}
-
-/*
- * Called when a PCI card is found. Retrieves and stores model information,
- * init's aiopic and serial port hardware.
- * Inputs: i is the board number (0-n)
- */
-static __init int register_PCI(int i, struct pci_dev *dev)
-{
- int num_aiops, aiop, max_num_aiops, chan;
- unsigned int aiopio[MAX_AIOPS_PER_BOARD];
- CONTROLLER_t *ctlp;
-
- int fast_clock = 0;
- int altChanRingIndicator = 0;
- int ports_per_aiop = 8;
- WordIO_t ConfigIO = 0;
- ByteIO_t UPCIRingInd = 0;
-
- if (!dev || !pci_match_id(rocket_pci_ids, dev) ||
- pci_enable_device(dev) || i >= NUM_BOARDS)
- return 0;
-
- rcktpt_io_addr[i] = pci_resource_start(dev, 0);
-
- rcktpt_type[i] = ROCKET_TYPE_NORMAL;
- rocketModel[i].loadrm2 = 0;
- rocketModel[i].startingPortNumber = nextLineNumber;
-
- /* Depending on the model, set up some config variables */
- switch (dev->device) {
- case PCI_DEVICE_ID_RP4QUAD:
- max_num_aiops = 1;
- ports_per_aiop = 4;
- rocketModel[i].model = MODEL_RP4QUAD;
- strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
- rocketModel[i].numPorts = 4;
- break;
- case PCI_DEVICE_ID_RP8OCTA:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_RP8OCTA;
- strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_URP8OCTA:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_UPCI_RP8OCTA;
- strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_RP8INTF:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_RP8INTF;
- strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_URP8INTF:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_UPCI_RP8INTF;
- strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_RP8J:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_RP8J;
- strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_RP4J:
- max_num_aiops = 1;
- ports_per_aiop = 4;
- rocketModel[i].model = MODEL_RP4J;
- strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
- rocketModel[i].numPorts = 4;
- break;
- case PCI_DEVICE_ID_RP8SNI:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_RP8SNI;
- strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_RP16SNI:
- max_num_aiops = 2;
- rocketModel[i].model = MODEL_RP16SNI;
- strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
- rocketModel[i].numPorts = 16;
- break;
- case PCI_DEVICE_ID_RP16INTF:
- max_num_aiops = 2;
- rocketModel[i].model = MODEL_RP16INTF;
- strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
- rocketModel[i].numPorts = 16;
- break;
- case PCI_DEVICE_ID_URP16INTF:
- max_num_aiops = 2;
- rocketModel[i].model = MODEL_UPCI_RP16INTF;
- strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
- rocketModel[i].numPorts = 16;
- break;
- case PCI_DEVICE_ID_CRP16INTF:
- max_num_aiops = 2;
- rocketModel[i].model = MODEL_CPCI_RP16INTF;
- strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
- rocketModel[i].numPorts = 16;
- break;
- case PCI_DEVICE_ID_RP32INTF:
- max_num_aiops = 4;
- rocketModel[i].model = MODEL_RP32INTF;
- strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
- rocketModel[i].numPorts = 32;
- break;
- case PCI_DEVICE_ID_URP32INTF:
- max_num_aiops = 4;
- rocketModel[i].model = MODEL_UPCI_RP32INTF;
- strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
- rocketModel[i].numPorts = 32;
- break;
- case PCI_DEVICE_ID_RPP4:
- max_num_aiops = 1;
- ports_per_aiop = 4;
- altChanRingIndicator++;
- fast_clock++;
- rocketModel[i].model = MODEL_RPP4;
- strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
- rocketModel[i].numPorts = 4;
- break;
- case PCI_DEVICE_ID_RPP8:
- max_num_aiops = 2;
- ports_per_aiop = 4;
- altChanRingIndicator++;
- fast_clock++;
- rocketModel[i].model = MODEL_RPP8;
- strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
- rocketModel[i].numPorts = 8;
- break;
- case PCI_DEVICE_ID_RP2_232:
- max_num_aiops = 1;
- ports_per_aiop = 2;
- altChanRingIndicator++;
- fast_clock++;
- rocketModel[i].model = MODEL_RP2_232;
- strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
- rocketModel[i].numPorts = 2;
- break;
- case PCI_DEVICE_ID_RP2_422:
- max_num_aiops = 1;
- ports_per_aiop = 2;
- altChanRingIndicator++;
- fast_clock++;
- rocketModel[i].model = MODEL_RP2_422;
- strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
- rocketModel[i].numPorts = 2;
- break;
- case PCI_DEVICE_ID_RP6M:
-
- max_num_aiops = 1;
- ports_per_aiop = 6;
-
- /* If revision is 1, the rocketmodem flash must be loaded.
- * If it is 2 it is a "socketed" version. */
- if (dev->revision == 1) {
- rcktpt_type[i] = ROCKET_TYPE_MODEMII;
- rocketModel[i].loadrm2 = 1;
- } else {
- rcktpt_type[i] = ROCKET_TYPE_MODEM;
- }
-
- rocketModel[i].model = MODEL_RP6M;
- strcpy(rocketModel[i].modelString, "RocketModem 6 port");
- rocketModel[i].numPorts = 6;
- break;
- case PCI_DEVICE_ID_RP4M:
- max_num_aiops = 1;
- ports_per_aiop = 4;
- if (dev->revision == 1) {
- rcktpt_type[i] = ROCKET_TYPE_MODEMII;
- rocketModel[i].loadrm2 = 1;
- } else {
- rcktpt_type[i] = ROCKET_TYPE_MODEM;
- }
-
- rocketModel[i].model = MODEL_RP4M;
- strcpy(rocketModel[i].modelString, "RocketModem 4 port");
- rocketModel[i].numPorts = 4;
- break;
- default:
- max_num_aiops = 0;
- break;
- }
-
- /*
- * Check for UPCI boards.
- */
-
- switch (dev->device) {
- case PCI_DEVICE_ID_URP32INTF:
- case PCI_DEVICE_ID_URP8INTF:
- case PCI_DEVICE_ID_URP16INTF:
- case PCI_DEVICE_ID_CRP16INTF:
- case PCI_DEVICE_ID_URP8OCTA:
- rcktpt_io_addr[i] = pci_resource_start(dev, 2);
- ConfigIO = pci_resource_start(dev, 1);
- if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
- UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-
- /*
- * Check for octa or quad cable.
- */
- if (!
- (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
- PCI_GPIO_CTRL_8PORT)) {
- ports_per_aiop = 4;
- rocketModel[i].numPorts = 4;
- }
- }
- break;
- case PCI_DEVICE_ID_UPCI_RM3_8PORT:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
- strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
- rocketModel[i].numPorts = 8;
- rcktpt_io_addr[i] = pci_resource_start(dev, 2);
- UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
- ConfigIO = pci_resource_start(dev, 1);
- rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
- break;
- case PCI_DEVICE_ID_UPCI_RM3_4PORT:
- max_num_aiops = 1;
- rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
- strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
- rocketModel[i].numPorts = 4;
- rcktpt_io_addr[i] = pci_resource_start(dev, 2);
- UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
- ConfigIO = pci_resource_start(dev, 1);
- rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
- break;
- default:
- break;
- }
-
- if (fast_clock) {
- sClockPrescale = 0x12; /* mod 2 (divide by 3) */
- rp_baud_base[i] = 921600;
- } else {
- /*
- * If support_low_speed is set, use the slow clock
- * prescale, which supports 50 bps
- */
- if (support_low_speed) {
- /* mod 9 (divide by 10) prescale */
- sClockPrescale = 0x19;
- rp_baud_base[i] = 230400;
- } else {
- /* mod 4 (divide by 5) prescale */
- sClockPrescale = 0x14;
- rp_baud_base[i] = 460800;
- }
- }
-
- for (aiop = 0; aiop < max_num_aiops; aiop++)
- aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
- ctlp = sCtlNumToCtlPtr(i);
- num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
- for (aiop = 0; aiop < max_num_aiops; aiop++)
- ctlp->AiopNumChan[aiop] = ports_per_aiop;
-
- dev_info(&dev->dev, "comtrol PCI controller #%d found at "
- "address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n",
- i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString,
- rocketModel[i].startingPortNumber,
- rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1);
-
- if (num_aiops <= 0) {
- rcktpt_io_addr[i] = 0;
- return (0);
- }
- is_PCI[i] = 1;
-
- /* Reset the AIOPIC, init the serial ports */
- for (aiop = 0; aiop < num_aiops; aiop++) {
- sResetAiopByNum(ctlp, aiop);
- for (chan = 0; chan < ports_per_aiop; chan++)
- init_r_port(i, aiop, chan, dev);
- }
-
- /* Rocket modems must be reset */
- if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
- (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
- (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
- for (chan = 0; chan < ports_per_aiop; chan++)
- sPCIModemReset(ctlp, chan, 1);
- msleep(500);
- for (chan = 0; chan < ports_per_aiop; chan++)
- sPCIModemReset(ctlp, chan, 0);
- msleep(500);
- rmSpeakerReset(ctlp, rocketModel[i].model);
- }
- return (1);
-}
-
-/*
- * Probes for PCI cards, inits them if found
- * Input: board_found = number of ISA boards already found, or the
- * starting board number
- * Returns: Number of PCI boards found
- */
-static int __init init_PCI(int boards_found)
-{
- struct pci_dev *dev = NULL;
- int count = 0;
-
- /* Work through the PCI device list, pulling out ours */
- while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
- if (register_PCI(count + boards_found, dev))
- count++;
- }
- return (count);
-}
-
-#endif /* CONFIG_PCI */
-
-/*
- * Probes for ISA cards
- * Input: i = the board number to look for
- * Returns: 1 if board found, 0 else
- */
-static int __init init_ISA(int i)
-{
- int num_aiops, num_chan = 0, total_num_chan = 0;
- int aiop, chan;
- unsigned int aiopio[MAX_AIOPS_PER_BOARD];
- CONTROLLER_t *ctlp;
- char *type_string;
-
- /* If io_addr is zero, no board configured */
- if (rcktpt_io_addr[i] == 0)
- return (0);
-
- /* Reserve the IO region */
- if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
- printk(KERN_ERR "Unable to reserve IO region for configured "
- "ISA RocketPort at address 0x%lx, board not "
- "installed...\n", rcktpt_io_addr[i]);
- rcktpt_io_addr[i] = 0;
- return (0);
- }
-
- ctlp = sCtlNumToCtlPtr(i);
-
- ctlp->boardType = rcktpt_type[i];
-
- switch (rcktpt_type[i]) {
- case ROCKET_TYPE_PC104:
- type_string = "(PC104)";
- break;
- case ROCKET_TYPE_MODEM:
- type_string = "(RocketModem)";
- break;
- case ROCKET_TYPE_MODEMII:
- type_string = "(RocketModem II)";
- break;
- default:
- type_string = "";
- break;
- }
-
- /*
- * If support_low_speed is set, use the slow clock prescale,
- * which supports 50 bps
- */
- if (support_low_speed) {
- sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */
- rp_baud_base[i] = 230400;
- } else {
- sClockPrescale = 0x14; /* mod 4 (divide by 5) prescale */
- rp_baud_base[i] = 460800;
- }
-
- for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
- aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
-
- num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio, MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
-
- if (ctlp->boardType == ROCKET_TYPE_PC104) {
- sEnAiop(ctlp, 2); /* only one AIOPIC, but these */
- sEnAiop(ctlp, 3); /* CSels used for other stuff */
- }
-
- /* If something went wrong initing the AIOP's release the ISA IO memory */
- if (num_aiops <= 0) {
- release_region(rcktpt_io_addr[i], 64);
- rcktpt_io_addr[i] = 0;
- return (0);
- }
-
- rocketModel[i].startingPortNumber = nextLineNumber;
-
- for (aiop = 0; aiop < num_aiops; aiop++) {
- sResetAiopByNum(ctlp, aiop);
- sEnAiop(ctlp, aiop);
- num_chan = sGetAiopNumChan(ctlp, aiop);
- total_num_chan += num_chan;
- for (chan = 0; chan < num_chan; chan++)
- init_r_port(i, aiop, chan, NULL);
- }
- is_PCI[i] = 0;
- if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
- num_chan = sGetAiopNumChan(ctlp, 0);
- total_num_chan = num_chan;
- for (chan = 0; chan < num_chan; chan++)
- sModemReset(ctlp, chan, 1);
- msleep(500);
- for (chan = 0; chan < num_chan; chan++)
- sModemReset(ctlp, chan, 0);
- msleep(500);
- strcpy(rocketModel[i].modelString, "RocketModem ISA");
- } else {
- strcpy(rocketModel[i].modelString, "RocketPort ISA");
- }
- rocketModel[i].numPorts = total_num_chan;
- rocketModel[i].model = MODEL_ISA;
-
- printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n",
- i, rcktpt_io_addr[i], num_aiops, type_string);
-
- printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
- rocketModel[i].modelString,
- rocketModel[i].startingPortNumber,
- rocketModel[i].startingPortNumber +
- rocketModel[i].numPorts - 1);
-
- return (1);
-}
-
-static const struct tty_operations rocket_ops = {
- .open = rp_open,
- .close = rp_close,
- .write = rp_write,
- .put_char = rp_put_char,
- .write_room = rp_write_room,
- .chars_in_buffer = rp_chars_in_buffer,
- .flush_buffer = rp_flush_buffer,
- .ioctl = rp_ioctl,
- .throttle = rp_throttle,
- .unthrottle = rp_unthrottle,
- .set_termios = rp_set_termios,
- .stop = rp_stop,
- .start = rp_start,
- .hangup = rp_hangup,
- .break_ctl = rp_break,
- .send_xchar = rp_send_xchar,
- .wait_until_sent = rp_wait_until_sent,
- .tiocmget = rp_tiocmget,
- .tiocmset = rp_tiocmset,
-};
-
-static const struct tty_port_operations rocket_port_ops = {
- .carrier_raised = carrier_raised,
- .dtr_rts = dtr_rts,
-};
-
-/*
- * The module "startup" routine; it's run when the module is loaded.
- */
-static int __init rp_init(void)
-{
- int ret = -ENOMEM, pci_boards_found, isa_boards_found, i;
-
- printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
- ROCKET_VERSION, ROCKET_DATE);
-
- rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
- if (!rocket_driver)
- goto err;
-
- /*
- * If board 1 is non-zero, there is at least one ISA configured. If controller is
- * zero, use the default controller IO address of board1 + 0x40.
- */
- if (board1) {
- if (controller == 0)
- controller = board1 + 0x40;
- } else {
- controller = 0; /* Used as a flag, meaning no ISA boards */
- }
-
- /* If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
- if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
- printk(KERN_ERR "Unable to reserve IO region for first "
- "configured ISA RocketPort controller 0x%lx. "
- "Driver exiting\n", controller);
- ret = -EBUSY;
- goto err_tty;
- }
-
- /* Store ISA variable retrieved from command line or .conf file. */
- rcktpt_io_addr[0] = board1;
- rcktpt_io_addr[1] = board2;
- rcktpt_io_addr[2] = board3;
- rcktpt_io_addr[3] = board4;
-
- rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
- rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
- rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
- rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
- rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
- rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
- rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
- rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
-
- /*
- * Set up the tty driver structure and then register this
- * driver with the tty layer.
- */
-
- rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV;
- rocket_driver->name = "ttyR";
- rocket_driver->driver_name = "Comtrol RocketPort";
- rocket_driver->major = TTY_ROCKET_MAJOR;
- rocket_driver->minor_start = 0;
- rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
- rocket_driver->subtype = SERIAL_TYPE_NORMAL;
- rocket_driver->init_termios = tty_std_termios;
- rocket_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- rocket_driver->init_termios.c_ispeed = 9600;
- rocket_driver->init_termios.c_ospeed = 9600;
-#ifdef ROCKET_SOFT_FLOW
- rocket_driver->flags |= TTY_DRIVER_REAL_RAW;
-#endif
- tty_set_operations(rocket_driver, &rocket_ops);
-
- ret = tty_register_driver(rocket_driver);
- if (ret < 0) {
- printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
- goto err_controller;
- }
-
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
-#endif
-
- /*
- * OK, let's probe each of the controllers looking for boards. Any boards found
- * will be initialized here.
- */
- isa_boards_found = 0;
- pci_boards_found = 0;
-
- for (i = 0; i < NUM_BOARDS; i++) {
- if (init_ISA(i))
- isa_boards_found++;
- }
-
-#ifdef CONFIG_PCI
- if (isa_boards_found < NUM_BOARDS)
- pci_boards_found = init_PCI(isa_boards_found);
-#endif
-
- max_board = pci_boards_found + isa_boards_found;
-
- if (max_board == 0) {
- printk(KERN_ERR "No rocketport ports found; unloading driver\n");
- ret = -ENXIO;
- goto err_ttyu;
- }
-
- return 0;
-err_ttyu:
- tty_unregister_driver(rocket_driver);
-err_controller:
- if (controller)
- release_region(controller, 4);
-err_tty:
- put_tty_driver(rocket_driver);
-err:
- return ret;
-}
-
-
-static void rp_cleanup_module(void)
-{
- int retval;
- int i;
-
- del_timer_sync(&rocket_timer);
-
- retval = tty_unregister_driver(rocket_driver);
- if (retval)
- printk(KERN_ERR "Error %d while trying to unregister "
- "rocketport driver\n", -retval);
-
- for (i = 0; i < MAX_RP_PORTS; i++)
- if (rp_table[i]) {
- tty_unregister_device(rocket_driver, i);
- tty_port_destroy(&rp_table[i]->port);
- kfree(rp_table[i]);
- }
-
- put_tty_driver(rocket_driver);
-
- for (i = 0; i < NUM_BOARDS; i++) {
- if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
- continue;
- release_region(rcktpt_io_addr[i], 64);
- }
- if (controller)
- release_region(controller, 4);
-}
-
-/***************************************************************************
-Function: sInitController
-Purpose: Initialization of controller global registers and controller
- structure.
-Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
- IRQNum,Frequency,PeriodicOnly)
- CONTROLLER_T *CtlP; Ptr to controller structure
- int CtlNum; Controller number
- ByteIO_t MudbacIO; Mudbac base I/O address.
- ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
- This list must be in the order the AIOPs will be found on the
- controller. Once an AIOP in the list is not found, it is
- assumed that there are no more AIOPs on the controller.
- int AiopIOListSize; Number of addresses in AiopIOList
- int IRQNum; Interrupt Request number. Can be any of the following:
- 0: Disable global interrupts
- 3: IRQ 3
- 4: IRQ 4
- 5: IRQ 5
- 9: IRQ 9
- 10: IRQ 10
- 11: IRQ 11
- 12: IRQ 12
- 15: IRQ 15
- Byte_t Frequency: A flag identifying the frequency
- of the periodic interrupt, can be any one of the following:
- FREQ_DIS - periodic interrupt disabled
- FREQ_137HZ - 137 Hertz
- FREQ_69HZ - 69 Hertz
- FREQ_34HZ - 34 Hertz
- FREQ_17HZ - 17 Hertz
- FREQ_9HZ - 9 Hertz
- FREQ_4HZ - 4 Hertz
- If IRQNum is set to 0 the Frequency parameter is
- overidden, it is forced to a value of FREQ_DIS.
- int PeriodicOnly: 1 if all interrupts except the periodic
- interrupt are to be blocked.
- 0 is both the periodic interrupt and
- other channel interrupts are allowed.
- If IRQNum is set to 0 the PeriodicOnly parameter is
- overidden, it is forced to a value of 0.
-Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
- initialization failed.
-
-Comments:
- If periodic interrupts are to be disabled but AIOP interrupts
- are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
- If interrupts are to be completely disabled set IRQNum to 0.
-
- Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
- invalid combination.
-
- This function performs initialization of global interrupt modes,
- but it does not actually enable global interrupts. To enable
- and disable global interrupts use functions sEnGlobalInt() and
- sDisGlobalInt(). Enabling of global interrupts is normally not
- done until all other initializations are complete.
-
- Even if interrupts are globally enabled, they must also be
- individually enabled for each channel that is to generate
- interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
- No context switches are allowed while executing this function.
-
- After this function all AIOPs on the controller are disabled,
- they can be enabled with sEnAiop().
-*/
-static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
- ByteIO_t * AiopIOList, int AiopIOListSize,
- int IRQNum, Byte_t Frequency, int PeriodicOnly)
-{
- int i;
- ByteIO_t io;
- int done;
-
- CtlP->AiopIntrBits = aiop_intr_bits;
- CtlP->AltChanRingIndicator = 0;
- CtlP->CtlNum = CtlNum;
- CtlP->CtlID = CTLID_0001; /* controller release 1 */
- CtlP->BusType = isISA;
- CtlP->MBaseIO = MudbacIO;
- CtlP->MReg1IO = MudbacIO + 1;
- CtlP->MReg2IO = MudbacIO + 2;
- CtlP->MReg3IO = MudbacIO + 3;
-#if 1
- CtlP->MReg2 = 0; /* interrupt disable */
- CtlP->MReg3 = 0; /* no periodic interrupts */
-#else
- if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */
- CtlP->MReg2 = 0; /* interrupt disable */
- CtlP->MReg3 = 0; /* no periodic interrupts */
- } else {
- CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
- CtlP->MReg3 = Frequency; /* set frequency */
- if (PeriodicOnly) { /* periodic interrupt only */
- CtlP->MReg3 |= PERIODIC_ONLY;
- }
- }
-#endif
- sOutB(CtlP->MReg2IO, CtlP->MReg2);
- sOutB(CtlP->MReg3IO, CtlP->MReg3);
- sControllerEOI(CtlP); /* clear EOI if warm init */
- /* Init AIOPs */
- CtlP->NumAiop = 0;
- for (i = done = 0; i < AiopIOListSize; i++) {
- io = AiopIOList[i];
- CtlP->AiopIO[i] = (WordIO_t) io;
- CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
- sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */
- sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */
- if (done)
- continue;
- sEnAiop(CtlP, i); /* enable the AIOP */
- CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
- if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
- done = 1; /* done looking for AIOPs */
- else {
- CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
- sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
- sOutB(io + _INDX_DATA, sClockPrescale);
- CtlP->NumAiop++; /* bump count of AIOPs */
- }
- sDisAiop(CtlP, i); /* disable AIOP */
- }
-
- if (CtlP->NumAiop == 0)
- return (-1);
- else
- return (CtlP->NumAiop);
-}
-
-/***************************************************************************
-Function: sReadAiopID
-Purpose: Read the AIOP idenfication number directly from an AIOP.
-Call: sReadAiopID(io)
- ByteIO_t io: AIOP base I/O address
-Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
- is replace by an identifying number.
- Flag AIOPID_NULL if no valid AIOP is found
-Warnings: No context switches are allowed while executing this function.
-
-*/
-static int sReadAiopID(ByteIO_t io)
-{
- Byte_t AiopID; /* ID byte from AIOP */
-
- sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */
- sOutB(io + _CMD_REG, 0x0);
- AiopID = sInW(io + _CHN_STAT0) & 0x07;
- if (AiopID == 0x06)
- return (1);
- else /* AIOP does not exist */
- return (-1);
-}
-
-/***************************************************************************
-Function: sReadAiopNumChan
-Purpose: Read the number of channels available in an AIOP directly from
- an AIOP.
-Call: sReadAiopNumChan(io)
- WordIO_t io: AIOP base I/O address
-Return: int: The number of channels available
-Comments: The number of channels is determined by write/reads from identical
- offsets within the SRAM address spaces for channels 0 and 4.
- If the channel 4 space is mirrored to channel 0 it is a 4 channel
- AIOP, otherwise it is an 8 channel.
-Warnings: No context switches are allowed while executing this function.
-*/
-static int sReadAiopNumChan(WordIO_t io)
-{
- Word_t x;
- static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
-
- /* write to chan 0 SRAM */
- out32((DWordIO_t) io + _INDX_ADDR, R);
- sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */
- x = sInW(io + _INDX_DATA);
- sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */
- if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
- return (8);
- else
- return (4);
-}
-
-/***************************************************************************
-Function: sInitChan
-Purpose: Initialization of a channel and channel structure
-Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
- CONTROLLER_T *CtlP; Ptr to controller structure
- CHANNEL_T *ChP; Ptr to channel structure
- int AiopNum; AIOP number within controller
- int ChanNum; Channel number within AIOP
-Return: int: 1 if initialization succeeded, 0 if it fails because channel
- number exceeds number of channels available in AIOP.
-Comments: This function must be called before a channel can be used.
-Warnings: No range checking on any of the parameters is done.
-
- No context switches are allowed while executing this function.
-*/
-static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
- int ChanNum)
-{
- int i;
- WordIO_t AiopIO;
- WordIO_t ChIOOff;
- Byte_t *ChR;
- Word_t ChOff;
- static Byte_t R[4];
- int brd9600;
-
- if (ChanNum >= CtlP->AiopNumChan[AiopNum])
- return 0; /* exceeds num chans in AIOP */
-
- /* Channel, AIOP, and controller identifiers */
- ChP->CtlP = CtlP;
- ChP->ChanID = CtlP->AiopID[AiopNum];
- ChP->AiopNum = AiopNum;
- ChP->ChanNum = ChanNum;
-
- /* Global direct addresses */
- AiopIO = CtlP->AiopIO[AiopNum];
- ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
- ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
- ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
- ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
- ChP->IndexData = AiopIO + _INDX_DATA;
-
- /* Channel direct addresses */
- ChIOOff = AiopIO + ChP->ChanNum * 2;
- ChP->TxRxData = ChIOOff + _TD0;
- ChP->ChanStat = ChIOOff + _CHN_STAT0;
- ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
- ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
-
- /* Initialize the channel from the RData array */
- for (i = 0; i < RDATASIZE; i += 4) {
- R[0] = RData[i];
- R[1] = RData[i + 1] + 0x10 * ChanNum;
- R[2] = RData[i + 2];
- R[3] = RData[i + 3];
- out32(ChP->IndexAddr, R);
- }
-
- ChR = ChP->R;
- for (i = 0; i < RREGDATASIZE; i += 4) {
- ChR[i] = RRegData[i];
- ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
- ChR[i + 2] = RRegData[i + 2];
- ChR[i + 3] = RRegData[i + 3];
- }
-
- /* Indexed registers */
- ChOff = (Word_t) ChanNum *0x1000;
-
- if (sClockPrescale == 0x14)
- brd9600 = 47;
- else
- brd9600 = 23;
-
- ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
- ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
- ChP->BaudDiv[2] = (Byte_t) brd9600;
- ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
- out32(ChP->IndexAddr, ChP->BaudDiv);
-
- ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
- ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
- ChP->TxControl[2] = 0;
- ChP->TxControl[3] = 0;
- out32(ChP->IndexAddr, ChP->TxControl);
-
- ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
- ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
- ChP->RxControl[2] = 0;
- ChP->RxControl[3] = 0;
- out32(ChP->IndexAddr, ChP->RxControl);
-
- ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
- ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
- ChP->TxEnables[2] = 0;
- ChP->TxEnables[3] = 0;
- out32(ChP->IndexAddr, ChP->TxEnables);
-
- ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
- ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
- ChP->TxCompare[2] = 0;
- ChP->TxCompare[3] = 0;
- out32(ChP->IndexAddr, ChP->TxCompare);
-
- ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
- ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
- ChP->TxReplace1[2] = 0;
- ChP->TxReplace1[3] = 0;
- out32(ChP->IndexAddr, ChP->TxReplace1);
-
- ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
- ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
- ChP->TxReplace2[2] = 0;
- ChP->TxReplace2[3] = 0;
- out32(ChP->IndexAddr, ChP->TxReplace2);
-
- ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
- ChP->TxFIFO = ChOff + _TX_FIFO;
-
- sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
- sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */
- sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
- sOutW(ChP->IndexData, 0);
- ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
- ChP->RxFIFO = ChOff + _RX_FIFO;
-
- sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
- sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */
- sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
- sOutW(ChP->IndexData, 0);
- sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
- sOutW(ChP->IndexData, 0);
- ChP->TxPrioCnt = ChOff + _TXP_CNT;
- sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
- sOutB(ChP->IndexData, 0);
- ChP->TxPrioPtr = ChOff + _TXP_PNTR;
- sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
- sOutB(ChP->IndexData, 0);
- ChP->TxPrioBuf = ChOff + _TXP_BUF;
- sEnRxProcessor(ChP); /* start the Rx processor */
-
- return 1;
-}
-
-/***************************************************************************
-Function: sStopRxProcessor
-Purpose: Stop the receive processor from processing a channel.
-Call: sStopRxProcessor(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-
-Comments: The receive processor can be started again with sStartRxProcessor().
- This function causes the receive processor to skip over the
- stopped channel. It does not stop it from processing other channels.
-
-Warnings: No context switches are allowed while executing this function.
-
- Do not leave the receive processor stopped for more than one
- character time.
-
- After calling this function a delay of 4 uS is required to ensure
- that the receive processor is no longer processing this channel.
-*/
-static void sStopRxProcessor(CHANNEL_T * ChP)
-{
- Byte_t R[4];
-
- R[0] = ChP->R[0];
- R[1] = ChP->R[1];
- R[2] = 0x0a;
- R[3] = ChP->R[3];
- out32(ChP->IndexAddr, R);
-}
-
-/***************************************************************************
-Function: sFlushRxFIFO
-Purpose: Flush the Rx FIFO
-Call: sFlushRxFIFO(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: void
-Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
- while it is being flushed the receive processor is stopped
- and the transmitter is disabled. After these operations a
- 4 uS delay is done before clearing the pointers to allow
- the receive processor to stop. These items are handled inside
- this function.
-Warnings: No context switches are allowed while executing this function.
-*/
-static void sFlushRxFIFO(CHANNEL_T * ChP)
-{
- int i;
- Byte_t Ch; /* channel number within AIOP */
- int RxFIFOEnabled; /* 1 if Rx FIFO enabled */
-
- if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
- return; /* don't need to flush */
-
- RxFIFOEnabled = 0;
- if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
- RxFIFOEnabled = 1;
- sDisRxFIFO(ChP); /* disable it */
- for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
- sInB(ChP->IntChan); /* depends on bus i/o timing */
- }
- sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
- Ch = (Byte_t) sGetChanNum(ChP);
- sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */
- sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */
- sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
- sOutW(ChP->IndexData, 0);
- sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
- sOutW(ChP->IndexData, 0);
- if (RxFIFOEnabled)
- sEnRxFIFO(ChP); /* enable Rx FIFO */
-}
-
-/***************************************************************************
-Function: sFlushTxFIFO
-Purpose: Flush the Tx FIFO
-Call: sFlushTxFIFO(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: void
-Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
- while it is being flushed the receive processor is stopped
- and the transmitter is disabled. After these operations a
- 4 uS delay is done before clearing the pointers to allow
- the receive processor to stop. These items are handled inside
- this function.
-Warnings: No context switches are allowed while executing this function.
-*/
-static void sFlushTxFIFO(CHANNEL_T * ChP)
-{
- int i;
- Byte_t Ch; /* channel number within AIOP */
- int TxEnabled; /* 1 if transmitter enabled */
-
- if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
- return; /* don't need to flush */
-
- TxEnabled = 0;
- if (ChP->TxControl[3] & TX_ENABLE) {
- TxEnabled = 1;
- sDisTransmit(ChP); /* disable transmitter */
- }
- sStopRxProcessor(ChP); /* stop Rx processor */
- for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */
- sInB(ChP->IntChan); /* depends on bus i/o timing */
- Ch = (Byte_t) sGetChanNum(ChP);
- sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */
- sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */
- sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
- sOutW(ChP->IndexData, 0);
- if (TxEnabled)
- sEnTransmit(ChP); /* enable transmitter */
- sStartRxProcessor(ChP); /* restart Rx processor */
-}
-
-/***************************************************************************
-Function: sWriteTxPrioByte
-Purpose: Write a byte of priority transmit data to a channel
-Call: sWriteTxPrioByte(ChP,Data)
- CHANNEL_T *ChP; Ptr to channel structure
- Byte_t Data; The transmit data byte
-
-Return: int: 1 if the bytes is successfully written, otherwise 0.
-
-Comments: The priority byte is transmitted before any data in the Tx FIFO.
-
-Warnings: No context switches are allowed while executing this function.
-*/
-static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
-{
- Byte_t DWBuf[4]; /* buffer for double word writes */
- Word_t *WordPtr; /* must be far because Win SS != DS */
- register DWordIO_t IndexAddr;
-
- if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */
- IndexAddr = ChP->IndexAddr;
- sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */
- if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */
- return (0); /* nothing sent */
-
- WordPtr = (Word_t *) (&DWBuf[0]);
- *WordPtr = ChP->TxPrioBuf; /* data byte address */
-
- DWBuf[2] = Data; /* data byte value */
- out32(IndexAddr, DWBuf); /* write it out */
-
- *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
-
- DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
- DWBuf[3] = 0; /* priority buffer pointer */
- out32(IndexAddr, DWBuf); /* write it out */
- } else { /* write it to Tx FIFO */
-
- sWriteTxByte(sGetTxRxDataIO(ChP), Data);
- }
- return (1); /* 1 byte sent */
-}
-
-/***************************************************************************
-Function: sEnInterrupts
-Purpose: Enable one or more interrupts for a channel
-Call: sEnInterrupts(ChP,Flags)
- CHANNEL_T *ChP; Ptr to channel structure
- Word_t Flags: Interrupt enable flags, can be any combination
- of the following flags:
- TXINT_EN: Interrupt on Tx FIFO empty
- RXINT_EN: Interrupt on Rx FIFO at trigger level (see
- sSetRxTrigger())
- SRCINT_EN: Interrupt on SRC (Special Rx Condition)
- MCINT_EN: Interrupt on modem input change
- CHANINT_EN: Allow channel interrupt signal to the AIOP's
- Interrupt Channel Register.
-Return: void
-Comments: If an interrupt enable flag is set in Flags, that interrupt will be
- enabled. If an interrupt enable flag is not set in Flags, that
- interrupt will not be changed. Interrupts can be disabled with
- function sDisInterrupts().
-
- This function sets the appropriate bit for the channel in the AIOP's
- Interrupt Mask Register if the CHANINT_EN flag is set. This allows
- this channel's bit to be set in the AIOP's Interrupt Channel Register.
-
- Interrupts must also be globally enabled before channel interrupts
- will be passed on to the host. This is done with function
- sEnGlobalInt().
-
- In some cases it may be desirable to disable interrupts globally but
- enable channel interrupts. This would allow the global interrupt
- status register to be used to determine which AIOPs need service.
-*/
-static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
-{
- Byte_t Mask; /* Interrupt Mask Register */
-
- ChP->RxControl[2] |=
- ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
-
- out32(ChP->IndexAddr, ChP->RxControl);
-
- ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
-
- out32(ChP->IndexAddr, ChP->TxControl);
-
- if (Flags & CHANINT_EN) {
- Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
- sOutB(ChP->IntMask, Mask);
- }
-}
-
-/***************************************************************************
-Function: sDisInterrupts
-Purpose: Disable one or more interrupts for a channel
-Call: sDisInterrupts(ChP,Flags)
- CHANNEL_T *ChP; Ptr to channel structure
- Word_t Flags: Interrupt flags, can be any combination
- of the following flags:
- TXINT_EN: Interrupt on Tx FIFO empty
- RXINT_EN: Interrupt on Rx FIFO at trigger level (see
- sSetRxTrigger())
- SRCINT_EN: Interrupt on SRC (Special Rx Condition)
- MCINT_EN: Interrupt on modem input change
- CHANINT_EN: Disable channel interrupt signal to the
- AIOP's Interrupt Channel Register.
-Return: void
-Comments: If an interrupt flag is set in Flags, that interrupt will be
- disabled. If an interrupt flag is not set in Flags, that
- interrupt will not be changed. Interrupts can be enabled with
- function sEnInterrupts().
-
- This function clears the appropriate bit for the channel in the AIOP's
- Interrupt Mask Register if the CHANINT_EN flag is set. This blocks
- this channel's bit from being set in the AIOP's Interrupt Channel
- Register.
-*/
-static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
-{
- Byte_t Mask; /* Interrupt Mask Register */
-
- ChP->RxControl[2] &=
- ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
- out32(ChP->IndexAddr, ChP->RxControl);
- ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
- out32(ChP->IndexAddr, ChP->TxControl);
-
- if (Flags & CHANINT_EN) {
- Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
- sOutB(ChP->IntMask, Mask);
- }
-}
-
-static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
-{
- sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
-}
-
-/*
- * Not an official SSCI function, but how to reset RocketModems.
- * ISA bus version
- */
-static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
-{
- ByteIO_t addr;
- Byte_t val;
-
- addr = CtlP->AiopIO[0] + 0x400;
- val = sInB(CtlP->MReg3IO);
- /* if AIOP[1] is not enabled, enable it */
- if ((val & 2) == 0) {
- val = sInB(CtlP->MReg2IO);
- sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
- sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
- }
-
- sEnAiop(CtlP, 1);
- if (!on)
- addr += 8;
- sOutB(addr + chan, 0); /* apply or remove reset */
- sDisAiop(CtlP, 1);
-}
-
-/*
- * Not an official SSCI function, but how to reset RocketModems.
- * PCI bus version
- */
-static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
-{
- ByteIO_t addr;
-
- addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */
- if (!on)
- addr += 8;
- sOutB(addr + chan, 0); /* apply or remove reset */
-}
-
-/* Returns the line number given the controller (board), aiop and channel number */
-static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
-{
- return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
-}
-
-/*
- * Stores the line number associated with a given controller (board), aiop
- * and channel number.
- * Returns: The line number assigned
- */
-static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
-{
- lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
- return (nextLineNumber - 1);
-}
diff --git a/drivers/tty/rocket.h b/drivers/tty/rocket.h
deleted file mode 100644
index d62ed6587f32..000000000000
--- a/drivers/tty/rocket.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * rocket.h --- the exported interface of the rocket driver to its configuration program.
- *
- * Written by Theodore Ts'o, Copyright 1997.
- * Copyright 1997 Comtrol Corporation.
- *
- */
-
-/* Model Information Struct */
-typedef struct {
- unsigned long model;
- char modelString[80];
- unsigned long numPorts;
- int loadrm2;
- int startingPortNumber;
-} rocketModel_t;
-
-struct rocket_config {
- int line;
- int flags;
- int closing_wait;
- int close_delay;
- int port;
- int reserved[32];
-};
-
-struct rocket_ports {
- int tty_major;
- int callout_major;
- rocketModel_t rocketModel[8];
-};
-
-struct rocket_version {
- char rocket_version[32];
- char rocket_date[32];
- char reserved[64];
-};
-
-/*
- * Rocketport flags
- */
-/*#define ROCKET_CALLOUT_NOHUP 0x00000001 */
-#define ROCKET_FORCE_CD 0x00000002
-#define ROCKET_HUP_NOTIFY 0x00000004
-#define ROCKET_SPLIT_TERMIOS 0x00000008
-#define ROCKET_SPD_MASK 0x00000070
-#define ROCKET_SPD_HI 0x00000010 /* Use 57600 instead of 38400 bps */
-#define ROCKET_SPD_VHI 0x00000020 /* Use 115200 instead of 38400 bps */
-#define ROCKET_SPD_SHI 0x00000030 /* Use 230400 instead of 38400 bps */
-#define ROCKET_SPD_WARP 0x00000040 /* Use 460800 instead of 38400 bps */
-#define ROCKET_SAK 0x00000080
-#define ROCKET_SESSION_LOCKOUT 0x00000100
-#define ROCKET_PGRP_LOCKOUT 0x00000200
-#define ROCKET_RTS_TOGGLE 0x00000400
-#define ROCKET_MODE_MASK 0x00003000
-#define ROCKET_MODE_RS232 0x00000000
-#define ROCKET_MODE_RS485 0x00001000
-#define ROCKET_MODE_RS422 0x00002000
-#define ROCKET_FLAGS 0x00003FFF
-
-#define ROCKET_USR_MASK 0x0071 /* Legal flags that non-privileged
- * users can set or reset */
-
-/*
- * For closing_wait and closing_wait2
- */
-#define ROCKET_CLOSING_WAIT_NONE ASYNC_CLOSING_WAIT_NONE
-#define ROCKET_CLOSING_WAIT_INF ASYNC_CLOSING_WAIT_INF
-
-/*
- * Rocketport ioctls -- "RP"
- */
-#define RCKP_GET_CONFIG 0x00525002
-#define RCKP_SET_CONFIG 0x00525003
-#define RCKP_GET_PORTS 0x00525004
-#define RCKP_RESET_RM2 0x00525005
-#define RCKP_GET_VERSION 0x00525006
-
-/* Rocketport Models */
-#define MODEL_RP32INTF 0x0001 /* RP 32 port w/external I/F */
-#define MODEL_RP8INTF 0x0002 /* RP 8 port w/external I/F */
-#define MODEL_RP16INTF 0x0003 /* RP 16 port w/external I/F */
-#define MODEL_RP8OCTA 0x0005 /* RP 8 port w/octa cable */
-#define MODEL_RP4QUAD 0x0004 /* RP 4 port w/quad cable */
-#define MODEL_RP8J 0x0006 /* RP 8 port w/RJ11 connectors */
-#define MODEL_RP4J 0x0007 /* RP 4 port w/RJ45 connectors */
-#define MODEL_RP8SNI 0x0008 /* RP 8 port w/ DB78 SNI connector */
-#define MODEL_RP16SNI 0x0009 /* RP 16 port w/ DB78 SNI connector */
-#define MODEL_RPP4 0x000A /* RP Plus 4 port */
-#define MODEL_RPP8 0x000B /* RP Plus 8 port */
-#define MODEL_RP2_232 0x000E /* RP Plus 2 port RS232 */
-#define MODEL_RP2_422 0x000F /* RP Plus 2 port RS232 */
-
-/* Rocketmodem II Models */
-#define MODEL_RP6M 0x000C /* RM 6 port */
-#define MODEL_RP4M 0x000D /* RM 4 port */
-
-/* Universal PCI boards */
-#define MODEL_UPCI_RP32INTF 0x0801 /* RP UPCI 32 port w/external I/F */
-#define MODEL_UPCI_RP8INTF 0x0802 /* RP UPCI 8 port w/external I/F */
-#define MODEL_UPCI_RP16INTF 0x0803 /* RP UPCI 16 port w/external I/F */
-#define MODEL_UPCI_RP8OCTA 0x0805 /* RP UPCI 8 port w/octa cable */
-#define MODEL_UPCI_RM3_8PORT 0x080C /* RP UPCI Rocketmodem III 8 port */
-#define MODEL_UPCI_RM3_4PORT 0x080C /* RP UPCI Rocketmodem III 4 port */
-
-/* Compact PCI 16 port */
-#define MODEL_CPCI_RP16INTF 0x0903 /* RP Compact PCI 16 port w/external I/F */
-
-/* All ISA boards */
-#define MODEL_ISA 0x1000
diff --git a/drivers/tty/rocket_int.h b/drivers/tty/rocket_int.h
deleted file mode 100644
index 727e50dbb92f..000000000000
--- a/drivers/tty/rocket_int.h
+++ /dev/null
@@ -1,1214 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * rocket_int.h --- internal header file for rocket.c
- *
- * Written by Theodore Ts'o, Copyright 1997.
- * Copyright 1997 Comtrol Corporation.
- *
- */
-
-/*
- * Definition of the types in rcktpt_type
- */
-#define ROCKET_TYPE_NORMAL 0
-#define ROCKET_TYPE_MODEM 1
-#define ROCKET_TYPE_MODEMII 2
-#define ROCKET_TYPE_MODEMIII 3
-#define ROCKET_TYPE_PC104 4
-
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-typedef unsigned char Byte_t;
-typedef unsigned int ByteIO_t;
-
-typedef unsigned int Word_t;
-typedef unsigned int WordIO_t;
-
-typedef unsigned int DWordIO_t;
-
-/*
- * Note! Normally the Linux I/O macros already take care of
- * byte-swapping the I/O instructions. However, all accesses using
- * sOutDW aren't really 32-bit accesses, but should be handled in byte
- * order. Hence the use of the cpu_to_le32() macro to byte-swap
- * things to no-op the byte swapping done by the big-endian outl()
- * instruction.
- */
-
-static inline void sOutB(unsigned short port, unsigned char value)
-{
-#ifdef ROCKET_DEBUG_IO
- printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value);
-#endif
- outb_p(value, port);
-}
-
-static inline void sOutW(unsigned short port, unsigned short value)
-{
-#ifdef ROCKET_DEBUG_IO
- printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value);
-#endif
- outw_p(value, port);
-}
-
-static inline void out32(unsigned short port, Byte_t *p)
-{
- u32 value = get_unaligned_le32(p);
-#ifdef ROCKET_DEBUG_IO
- printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value);
-#endif
- outl_p(value, port);
-}
-
-static inline unsigned char sInB(unsigned short port)
-{
- return inb_p(port);
-}
-
-static inline unsigned short sInW(unsigned short port)
-{
- return inw_p(port);
-}
-
-/* This is used to move arrays of bytes so byte swapping isn't appropriate. */
-#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count)
-#define sInStrW(port, addr, count) if (count) insw(port, addr, count)
-
-#define CTL_SIZE 8
-#define AIOP_CTL_SIZE 4
-#define CHAN_AIOP_SIZE 8
-#define MAX_PORTS_PER_AIOP 8
-#define MAX_AIOPS_PER_BOARD 4
-#define MAX_PORTS_PER_BOARD 32
-
-/* Bus type ID */
-#define isISA 0
-#define isPCI 1
-#define isMC 2
-
-/* Controller ID numbers */
-#define CTLID_NULL -1 /* no controller exists */
-#define CTLID_0001 0x0001 /* controller release 1 */
-
-/* AIOP ID numbers, identifies AIOP type implementing channel */
-#define AIOPID_NULL -1 /* no AIOP or channel exists */
-#define AIOPID_0001 0x0001 /* AIOP release 1 */
-
-/************************************************************************
- Global Register Offsets - Direct Access - Fixed values
-************************************************************************/
-
-#define _CMD_REG 0x38 /* Command Register 8 Write */
-#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */
-#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */
-#define _UNUSED 0x3B /* Unused 8 */
-#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */
-#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */
-
-/************************************************************************
- Channel Register Offsets for 1st channel in AIOP - Direct Access
-************************************************************************/
-#define _TD0 0x00 /* Transmit Data 16 Write */
-#define _RD0 0x00 /* Receive Data 16 Read */
-#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */
-#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */
-#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */
-
-/************************************************************************
- Tx Control Register Offsets - Indexed - External - Fixed
-************************************************************************/
-#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */
-#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */
-#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */
-#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */
-#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */
-#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */
-
-/************************************************************************
-Memory Controller Register Offsets - Indexed - External - Fixed
-************************************************************************/
-#define _RX_FIFO 0x000 /* Rx FIFO */
-#define _TX_FIFO 0x800 /* Tx FIFO */
-#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */
-#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */
-#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */
-#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */
-#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */
-#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */
-
-#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */
-#define TXFIFO_SIZE 255 /* size of Tx FIFO */
-#define RXFIFO_SIZE 1023 /* size of Rx FIFO */
-
-/************************************************************************
-Tx Priority Buffer - Indexed - External - Fixed
-************************************************************************/
-#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */
-#define TXP_SIZE 0x20 /* 32 bytes */
-
-/************************************************************************
-Channel Register Offsets - Indexed - Internal - Fixed
-************************************************************************/
-
-#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */
-#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */
-#define _BAUD 0xFF4 /* Baud Rate 16 Write */
-#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */
-
-#define STMBREAK 0x08 /* BREAK */
-#define STMFRAME 0x04 /* framing error */
-#define STMRCVROVR 0x02 /* receiver over run error */
-#define STMPARITY 0x01 /* parity error */
-#define STMERROR (STMBREAK | STMFRAME | STMPARITY)
-#define STMBREAKH 0x800 /* BREAK */
-#define STMFRAMEH 0x400 /* framing error */
-#define STMRCVROVRH 0x200 /* receiver over run error */
-#define STMPARITYH 0x100 /* parity error */
-#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH)
-
-#define CTS_ACT 0x20 /* CTS input asserted */
-#define DSR_ACT 0x10 /* DSR input asserted */
-#define CD_ACT 0x08 /* CD input asserted */
-#define TXFIFOMT 0x04 /* Tx FIFO is empty */
-#define TXSHRMT 0x02 /* Tx shift register is empty */
-#define RDA 0x01 /* Rx data available */
-#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */
-
-#define STATMODE 0x8000 /* status mode enable bit */
-#define RXFOVERFL 0x2000 /* receive FIFO overflow */
-#define RX2MATCH 0x1000 /* receive compare byte 2 match */
-#define RX1MATCH 0x0800 /* receive compare byte 1 match */
-#define RXBREAK 0x0400 /* received BREAK */
-#define RXFRAME 0x0200 /* received framing error */
-#define RXPARITY 0x0100 /* received parity error */
-#define STATERROR (RXBREAK | RXFRAME | RXPARITY)
-
-#define CTSFC_EN 0x80 /* CTS flow control enable bit */
-#define RTSTOG_EN 0x40 /* RTS toggle enable bit */
-#define TXINT_EN 0x10 /* transmit interrupt enable */
-#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */
-#define PARITY_EN 0x04 /* enable parity (0 = no parity) */
-#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */
-#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */
-
-#define SETBREAK 0x10 /* send break condition (must clear) */
-#define LOCALLOOP 0x08 /* local loopback set for test */
-#define SET_DTR 0x04 /* assert DTR */
-#define SET_RTS 0x02 /* assert RTS */
-#define TX_ENABLE 0x01 /* enable transmitter */
-
-#define RTSFC_EN 0x40 /* RTS flow control enable */
-#define RXPROC_EN 0x20 /* receive processor enable */
-#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */
-#define TRIG_1 0x08 /* trigger level 1 char */
-#define TRIG_1_2 0x10 /* trigger level 1/2 */
-#define TRIG_7_8 0x18 /* trigger level 7/8 */
-#define TRIG_MASK 0x18 /* trigger level mask */
-#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */
-#define RXINT_EN 0x02 /* Rx interrupt enable */
-#define MCINT_EN 0x01 /* modem change interrupt enable */
-
-#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */
-#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */
-#define SRC_INT 0x08 /* special receive condition interrupt */
-#define DELTA_CD 0x04 /* CD change interrupt */
-#define DELTA_CTS 0x02 /* CTS change interrupt */
-#define DELTA_DSR 0x01 /* DSR change interrupt */
-
-#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */
-#define IGN2_EN 0x08 /* ignore byte 2 enable */
-#define IGN1_EN 0x04 /* ignore byte 1 enable */
-#define COMP2_EN 0x02 /* compare byte 2 enable */
-#define COMP1_EN 0x01 /* compare byte 1 enable */
-
-#define RESET_ALL 0x80 /* reset AIOP (all channels) */
-#define TXOVERIDE 0x40 /* Transmit software off override */
-#define RESETUART 0x20 /* reset channel's UART */
-#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */
-#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */
-
-#define INTSTAT0 0x01 /* AIOP 0 interrupt status */
-#define INTSTAT1 0x02 /* AIOP 1 interrupt status */
-#define INTSTAT2 0x04 /* AIOP 2 interrupt status */
-#define INTSTAT3 0x08 /* AIOP 3 interrupt status */
-
-#define INTR_EN 0x08 /* allow interrupts to host */
-#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */
-
-/**************************************************************************
- MUDBAC remapped for PCI
-**************************************************************************/
-
-#define _CFG_INT_PCI 0x40
-#define _PCI_INT_FUNC 0x3A
-
-#define PCI_STROB 0x2000 /* bit 13 of int aiop register */
-#define INTR_EN_PCI 0x0010 /* allow interrupts to host */
-
-/*
- * Definitions for Universal PCI board registers
- */
-#define _PCI_9030_INT_CTRL 0x4c /* Offsets from BAR1 */
-#define _PCI_9030_GPIO_CTRL 0x54
-#define PCI_INT_CTRL_AIOP 0x0001
-#define PCI_GPIO_CTRL_8PORT 0x4000
-#define _PCI_9030_RING_IND 0xc0 /* Offsets from BAR1 */
-
-#define CHAN3_EN 0x08 /* enable AIOP 3 */
-#define CHAN2_EN 0x04 /* enable AIOP 2 */
-#define CHAN1_EN 0x02 /* enable AIOP 1 */
-#define CHAN0_EN 0x01 /* enable AIOP 0 */
-#define FREQ_DIS 0x00
-#define FREQ_274HZ 0x60
-#define FREQ_137HZ 0x50
-#define FREQ_69HZ 0x40
-#define FREQ_34HZ 0x30
-#define FREQ_17HZ 0x20
-#define FREQ_9HZ 0x10
-#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */
-
-#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */
-
-#define RDATASIZE 72
-#define RREGDATASIZE 52
-
-/*
- * AIOP interrupt bits for ISA/PCI boards and UPCI boards.
- */
-#define AIOP_INTR_BIT_0 0x0001
-#define AIOP_INTR_BIT_1 0x0002
-#define AIOP_INTR_BIT_2 0x0004
-#define AIOP_INTR_BIT_3 0x0008
-
-#define AIOP_INTR_BITS ( \
- AIOP_INTR_BIT_0 \
- | AIOP_INTR_BIT_1 \
- | AIOP_INTR_BIT_2 \
- | AIOP_INTR_BIT_3)
-
-#define UPCI_AIOP_INTR_BIT_0 0x0004
-#define UPCI_AIOP_INTR_BIT_1 0x0020
-#define UPCI_AIOP_INTR_BIT_2 0x0100
-#define UPCI_AIOP_INTR_BIT_3 0x0800
-
-#define UPCI_AIOP_INTR_BITS ( \
- UPCI_AIOP_INTR_BIT_0 \
- | UPCI_AIOP_INTR_BIT_1 \
- | UPCI_AIOP_INTR_BIT_2 \
- | UPCI_AIOP_INTR_BIT_3)
-
-/* Controller level information structure */
-typedef struct {
- int CtlID;
- int CtlNum;
- int BusType;
- int boardType;
- int isUPCI;
- WordIO_t PCIIO;
- WordIO_t PCIIO2;
- ByteIO_t MBaseIO;
- ByteIO_t MReg1IO;
- ByteIO_t MReg2IO;
- ByteIO_t MReg3IO;
- Byte_t MReg2;
- Byte_t MReg3;
- int NumAiop;
- int AltChanRingIndicator;
- ByteIO_t UPCIRingInd;
- WordIO_t AiopIO[AIOP_CTL_SIZE];
- ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE];
- int AiopID[AIOP_CTL_SIZE];
- int AiopNumChan[AIOP_CTL_SIZE];
- Word_t *AiopIntrBits;
-} CONTROLLER_T;
-
-typedef CONTROLLER_T CONTROLLER_t;
-
-/* Channel level information structure */
-typedef struct {
- CONTROLLER_T *CtlP;
- int AiopNum;
- int ChanID;
- int ChanNum;
- int rtsToggle;
-
- ByteIO_t Cmd;
- ByteIO_t IntChan;
- ByteIO_t IntMask;
- DWordIO_t IndexAddr;
- WordIO_t IndexData;
-
- WordIO_t TxRxData;
- WordIO_t ChanStat;
- WordIO_t TxRxCount;
- ByteIO_t IntID;
-
- Word_t TxFIFO;
- Word_t TxFIFOPtrs;
- Word_t RxFIFO;
- Word_t RxFIFOPtrs;
- Word_t TxPrioCnt;
- Word_t TxPrioPtr;
- Word_t TxPrioBuf;
-
- Byte_t R[RREGDATASIZE];
-
- Byte_t BaudDiv[4];
- Byte_t TxControl[4];
- Byte_t RxControl[4];
- Byte_t TxEnables[4];
- Byte_t TxCompare[4];
- Byte_t TxReplace1[4];
- Byte_t TxReplace2[4];
-} CHANNEL_T;
-
-typedef CHANNEL_T CHANNEL_t;
-typedef CHANNEL_T *CHANPTR_T;
-
-#define InterfaceModeRS232 0x00
-#define InterfaceModeRS422 0x08
-#define InterfaceModeRS485 0x10
-#define InterfaceModeRS232T 0x18
-
-/***************************************************************************
-Function: sClrBreak
-Purpose: Stop sending a transmit BREAK signal
-Call: sClrBreak(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrBreak(ChP) \
-do { \
- (ChP)->TxControl[3] &= ~SETBREAK; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrDTR
-Purpose: Clr the DTR output
-Call: sClrDTR(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrDTR(ChP) \
-do { \
- (ChP)->TxControl[3] &= ~SET_DTR; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrRTS
-Purpose: Clr the RTS output
-Call: sClrRTS(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrRTS(ChP) \
-do { \
- if ((ChP)->rtsToggle) break; \
- (ChP)->TxControl[3] &= ~SET_RTS; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrTxXOFF
-Purpose: Clear any existing transmit software flow control off condition
-Call: sClrTxXOFF(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrTxXOFF(ChP) \
-do { \
- sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \
- sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \
-} while (0)
-
-/***************************************************************************
-Function: sCtlNumToCtlPtr
-Purpose: Convert a controller number to controller structure pointer
-Call: sCtlNumToCtlPtr(CtlNum)
- int CtlNum; Controller number
-Return: CONTROLLER_T *: Ptr to controller structure
-*/
-#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM]
-
-/***************************************************************************
-Function: sControllerEOI
-Purpose: Strobe the MUDBAC's End Of Interrupt bit.
-Call: sControllerEOI(CtlP)
- CONTROLLER_T *CtlP; Ptr to controller structure
-*/
-#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB)
-
-/***************************************************************************
-Function: sPCIControllerEOI
-Purpose: Strobe the PCI End Of Interrupt bit.
- For the UPCI boards, toggle the AIOP interrupt enable bit
- (this was taken from the Windows driver).
-Call: sPCIControllerEOI(CtlP)
- CONTROLLER_T *CtlP; Ptr to controller structure
-*/
-#define sPCIControllerEOI(CTLP) \
-do { \
- if ((CTLP)->isUPCI) { \
- Word_t w = sInW((CTLP)->PCIIO); \
- sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \
- sOutW((CTLP)->PCIIO, w); \
- } \
- else { \
- sOutW((CTLP)->PCIIO, PCI_STROB); \
- } \
-} while (0)
-
-/***************************************************************************
-Function: sDisAiop
-Purpose: Disable I/O access to an AIOP
-Call: sDisAiop(CltP)
- CONTROLLER_T *CtlP; Ptr to controller structure
- int AiopNum; Number of AIOP on controller
-*/
-#define sDisAiop(CTLP,AIOPNUM) \
-do { \
- (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \
- sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-} while (0)
-
-/***************************************************************************
-Function: sDisCTSFlowCtl
-Purpose: Disable output flow control using CTS
-Call: sDisCTSFlowCtl(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisCTSFlowCtl(ChP) \
-do { \
- (ChP)->TxControl[2] &= ~CTSFC_EN; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisIXANY
-Purpose: Disable IXANY Software Flow Control
-Call: sDisIXANY(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisIXANY(ChP) \
-do { \
- (ChP)->R[0x0e] = 0x86; \
- out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
-} while (0)
-
-/***************************************************************************
-Function: DisParity
-Purpose: Disable parity
-Call: sDisParity(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
- sDisParity(), sSetOddParity(), and sSetEvenParity().
-*/
-#define sDisParity(ChP) \
-do { \
- (ChP)->TxControl[2] &= ~PARITY_EN; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisRTSToggle
-Purpose: Disable RTS toggle
-Call: sDisRTSToggle(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisRTSToggle(ChP) \
-do { \
- (ChP)->TxControl[2] &= ~RTSTOG_EN; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
- (ChP)->rtsToggle = 0; \
-} while (0)
-
-/***************************************************************************
-Function: sDisRxFIFO
-Purpose: Disable Rx FIFO
-Call: sDisRxFIFO(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisRxFIFO(ChP) \
-do { \
- (ChP)->R[0x32] = 0x0a; \
- out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
-} while (0)
-
-/***************************************************************************
-Function: sDisRxStatusMode
-Purpose: Disable the Rx status mode
-Call: sDisRxStatusMode(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: This takes the channel out of the receive status mode. All
- subsequent reads of receive data using sReadRxWord() will return
- two data bytes.
-*/
-#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0)
-
-/***************************************************************************
-Function: sDisTransmit
-Purpose: Disable transmit
-Call: sDisTransmit(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
- This disables movement of Tx data from the Tx FIFO into the 1 byte
- Tx buffer. Therefore there could be up to a 2 byte latency
- between the time sDisTransmit() is called and the transmit buffer
- and transmit shift register going completely empty.
-*/
-#define sDisTransmit(ChP) \
-do { \
- (ChP)->TxControl[3] &= ~TX_ENABLE; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisTxSoftFlowCtl
-Purpose: Disable Tx Software Flow Control
-Call: sDisTxSoftFlowCtl(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisTxSoftFlowCtl(ChP) \
-do { \
- (ChP)->R[0x06] = 0x8a; \
- out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sEnAiop
-Purpose: Enable I/O access to an AIOP
-Call: sEnAiop(CltP)
- CONTROLLER_T *CtlP; Ptr to controller structure
- int AiopNum; Number of AIOP on controller
-*/
-#define sEnAiop(CTLP,AIOPNUM) \
-do { \
- (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \
- sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-} while (0)
-
-/***************************************************************************
-Function: sEnCTSFlowCtl
-Purpose: Enable output flow control using CTS
-Call: sEnCTSFlowCtl(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnCTSFlowCtl(ChP) \
-do { \
- (ChP)->TxControl[2] |= CTSFC_EN; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnIXANY
-Purpose: Enable IXANY Software Flow Control
-Call: sEnIXANY(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnIXANY(ChP) \
-do { \
- (ChP)->R[0x0e] = 0x21; \
- out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
-} while (0)
-
-/***************************************************************************
-Function: EnParity
-Purpose: Enable parity
-Call: sEnParity(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
- sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: Before enabling parity odd or even parity should be chosen using
- functions sSetOddParity() or sSetEvenParity().
-*/
-#define sEnParity(ChP) \
-do { \
- (ChP)->TxControl[2] |= PARITY_EN; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRTSToggle
-Purpose: Enable RTS toggle
-Call: sEnRTSToggle(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function will disable RTS flow control and clear the RTS
- line to allow operation of RTS toggle.
-*/
-#define sEnRTSToggle(ChP) \
-do { \
- (ChP)->RxControl[2] &= ~RTSFC_EN; \
- out32((ChP)->IndexAddr,(ChP)->RxControl); \
- (ChP)->TxControl[2] |= RTSTOG_EN; \
- (ChP)->TxControl[3] &= ~SET_RTS; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
- (ChP)->rtsToggle = 1; \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxFIFO
-Purpose: Enable Rx FIFO
-Call: sEnRxFIFO(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnRxFIFO(ChP) \
-do { \
- (ChP)->R[0x32] = 0x08; \
- out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxProcessor
-Purpose: Enable the receive processor
-Call: sEnRxProcessor(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function is used to start the receive processor. When
- the channel is in the reset state the receive processor is not
- running. This is done to prevent the receive processor from
- executing invalid microcode instructions prior to the
- downloading of the microcode.
-
-Warnings: This function must be called after valid microcode has been
- downloaded to the AIOP, and it must not be called before the
- microcode has been downloaded.
-*/
-#define sEnRxProcessor(ChP) \
-do { \
- (ChP)->RxControl[2] |= RXPROC_EN; \
- out32((ChP)->IndexAddr,(ChP)->RxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxStatusMode
-Purpose: Enable the Rx status mode
-Call: sEnRxStatusMode(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: This places the channel in the receive status mode. All subsequent
- reads of receive data using sReadRxWord() will return a data byte
- in the low word and a status byte in the high word.
-
-*/
-#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE)
-
-/***************************************************************************
-Function: sEnTransmit
-Purpose: Enable transmit
-Call: sEnTransmit(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnTransmit(ChP) \
-do { \
- (ChP)->TxControl[3] |= TX_ENABLE; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnTxSoftFlowCtl
-Purpose: Enable Tx Software Flow Control
-Call: sEnTxSoftFlowCtl(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnTxSoftFlowCtl(ChP) \
-do { \
- (ChP)->R[0x06] = 0xc5; \
- out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sGetAiopIntStatus
-Purpose: Get the AIOP interrupt status
-Call: sGetAiopIntStatus(CtlP,AiopNum)
- CONTROLLER_T *CtlP; Ptr to controller structure
- int AiopNum; AIOP number
-Return: Byte_t: The AIOP interrupt status. Bits 0 through 7
- represent channels 0 through 7 respectively. If a
- bit is set that channel is interrupting.
-*/
-#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM])
-
-/***************************************************************************
-Function: sGetAiopNumChan
-Purpose: Get the number of channels supported by an AIOP
-Call: sGetAiopNumChan(CtlP,AiopNum)
- CONTROLLER_T *CtlP; Ptr to controller structure
- int AiopNum; AIOP number
-Return: int: The number of channels supported by the AIOP
-*/
-#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM]
-
-/***************************************************************************
-Function: sGetChanIntID
-Purpose: Get a channel's interrupt identification byte
-Call: sGetChanIntID(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: Byte_t: The channel interrupt ID. Can be any
- combination of the following flags:
- RXF_TRIG: Rx FIFO trigger level interrupt
- TXFIFO_MT: Tx FIFO empty interrupt
- SRC_INT: Special receive condition interrupt
- DELTA_CD: CD change interrupt
- DELTA_CTS: CTS change interrupt
- DELTA_DSR: DSR change interrupt
-*/
-#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR))
-
-/***************************************************************************
-Function: sGetChanNum
-Purpose: Get the number of a channel within an AIOP
-Call: sGetChanNum(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: int: Channel number within AIOP, or NULLCHAN if channel does
- not exist.
-*/
-#define sGetChanNum(ChP) (ChP)->ChanNum
-
-/***************************************************************************
-Function: sGetChanStatus
-Purpose: Get the channel status
-Call: sGetChanStatus(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: Word_t: The channel status. Can be any combination of
- the following flags:
- LOW BYTE FLAGS
- CTS_ACT: CTS input asserted
- DSR_ACT: DSR input asserted
- CD_ACT: CD input asserted
- TXFIFOMT: Tx FIFO is empty
- TXSHRMT: Tx shift register is empty
- RDA: Rx data available
-
- HIGH BYTE FLAGS
- STATMODE: status mode enable bit
- RXFOVERFL: receive FIFO overflow
- RX2MATCH: receive compare byte 2 match
- RX1MATCH: receive compare byte 1 match
- RXBREAK: received BREAK
- RXFRAME: received framing error
- RXPARITY: received parity error
-Warnings: This function will clear the high byte flags in the Channel
- Status Register.
-*/
-#define sGetChanStatus(ChP) sInW((ChP)->ChanStat)
-
-/***************************************************************************
-Function: sGetChanStatusLo
-Purpose: Get the low byte only of the channel status
-Call: sGetChanStatusLo(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: Byte_t: The channel status low byte. Can be any combination
- of the following flags:
- CTS_ACT: CTS input asserted
- DSR_ACT: DSR input asserted
- CD_ACT: CD input asserted
- TXFIFOMT: Tx FIFO is empty
- TXSHRMT: Tx shift register is empty
- RDA: Rx data available
-*/
-#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat)
-
-/**********************************************************************
- * Get RI status of channel
- * Defined as a function in rocket.c -aes
- */
-#if 0
-#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \
- (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \
- (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \
- (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \
- 0))
-#endif
-
-/***************************************************************************
-Function: sGetControllerIntStatus
-Purpose: Get the controller interrupt status
-Call: sGetControllerIntStatus(CtlP)
- CONTROLLER_T *CtlP; Ptr to controller structure
-Return: Byte_t: The controller interrupt status in the lower 4
- bits. Bits 0 through 3 represent AIOP's 0
- through 3 respectively. If a bit is set that
- AIOP is interrupting. Bits 4 through 7 will
- always be cleared.
-*/
-#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f)
-
-/***************************************************************************
-Function: sPCIGetControllerIntStatus
-Purpose: Get the controller interrupt status
-Call: sPCIGetControllerIntStatus(CtlP)
- CONTROLLER_T *CtlP; Ptr to controller structure
-Return: unsigned char: The controller interrupt status in the lower 4
- bits and bit 4. Bits 0 through 3 represent AIOP's 0
- through 3 respectively. Bit 4 is set if the int
- was generated from periodic. If a bit is set the
- AIOP is interrupting.
-*/
-#define sPCIGetControllerIntStatus(CTLP) \
- ((CTLP)->isUPCI ? \
- (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \
- ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS))
-
-/***************************************************************************
-
-Function: sGetRxCnt
-Purpose: Get the number of data bytes in the Rx FIFO
-Call: sGetRxCnt(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: int: The number of data bytes in the Rx FIFO.
-Comments: Byte read of count register is required to obtain Rx count.
-
-*/
-#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount)
-
-/***************************************************************************
-Function: sGetTxCnt
-Purpose: Get the number of data bytes in the Tx FIFO
-Call: sGetTxCnt(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: Byte_t: The number of data bytes in the Tx FIFO.
-Comments: Byte read of count register is required to obtain Tx count.
-
-*/
-#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount)
-
-/*****************************************************************************
-Function: sGetTxRxDataIO
-Purpose: Get the I/O address of a channel's TxRx Data register
-Call: sGetTxRxDataIO(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Return: WordIO_t: I/O address of a channel's TxRx Data register
-*/
-#define sGetTxRxDataIO(ChP) (ChP)->TxRxData
-
-/***************************************************************************
-Function: sInitChanDefaults
-Purpose: Initialize a channel structure to it's default state.
-Call: sInitChanDefaults(ChP)
- CHANNEL_T *ChP; Ptr to the channel structure
-Comments: This function must be called once for every channel structure
- that exists before any other SSCI calls can be made.
-
-*/
-#define sInitChanDefaults(ChP) \
-do { \
- (ChP)->CtlP = NULLCTLPTR; \
- (ChP)->AiopNum = NULLAIOP; \
- (ChP)->ChanID = AIOPID_NULL; \
- (ChP)->ChanNum = NULLCHAN; \
-} while (0)
-
-/***************************************************************************
-Function: sResetAiopByNum
-Purpose: Reset the AIOP by number
-Call: sResetAiopByNum(CTLP,AIOPNUM)
- CONTROLLER_T CTLP; Ptr to controller structure
- AIOPNUM; AIOP index
-*/
-#define sResetAiopByNum(CTLP,AIOPNUM) \
-do { \
- sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \
- sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \
-} while (0)
-
-/***************************************************************************
-Function: sSendBreak
-Purpose: Send a transmit BREAK signal
-Call: sSendBreak(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSendBreak(ChP) \
-do { \
- (ChP)->TxControl[3] |= SETBREAK; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetBaud
-Purpose: Set baud rate
-Call: sSetBaud(ChP,Divisor)
- CHANNEL_T *ChP; Ptr to channel structure
- Word_t Divisor; 16 bit baud rate divisor for channel
-*/
-#define sSetBaud(ChP,DIVISOR) \
-do { \
- (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \
- (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \
- out32((ChP)->IndexAddr,(ChP)->BaudDiv); \
-} while (0)
-
-/***************************************************************************
-Function: sSetData7
-Purpose: Set data bits to 7
-Call: sSetData7(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetData7(ChP) \
-do { \
- (ChP)->TxControl[2] &= ~DATA8BIT; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetData8
-Purpose: Set data bits to 8
-Call: sSetData8(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetData8(ChP) \
-do { \
- (ChP)->TxControl[2] |= DATA8BIT; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetDTR
-Purpose: Set the DTR output
-Call: sSetDTR(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetDTR(ChP) \
-do { \
- (ChP)->TxControl[3] |= SET_DTR; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetEvenParity
-Purpose: Set even parity
-Call: sSetEvenParity(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
- sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: This function has no effect unless parity is enabled with function
- sEnParity().
-*/
-#define sSetEvenParity(ChP) \
-do { \
- (ChP)->TxControl[2] |= EVEN_PAR; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetOddParity
-Purpose: Set odd parity
-Call: sSetOddParity(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
- sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: This function has no effect unless parity is enabled with function
- sEnParity().
-*/
-#define sSetOddParity(ChP) \
-do { \
- (ChP)->TxControl[2] &= ~EVEN_PAR; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetRTS
-Purpose: Set the RTS output
-Call: sSetRTS(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetRTS(ChP) \
-do { \
- if ((ChP)->rtsToggle) break; \
- (ChP)->TxControl[3] |= SET_RTS; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetRxTrigger
-Purpose: Set the Rx FIFO trigger level
-Call: sSetRxProcessor(ChP,Level)
- CHANNEL_T *ChP; Ptr to channel structure
- Byte_t Level; Number of characters in Rx FIFO at which the
- interrupt will be generated. Can be any of the following flags:
-
- TRIG_NO: no trigger
- TRIG_1: 1 character in FIFO
- TRIG_1_2: FIFO 1/2 full
- TRIG_7_8: FIFO 7/8 full
-Comments: An interrupt will be generated when the trigger level is reached
- only if function sEnInterrupt() has been called with flag
- RXINT_EN set. The RXF_TRIG flag in the Interrupt Idenfification
- register will be set whenever the trigger level is reached
- regardless of the setting of RXINT_EN.
-
-*/
-#define sSetRxTrigger(ChP,LEVEL) \
-do { \
- (ChP)->RxControl[2] &= ~TRIG_MASK; \
- (ChP)->RxControl[2] |= LEVEL; \
- out32((ChP)->IndexAddr,(ChP)->RxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetStop1
-Purpose: Set stop bits to 1
-Call: sSetStop1(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetStop1(ChP) \
-do { \
- (ChP)->TxControl[2] &= ~STOP2; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetStop2
-Purpose: Set stop bits to 2
-Call: sSetStop2(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetStop2(ChP) \
-do { \
- (ChP)->TxControl[2] |= STOP2; \
- out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetTxXOFFChar
-Purpose: Set the Tx XOFF flow control character
-Call: sSetTxXOFFChar(ChP,Ch)
- CHANNEL_T *ChP; Ptr to channel structure
- Byte_t Ch; The value to set the Tx XOFF character to
-*/
-#define sSetTxXOFFChar(ChP,CH) \
-do { \
- (ChP)->R[0x07] = (CH); \
- out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sSetTxXONChar
-Purpose: Set the Tx XON flow control character
-Call: sSetTxXONChar(ChP,Ch)
- CHANNEL_T *ChP; Ptr to channel structure
- Byte_t Ch; The value to set the Tx XON character to
-*/
-#define sSetTxXONChar(ChP,CH) \
-do { \
- (ChP)->R[0x0b] = (CH); \
- out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \
-} while (0)
-
-/***************************************************************************
-Function: sStartRxProcessor
-Purpose: Start a channel's receive processor
-Call: sStartRxProcessor(ChP)
- CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function is used to start a Rx processor after it was
- stopped with sStopRxProcessor() or sStopSWInFlowCtl(). It
- will restart both the Rx processor and software input flow control.
-
-*/
-#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0])
-
-/***************************************************************************
-Function: sWriteTxByte
-Purpose: Write a transmit data byte to a channel.
- ByteIO_t io: Channel transmit register I/O address. This can
- be obtained with sGetTxRxDataIO().
- Byte_t Data; The transmit data byte.
-Warnings: This function writes the data byte without checking to see if
- sMaxTxSize is exceeded in the Tx FIFO.
-*/
-#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
-
-/*
- * Begin Linux specific definitions for the Rocketport driver
- *
- * This code is Copyright Theodore Ts'o, 1995-1997
- */
-
-struct r_port {
- int magic;
- struct tty_port port;
- int line;
- int flags; /* Don't yet match the ASY_ flags!! */
- unsigned int board:3;
- unsigned int aiop:2;
- unsigned int chan:3;
- CONTROLLER_t *ctlp;
- CHANNEL_t channel;
- int intmask;
- int xmit_fifo_room; /* room in xmit fifo */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- int cd_status;
- int ignore_status_mask;
- int read_status_mask;
- int cps;
-
- spinlock_t slock;
- struct mutex write_mtx;
-};
-
-#define RPORT_MAGIC 0x525001
-
-#define NUM_BOARDS 8
-#define MAX_RP_PORTS (32*NUM_BOARDS)
-
-/*
- * The size of the xmit buffer is 1 page, or 4096 bytes
- */
-#define XMIT_BUF_SIZE 4096
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/*
- * Assigned major numbers for the Comtrol Rocketport
- */
-#define TTY_ROCKET_MAJOR 46
-#define CUA_ROCKET_MAJOR 47
-
-#ifdef PCI_VENDOR_ID_RP
-#undef PCI_VENDOR_ID_RP
-#undef PCI_DEVICE_ID_RP8OCTA
-#undef PCI_DEVICE_ID_RP8INTF
-#undef PCI_DEVICE_ID_RP16INTF
-#undef PCI_DEVICE_ID_RP32INTF
-#undef PCI_DEVICE_ID_URP8OCTA
-#undef PCI_DEVICE_ID_URP8INTF
-#undef PCI_DEVICE_ID_URP16INTF
-#undef PCI_DEVICE_ID_CRP16INTF
-#undef PCI_DEVICE_ID_URP32INTF
-#endif
-
-/* Comtrol PCI Vendor ID */
-#define PCI_VENDOR_ID_RP 0x11fe
-
-/* Comtrol Device ID's */
-#define PCI_DEVICE_ID_RP32INTF 0x0001 /* Rocketport 32 port w/external I/F */
-#define PCI_DEVICE_ID_RP8INTF 0x0002 /* Rocketport 8 port w/external I/F */
-#define PCI_DEVICE_ID_RP16INTF 0x0003 /* Rocketport 16 port w/external I/F */
-#define PCI_DEVICE_ID_RP4QUAD 0x0004 /* Rocketport 4 port w/quad cable */
-#define PCI_DEVICE_ID_RP8OCTA 0x0005 /* Rocketport 8 port w/octa cable */
-#define PCI_DEVICE_ID_RP8J 0x0006 /* Rocketport 8 port w/RJ11 connectors */
-#define PCI_DEVICE_ID_RP4J 0x0007 /* Rocketport 4 port w/RJ11 connectors */
-#define PCI_DEVICE_ID_RP8SNI 0x0008 /* Rocketport 8 port w/ DB78 SNI (Siemens) connector */
-#define PCI_DEVICE_ID_RP16SNI 0x0009 /* Rocketport 16 port w/ DB78 SNI (Siemens) connector */
-#define PCI_DEVICE_ID_RPP4 0x000A /* Rocketport Plus 4 port */
-#define PCI_DEVICE_ID_RPP8 0x000B /* Rocketport Plus 8 port */
-#define PCI_DEVICE_ID_RP6M 0x000C /* RocketModem 6 port */
-#define PCI_DEVICE_ID_RP4M 0x000D /* RocketModem 4 port */
-#define PCI_DEVICE_ID_RP2_232 0x000E /* Rocketport Plus 2 port RS232 */
-#define PCI_DEVICE_ID_RP2_422 0x000F /* Rocketport Plus 2 port RS422 */
-
-/* Universal PCI boards */
-#define PCI_DEVICE_ID_URP32INTF 0x0801 /* Rocketport UPCI 32 port w/external I/F */
-#define PCI_DEVICE_ID_URP8INTF 0x0802 /* Rocketport UPCI 8 port w/external I/F */
-#define PCI_DEVICE_ID_URP16INTF 0x0803 /* Rocketport UPCI 16 port w/external I/F */
-#define PCI_DEVICE_ID_URP8OCTA 0x0805 /* Rocketport UPCI 8 port w/octa cable */
-#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C /* Rocketmodem III 8 port */
-#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D /* Rocketmodem III 4 port */
-
-/* Compact PCI device */
-#define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */
-
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index c33e02cbde93..61550f24a2d3 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -28,6 +28,10 @@
#define ASPEED_VUART_ADDRL 0x28
#define ASPEED_VUART_ADDRH 0x2c
+#define ASPEED_VUART_DEFAULT_LPC_ADDR 0x3f8
+#define ASPEED_VUART_DEFAULT_SIRQ 4
+#define ASPEED_VUART_DEFAULT_SIRQ_POLARITY IRQ_TYPE_LEVEL_LOW
+
struct aspeed_vuart {
struct device *dev;
void __iomem *regs;
@@ -72,22 +76,31 @@ static ssize_t lpc_address_show(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
}
+static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
+{
+ if (addr > U16_MAX)
+ return -EINVAL;
+
+ writeb(addr >> 8, vuart->regs + ASPEED_VUART_ADDRH);
+ writeb(addr >> 0, vuart->regs + ASPEED_VUART_ADDRL);
+
+ return 0;
+}
+
static ssize_t lpc_address_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
- unsigned long val;
+ u32 val;
int err;
- err = kstrtoul(buf, 0, &val);
+ err = kstrtou32(buf, 0, &val);
if (err)
return err;
- writeb(val >> 8, vuart->regs + ASPEED_VUART_ADDRH);
- writeb(val >> 0, vuart->regs + ASPEED_VUART_ADDRL);
-
- return count;
+ err = aspeed_vuart_set_lpc_address(vuart, val);
+ return err ? : count;
}
static DEVICE_ATTR_RW(lpc_address);
@@ -105,27 +118,37 @@ static ssize_t sirq_show(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
}
+static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
+{
+ u8 reg;
+
+ if (sirq > (ASPEED_VUART_GCRB_HOST_SIRQ_MASK >> ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT))
+ return -EINVAL;
+
+ sirq <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
+ sirq &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
+
+ reg = readb(vuart->regs + ASPEED_VUART_GCRB);
+ reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
+ reg |= sirq;
+ writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
+
+ return 0;
+}
+
static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct aspeed_vuart *vuart = dev_get_drvdata(dev);
unsigned long val;
int err;
- u8 reg;
err = kstrtoul(buf, 0, &val);
if (err)
return err;
- val <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
- val &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
-
- reg = readb(vuart->regs + ASPEED_VUART_GCRB);
- reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
- reg |= val;
- writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
-
- return count;
+ err = aspeed_vuart_set_sirq(vuart, val);
+ return err ? : count;
}
static DEVICE_ATTR_RW(sirq);
@@ -297,7 +320,6 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned int iir, lsr;
- unsigned long flags;
int space, count;
iir = serial_port_in(port, UART_IIR);
@@ -305,7 +327,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
if (iir & UART_IIR_NO_INT)
return 0;
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock(&port->lock);
lsr = serial_port_in(port, UART_LSR);
@@ -341,7 +363,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
if (lsr & UART_LSR_THRE)
serial8250_tx_chars(up);
- uart_unlock_and_check_sysrq(port, flags);
+ uart_unlock_and_check_sysrq(port);
return 1;
}
@@ -367,6 +389,18 @@ static void aspeed_vuart_auto_configure_sirq_polarity(
aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
}
+static int aspeed_vuart_map_irq_polarity(u32 dt)
+{
+ switch (dt) {
+ case IRQ_TYPE_LEVEL_LOW:
+ return 0;
+ case IRQ_TYPE_LEVEL_HIGH:
+ return 1;
+ default:
+ return -EINVAL;
+ }
+}
+
static int aspeed_vuart_probe(struct platform_device *pdev)
{
struct of_phandle_args sirq_polarity_sense_args;
@@ -374,8 +408,8 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
struct aspeed_vuart *vuart;
struct device_node *np;
struct resource *res;
- u32 clk, prop;
- int rc;
+ u32 clk, prop, sirq[2];
+ int rc, sirq_polarity;
np = pdev->dev.of_node;
@@ -482,6 +516,37 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
of_node_put(sirq_polarity_sense_args.np);
}
+ rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &prop);
+ if (rc < 0)
+ prop = ASPEED_VUART_DEFAULT_LPC_ADDR;
+
+ rc = aspeed_vuart_set_lpc_address(vuart, prop);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "invalid value in aspeed,lpc-io-reg property\n");
+ goto err_clk_disable;
+ }
+
+ rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2);
+ if (rc < 0) {
+ sirq[0] = ASPEED_VUART_DEFAULT_SIRQ;
+ sirq[1] = ASPEED_VUART_DEFAULT_SIRQ_POLARITY;
+ }
+
+ rc = aspeed_vuart_set_sirq(vuart, sirq[0]);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "invalid sirq number in aspeed,lpc-interrupts property\n");
+ goto err_clk_disable;
+ }
+
+ sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]);
+ if (sirq_polarity < 0) {
+ dev_err(&pdev->dev, "invalid sirq polarity in aspeed,lpc-interrupts property\n");
+ rc = sirq_polarity;
+ goto err_clk_disable;
+ }
+
+ aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity);
+
aspeed_vuart_set_enabled(vuart, true);
aspeed_vuart_set_host_tx_discard(vuart, true);
platform_set_drvdata(pdev, vuart);
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
new file mode 100644
index 000000000000..725a450058f8
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -0,0 +1,1202 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2020, Broadcom */
+/*
+ * 8250-core based driver for Broadcom ns16550a UARTs
+ *
+ * This driver uses the standard 8250 driver core but adds additional
+ * optional features including the ability to use a baud rate clock
+ * mux for more accurate high speed baud rate selection and also
+ * an optional DMA engine.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+
+#include "8250.h"
+
+/* Register definitions for UART DMA block. Version 1.1 or later. */
+#define UDMA_ARB_RX 0x00
+#define UDMA_ARB_TX 0x04
+#define UDMA_ARB_REQ 0x00000001
+#define UDMA_ARB_GRANT 0x00000002
+
+#define UDMA_RX_REVISION 0x00
+#define UDMA_RX_REVISION_REQUIRED 0x00000101
+#define UDMA_RX_CTRL 0x04
+#define UDMA_RX_CTRL_BUF_CLOSE_MODE 0x00010000
+#define UDMA_RX_CTRL_MASK_WR_DONE 0x00008000
+#define UDMA_RX_CTRL_ENDIAN_OVERRIDE 0x00004000
+#define UDMA_RX_CTRL_ENDIAN 0x00002000
+#define UDMA_RX_CTRL_OE_IS_ERR 0x00001000
+#define UDMA_RX_CTRL_PE_IS_ERR 0x00000800
+#define UDMA_RX_CTRL_FE_IS_ERR 0x00000400
+#define UDMA_RX_CTRL_NUM_BUF_USED_MASK 0x000003c0
+#define UDMA_RX_CTRL_NUM_BUF_USED_SHIFT 6
+#define UDMA_RX_CTRL_BUF_CLOSE_CLK_SEL_SYS 0x00000020
+#define UDMA_RX_CTRL_BUF_CLOSE_ENA 0x00000010
+#define UDMA_RX_CTRL_TIMEOUT_CLK_SEL_SYS 0x00000008
+#define UDMA_RX_CTRL_TIMEOUT_ENA 0x00000004
+#define UDMA_RX_CTRL_ABORT 0x00000002
+#define UDMA_RX_CTRL_ENA 0x00000001
+#define UDMA_RX_STATUS 0x08
+#define UDMA_RX_STATUS_ACTIVE_BUF_MASK 0x0000000f
+#define UDMA_RX_TRANSFER_LEN 0x0c
+#define UDMA_RX_TRANSFER_TOTAL 0x10
+#define UDMA_RX_BUFFER_SIZE 0x14
+#define UDMA_RX_SRC_ADDR 0x18
+#define UDMA_RX_TIMEOUT 0x1c
+#define UDMA_RX_BUFFER_CLOSE 0x20
+#define UDMA_RX_BLOCKOUT_COUNTER 0x24
+#define UDMA_RX_BUF0_PTR_LO 0x28
+#define UDMA_RX_BUF0_PTR_HI 0x2c
+#define UDMA_RX_BUF0_STATUS 0x30
+#define UDMA_RX_BUFX_STATUS_OVERRUN_ERR 0x00000010
+#define UDMA_RX_BUFX_STATUS_FRAME_ERR 0x00000008
+#define UDMA_RX_BUFX_STATUS_PARITY_ERR 0x00000004
+#define UDMA_RX_BUFX_STATUS_CLOSE_EXPIRED 0x00000002
+#define UDMA_RX_BUFX_STATUS_DATA_RDY 0x00000001
+#define UDMA_RX_BUF0_DATA_LEN 0x34
+#define UDMA_RX_BUF1_PTR_LO 0x38
+#define UDMA_RX_BUF1_PTR_HI 0x3c
+#define UDMA_RX_BUF1_STATUS 0x40
+#define UDMA_RX_BUF1_DATA_LEN 0x44
+
+#define UDMA_TX_REVISION 0x00
+#define UDMA_TX_REVISION_REQUIRED 0x00000101
+#define UDMA_TX_CTRL 0x04
+#define UDMA_TX_CTRL_ENDIAN_OVERRIDE 0x00000080
+#define UDMA_TX_CTRL_ENDIAN 0x00000040
+#define UDMA_TX_CTRL_NUM_BUF_USED_MASK 0x00000030
+#define UDMA_TX_CTRL_NUM_BUF_USED_1 0x00000010
+#define UDMA_TX_CTRL_ABORT 0x00000002
+#define UDMA_TX_CTRL_ENA 0x00000001
+#define UDMA_TX_DST_ADDR 0x08
+#define UDMA_TX_BLOCKOUT_COUNTER 0x10
+#define UDMA_TX_TRANSFER_LEN 0x14
+#define UDMA_TX_TRANSFER_TOTAL 0x18
+#define UDMA_TX_STATUS 0x20
+#define UDMA_TX_BUF0_PTR_LO 0x24
+#define UDMA_TX_BUF0_PTR_HI 0x28
+#define UDMA_TX_BUF0_STATUS 0x2c
+#define UDMA_TX_BUFX_LAST 0x00000002
+#define UDMA_TX_BUFX_EMPTY 0x00000001
+#define UDMA_TX_BUF0_DATA_LEN 0x30
+#define UDMA_TX_BUF0_DATA_SENT 0x34
+#define UDMA_TX_BUF1_PTR_LO 0x38
+
+#define UDMA_INTR_STATUS 0x00
+#define UDMA_INTR_ARB_TX_GRANT 0x00040000
+#define UDMA_INTR_ARB_RX_GRANT 0x00020000
+#define UDMA_INTR_TX_ALL_EMPTY 0x00010000
+#define UDMA_INTR_TX_EMPTY_BUF1 0x00008000
+#define UDMA_INTR_TX_EMPTY_BUF0 0x00004000
+#define UDMA_INTR_TX_ABORT 0x00002000
+#define UDMA_INTR_TX_DONE 0x00001000
+#define UDMA_INTR_RX_ERROR 0x00000800
+#define UDMA_INTR_RX_TIMEOUT 0x00000400
+#define UDMA_INTR_RX_READY_BUF7 0x00000200
+#define UDMA_INTR_RX_READY_BUF6 0x00000100
+#define UDMA_INTR_RX_READY_BUF5 0x00000080
+#define UDMA_INTR_RX_READY_BUF4 0x00000040
+#define UDMA_INTR_RX_READY_BUF3 0x00000020
+#define UDMA_INTR_RX_READY_BUF2 0x00000010
+#define UDMA_INTR_RX_READY_BUF1 0x00000008
+#define UDMA_INTR_RX_READY_BUF0 0x00000004
+#define UDMA_INTR_RX_READY_MASK 0x000003fc
+#define UDMA_INTR_RX_READY_SHIFT 2
+#define UDMA_INTR_RX_ABORT 0x00000002
+#define UDMA_INTR_RX_DONE 0x00000001
+#define UDMA_INTR_SET 0x04
+#define UDMA_INTR_CLEAR 0x08
+#define UDMA_INTR_MASK_STATUS 0x0c
+#define UDMA_INTR_MASK_SET 0x10
+#define UDMA_INTR_MASK_CLEAR 0x14
+
+
+#define UDMA_RX_INTERRUPTS ( \
+ UDMA_INTR_RX_ERROR | \
+ UDMA_INTR_RX_TIMEOUT | \
+ UDMA_INTR_RX_READY_BUF0 | \
+ UDMA_INTR_RX_READY_BUF1 | \
+ UDMA_INTR_RX_READY_BUF2 | \
+ UDMA_INTR_RX_READY_BUF3 | \
+ UDMA_INTR_RX_READY_BUF4 | \
+ UDMA_INTR_RX_READY_BUF5 | \
+ UDMA_INTR_RX_READY_BUF6 | \
+ UDMA_INTR_RX_READY_BUF7 | \
+ UDMA_INTR_RX_ABORT | \
+ UDMA_INTR_RX_DONE)
+
+#define UDMA_RX_ERR_INTERRUPTS ( \
+ UDMA_INTR_RX_ERROR | \
+ UDMA_INTR_RX_TIMEOUT | \
+ UDMA_INTR_RX_ABORT | \
+ UDMA_INTR_RX_DONE)
+
+#define UDMA_TX_INTERRUPTS ( \
+ UDMA_INTR_TX_ABORT | \
+ UDMA_INTR_TX_DONE)
+
+#define UDMA_IS_RX_INTERRUPT(status) ((status) & UDMA_RX_INTERRUPTS)
+#define UDMA_IS_TX_INTERRUPT(status) ((status) & UDMA_TX_INTERRUPTS)
+
+
+/* Current devices have 8 sets of RX buffer registers */
+#define UDMA_RX_BUFS_COUNT 8
+#define UDMA_RX_BUFS_REG_OFFSET (UDMA_RX_BUF1_PTR_LO - UDMA_RX_BUF0_PTR_LO)
+#define UDMA_RX_BUFx_PTR_LO(x) (UDMA_RX_BUF0_PTR_LO + \
+ ((x) * UDMA_RX_BUFS_REG_OFFSET))
+#define UDMA_RX_BUFx_PTR_HI(x) (UDMA_RX_BUF0_PTR_HI + \
+ ((x) * UDMA_RX_BUFS_REG_OFFSET))
+#define UDMA_RX_BUFx_STATUS(x) (UDMA_RX_BUF0_STATUS + \
+ ((x) * UDMA_RX_BUFS_REG_OFFSET))
+#define UDMA_RX_BUFx_DATA_LEN(x) (UDMA_RX_BUF0_DATA_LEN + \
+ ((x) * UDMA_RX_BUFS_REG_OFFSET))
+
+/* Current devices have 2 sets of TX buffer registers */
+#define UDMA_TX_BUFS_COUNT 2
+#define UDMA_TX_BUFS_REG_OFFSET (UDMA_TX_BUF1_PTR_LO - UDMA_TX_BUF0_PTR_LO)
+#define UDMA_TX_BUFx_PTR_LO(x) (UDMA_TX_BUF0_PTR_LO + \
+ ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_PTR_HI(x) (UDMA_TX_BUF0_PTR_HI + \
+ ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_STATUS(x) (UDMA_TX_BUF0_STATUS + \
+ ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_DATA_LEN(x) (UDMA_TX_BUF0_DATA_LEN + \
+ ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define UDMA_TX_BUFx_DATA_SENT(x) (UDMA_TX_BUF0_DATA_SENT + \
+ ((x) * UDMA_TX_BUFS_REG_OFFSET))
+#define REGS_8250 0
+#define REGS_DMA_RX 1
+#define REGS_DMA_TX 2
+#define REGS_DMA_ISR 3
+#define REGS_DMA_ARB 4
+#define REGS_MAX 5
+
+#define TX_BUF_SIZE 4096
+#define RX_BUF_SIZE 4096
+#define RX_BUFS_COUNT 2
+#define KHZ 1000
+#define MHZ(x) ((x) * KHZ * KHZ)
+
+static const u32 brcmstb_rate_table[] = {
+ MHZ(81),
+ MHZ(108),
+ MHZ(64), /* Actually 64285715 for some chips */
+ MHZ(48),
+};
+
+static const u32 brcmstb_rate_table_7278[] = {
+ MHZ(81),
+ MHZ(108),
+ 0,
+ MHZ(48),
+};
+
+struct brcmuart_priv {
+ int line;
+ struct clk *baud_mux_clk;
+ unsigned long default_mux_rate;
+ u32 real_rates[ARRAY_SIZE(brcmstb_rate_table)];
+ const u32 *rate_table;
+ ktime_t char_wait;
+ struct uart_port *up;
+ struct hrtimer hrt;
+ bool shutdown;
+ bool dma_enabled;
+ struct uart_8250_dma dma;
+ void __iomem *regs[REGS_MAX];
+ dma_addr_t rx_addr;
+ void *rx_bufs;
+ size_t rx_size;
+ int rx_next_buf;
+ dma_addr_t tx_addr;
+ void *tx_buf;
+ size_t tx_size;
+ bool tx_running;
+ bool rx_running;
+ struct dentry *debugfs_dir;
+
+ /* stats exposed through debugfs */
+ u64 dma_rx_partial_buf;
+ u64 dma_rx_full_buf;
+ u32 rx_bad_timeout_late_char;
+ u32 rx_bad_timeout_no_char;
+ u32 rx_missing_close_timeout;
+ u32 rx_err;
+ u32 rx_timeout;
+ u32 rx_abort;
+};
+
+static struct dentry *brcmuart_debugfs_root;
+
+/*
+ * Register access routines
+ */
+static u32 udma_readl(struct brcmuart_priv *priv,
+ int reg_type, int offset)
+{
+ return readl(priv->regs[reg_type] + offset);
+}
+
+static void udma_writel(struct brcmuart_priv *priv,
+ int reg_type, int offset, u32 value)
+{
+ writel(value, priv->regs[reg_type] + offset);
+}
+
+static void udma_set(struct brcmuart_priv *priv,
+ int reg_type, int offset, u32 bits)
+{
+ void __iomem *reg = priv->regs[reg_type] + offset;
+ u32 value;
+
+ value = readl(reg);
+ value |= bits;
+ writel(value, reg);
+}
+
+static void udma_unset(struct brcmuart_priv *priv,
+ int reg_type, int offset, u32 bits)
+{
+ void __iomem *reg = priv->regs[reg_type] + offset;
+ u32 value;
+
+ value = readl(reg);
+ value &= ~bits;
+ writel(value, reg);
+}
+
+/*
+ * The UART DMA engine hardware can be used by multiple UARTS, but
+ * only one at a time. Sharing is not currently supported so
+ * the first UART to request the DMA engine will get it and any
+ * subsequent requests by other UARTS will fail.
+ */
+static int brcmuart_arbitration(struct brcmuart_priv *priv, bool acquire)
+{
+ u32 rx_grant;
+ u32 tx_grant;
+ int waits;
+ int ret = 0;
+
+ if (acquire) {
+ udma_set(priv, REGS_DMA_ARB, UDMA_ARB_RX, UDMA_ARB_REQ);
+ udma_set(priv, REGS_DMA_ARB, UDMA_ARB_TX, UDMA_ARB_REQ);
+
+ waits = 1;
+ while (1) {
+ rx_grant = udma_readl(priv, REGS_DMA_ARB, UDMA_ARB_RX);
+ tx_grant = udma_readl(priv, REGS_DMA_ARB, UDMA_ARB_TX);
+ if (rx_grant & tx_grant & UDMA_ARB_GRANT)
+ return 0;
+ if (waits-- == 0)
+ break;
+ msleep(1);
+ }
+ ret = 1;
+ }
+
+ udma_unset(priv, REGS_DMA_ARB, UDMA_ARB_RX, UDMA_ARB_REQ);
+ udma_unset(priv, REGS_DMA_ARB, UDMA_ARB_TX, UDMA_ARB_REQ);
+ return ret;
+}
+
+static void brcmuart_init_dma_hardware(struct brcmuart_priv *priv)
+{
+ u32 daddr;
+ u32 value;
+ int x;
+
+ /* Start with all interrupts disabled */
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_MASK_SET, 0xffffffff);
+
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_BUFFER_SIZE, RX_BUF_SIZE);
+
+ /*
+ * Setup buffer close to happen when 32 character times have
+ * elapsed since the last character was received.
+ */
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_BUFFER_CLOSE, 16*10*32);
+ value = (RX_BUFS_COUNT << UDMA_RX_CTRL_NUM_BUF_USED_SHIFT)
+ | UDMA_RX_CTRL_BUF_CLOSE_MODE
+ | UDMA_RX_CTRL_BUF_CLOSE_ENA;
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_CTRL, value);
+
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_BLOCKOUT_COUNTER, 0);
+ daddr = priv->rx_addr;
+ for (x = 0; x < RX_BUFS_COUNT; x++) {
+
+ /* Set RX transfer length to 0 for unknown */
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_TRANSFER_LEN, 0);
+
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_BUFx_PTR_LO(x),
+ lower_32_bits(daddr));
+ udma_writel(priv, REGS_DMA_RX, UDMA_RX_BUFx_PTR_HI(x),
+ upper_32_bits(daddr));
+ daddr += RX_BUF_SIZE;
+ }
+
+ daddr = priv->tx_addr;
+ udma_writel(priv, REGS_DMA_TX, UDMA_TX_BUFx_PTR_LO(0),
+ lower_32_bits(daddr));
+ udma_writel(priv, REGS_DMA_TX, UDMA_TX_BUFx_PTR_HI(0),
+ upper_32_bits(daddr));
+ udma_writel(priv, REGS_DMA_TX, UDMA_TX_CTRL,
+ UDMA_TX_CTRL_NUM_BUF_USED_1);
+
+ /* clear all interrupts then enable them */
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_CLEAR, 0xffffffff);
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_MASK_CLEAR,
+ UDMA_RX_INTERRUPTS | UDMA_TX_INTERRUPTS);
+
+}
+
+static void start_rx_dma(struct uart_8250_port *p)
+{
+ struct brcmuart_priv *priv = p->port.private_data;
+ int x;
+
+ udma_unset(priv, REGS_DMA_RX, UDMA_RX_CTRL, UDMA_RX_CTRL_ENA);
+
+ /* Clear the RX ready bit for all buffers */
+ for (x = 0; x < RX_BUFS_COUNT; x++)
+ udma_unset(priv, REGS_DMA_RX, UDMA_RX_BUFx_STATUS(x),
+ UDMA_RX_BUFX_STATUS_DATA_RDY);
+
+ /* always start with buffer 0 */
+ udma_unset(priv, REGS_DMA_RX, UDMA_RX_STATUS,
+ UDMA_RX_STATUS_ACTIVE_BUF_MASK);
+ priv->rx_next_buf = 0;
+
+ udma_set(priv, REGS_DMA_RX, UDMA_RX_CTRL, UDMA_RX_CTRL_ENA);
+ priv->rx_running = true;
+}
+
+static void stop_rx_dma(struct uart_8250_port *p)
+{
+ struct brcmuart_priv *priv = p->port.private_data;
+
+ /* If RX is running, set the RX ABORT */
+ if (priv->rx_running)
+ udma_set(priv, REGS_DMA_RX, UDMA_RX_CTRL, UDMA_RX_CTRL_ABORT);
+}
+
+static int stop_tx_dma(struct uart_8250_port *p)
+{
+ struct brcmuart_priv *priv = p->port.private_data;
+ u32 value;
+
+ /* If TX is running, set the TX ABORT */
+ value = udma_readl(priv, REGS_DMA_TX, UDMA_TX_CTRL);
+ if (value & UDMA_TX_CTRL_ENA)
+ udma_set(priv, REGS_DMA_TX, UDMA_TX_CTRL, UDMA_TX_CTRL_ABORT);
+ priv->tx_running = false;
+ return 0;
+}
+
+/*
+ * NOTE: printk's in this routine will hang the system if this is
+ * the console tty
+ */
+static int brcmuart_tx_dma(struct uart_8250_port *p)
+{
+ struct brcmuart_priv *priv = p->port.private_data;
+ struct circ_buf *xmit = &p->port.state->xmit;
+ u32 tx_size;
+
+ if (uart_tx_stopped(&p->port) || priv->tx_running ||
+ uart_circ_empty(xmit)) {
+ return 0;
+ }
+ tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
+
+ priv->dma.tx_err = 0;
+ memcpy(priv->tx_buf, &xmit->buf[xmit->tail], tx_size);
+ xmit->tail += tx_size;
+ xmit->tail &= UART_XMIT_SIZE - 1;
+ p->port.icount.tx += tx_size;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&p->port);
+
+ udma_writel(priv, REGS_DMA_TX, UDMA_TX_TRANSFER_LEN, tx_size);
+ udma_writel(priv, REGS_DMA_TX, UDMA_TX_BUF0_DATA_LEN, tx_size);
+ udma_unset(priv, REGS_DMA_TX, UDMA_TX_BUF0_STATUS, UDMA_TX_BUFX_EMPTY);
+ udma_set(priv, REGS_DMA_TX, UDMA_TX_CTRL, UDMA_TX_CTRL_ENA);
+ priv->tx_running = true;
+
+ return 0;
+}
+
+static void brcmuart_rx_buf_done_isr(struct uart_port *up, int index)
+{
+ struct brcmuart_priv *priv = up->private_data;
+ struct tty_port *tty_port = &up->state->port;
+ u32 status;
+ u32 length;
+ u32 copied;
+
+ /* Make sure we're still in sync with the hardware */
+ status = udma_readl(priv, REGS_DMA_RX, UDMA_RX_BUFx_STATUS(index));
+ length = udma_readl(priv, REGS_DMA_RX, UDMA_RX_BUFx_DATA_LEN(index));
+
+ if ((status & UDMA_RX_BUFX_STATUS_DATA_RDY) == 0) {
+ dev_err(up->dev, "RX done interrupt but DATA_RDY not found\n");
+ return;
+ }
+ if (status & (UDMA_RX_BUFX_STATUS_OVERRUN_ERR |
+ UDMA_RX_BUFX_STATUS_FRAME_ERR |
+ UDMA_RX_BUFX_STATUS_PARITY_ERR)) {
+ if (status & UDMA_RX_BUFX_STATUS_OVERRUN_ERR) {
+ up->icount.overrun++;
+ dev_warn(up->dev, "RX OVERRUN Error\n");
+ }
+ if (status & UDMA_RX_BUFX_STATUS_FRAME_ERR) {
+ up->icount.frame++;
+ dev_warn(up->dev, "RX FRAMING Error\n");
+ }
+ if (status & UDMA_RX_BUFX_STATUS_PARITY_ERR) {
+ up->icount.parity++;
+ dev_warn(up->dev, "RX PARITY Error\n");
+ }
+ }
+ copied = (u32)tty_insert_flip_string(
+ tty_port,
+ priv->rx_bufs + (index * RX_BUF_SIZE),
+ length);
+ if (copied != length) {
+ dev_warn(up->dev, "Flip buffer overrun of %d bytes\n",
+ length - copied);
+ up->icount.overrun += length - copied;
+ }
+ up->icount.rx += length;
+ if (status & UDMA_RX_BUFX_STATUS_CLOSE_EXPIRED)
+ priv->dma_rx_partial_buf++;
+ else if (length != RX_BUF_SIZE)
+ /*
+ * This is a bug in the controller that doesn't cause
+ * any problems but will be fixed in the future.
+ */
+ priv->rx_missing_close_timeout++;
+ else
+ priv->dma_rx_full_buf++;
+
+ tty_flip_buffer_push(tty_port);
+}
+
+static void brcmuart_rx_isr(struct uart_port *up, u32 rx_isr)
+{
+ struct brcmuart_priv *priv = up->private_data;
+ struct device *dev = up->dev;
+ u32 rx_done_isr;
+ u32 check_isr;
+
+ rx_done_isr = (rx_isr & UDMA_INTR_RX_READY_MASK);
+ while (rx_done_isr) {
+ check_isr = UDMA_INTR_RX_READY_BUF0 << priv->rx_next_buf;
+ if (check_isr & rx_done_isr) {
+ brcmuart_rx_buf_done_isr(up, priv->rx_next_buf);
+ } else {
+ dev_err(dev,
+ "RX buffer ready out of sequence, restarting RX DMA\n");
+ start_rx_dma(up_to_u8250p(up));
+ break;
+ }
+ if (rx_isr & UDMA_RX_ERR_INTERRUPTS) {
+ if (rx_isr & UDMA_INTR_RX_ERROR)
+ priv->rx_err++;
+ if (rx_isr & UDMA_INTR_RX_TIMEOUT) {
+ priv->rx_timeout++;
+ dev_err(dev, "RX TIMEOUT Error\n");
+ }
+ if (rx_isr & UDMA_INTR_RX_ABORT)
+ priv->rx_abort++;
+ priv->rx_running = false;
+ }
+ /* If not ABORT, re-enable RX buffer */
+ if (!(rx_isr & UDMA_INTR_RX_ABORT))
+ udma_unset(priv, REGS_DMA_RX,
+ UDMA_RX_BUFx_STATUS(priv->rx_next_buf),
+ UDMA_RX_BUFX_STATUS_DATA_RDY);
+ rx_done_isr &= ~check_isr;
+ priv->rx_next_buf++;
+ if (priv->rx_next_buf == RX_BUFS_COUNT)
+ priv->rx_next_buf = 0;
+ }
+}
+
+static void brcmuart_tx_isr(struct uart_port *up, u32 isr)
+{
+ struct brcmuart_priv *priv = up->private_data;
+ struct device *dev = up->dev;
+ struct uart_8250_port *port_8250 = up_to_u8250p(up);
+ struct circ_buf *xmit = &port_8250->port.state->xmit;
+
+ if (isr & UDMA_INTR_TX_ABORT) {
+ if (priv->tx_running)
+ dev_err(dev, "Unexpected TX_ABORT interrupt\n");
+ return;
+ }
+ priv->tx_running = false;
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(up))
+ brcmuart_tx_dma(port_8250);
+}
+
+static irqreturn_t brcmuart_isr(int irq, void *dev_id)
+{
+ struct uart_port *up = dev_id;
+ struct device *dev = up->dev;
+ struct brcmuart_priv *priv = up->private_data;
+ unsigned long flags;
+ u32 interrupts;
+ u32 rval;
+ u32 tval;
+
+ interrupts = udma_readl(priv, REGS_DMA_ISR, UDMA_INTR_STATUS);
+ if (interrupts == 0)
+ return IRQ_NONE;
+
+ spin_lock_irqsave(&up->lock, flags);
+
+ /* Clear all interrupts */
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_CLEAR, interrupts);
+
+ rval = UDMA_IS_RX_INTERRUPT(interrupts);
+ if (rval)
+ brcmuart_rx_isr(up, rval);
+ tval = UDMA_IS_TX_INTERRUPT(interrupts);
+ if (tval)
+ brcmuart_tx_isr(up, tval);
+ if ((rval | tval) == 0)
+ dev_warn(dev, "Spurious interrupt: 0x%x\n", interrupts);
+
+ spin_unlock_irqrestore(&up->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static int brcmuart_startup(struct uart_port *port)
+{
+ int res;
+ struct uart_8250_port *up = up_to_u8250p(port);
+ struct brcmuart_priv *priv = up->port.private_data;
+
+ priv->shutdown = false;
+
+ /*
+ * prevent serial8250_do_startup() from allocating non-existent
+ * DMA resources
+ */
+ up->dma = NULL;
+
+ res = serial8250_do_startup(port);
+ if (!priv->dma_enabled)
+ return res;
+ /*
+ * Disable the Receive Data Interrupt because the DMA engine
+ * will handle this.
+ */
+ up->ier &= ~UART_IER_RDI;
+ serial_port_out(port, UART_IER, up->ier);
+
+ priv->tx_running = false;
+ priv->dma.rx_dma = NULL;
+ priv->dma.tx_dma = brcmuart_tx_dma;
+ up->dma = &priv->dma;
+
+ brcmuart_init_dma_hardware(priv);
+ start_rx_dma(up);
+ return res;
+}
+
+static void brcmuart_shutdown(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ struct brcmuart_priv *priv = up->port.private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ priv->shutdown = true;
+ if (priv->dma_enabled) {
+ stop_rx_dma(up);
+ stop_tx_dma(up);
+ /* disable all interrupts */
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_MASK_SET,
+ UDMA_RX_INTERRUPTS | UDMA_TX_INTERRUPTS);
+ }
+
+ /*
+ * prevent serial8250_do_shutdown() from trying to free
+ * DMA resources that we never alloc'd for this driver.
+ */
+ up->dma = NULL;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_do_shutdown(port);
+}
+
+/*
+ * Not all clocks run at the exact specified rate, so set each requested
+ * rate and then get the actual rate.
+ */
+static void init_real_clk_rates(struct device *dev, struct brcmuart_priv *priv)
+{
+ int x;
+ int rc;
+
+ priv->default_mux_rate = clk_get_rate(priv->baud_mux_clk);
+ for (x = 0; x < ARRAY_SIZE(priv->real_rates); x++) {
+ if (priv->rate_table[x] == 0) {
+ priv->real_rates[x] = 0;
+ continue;
+ }
+ rc = clk_set_rate(priv->baud_mux_clk, priv->rate_table[x]);
+ if (rc) {
+ dev_err(dev, "Error selecting BAUD MUX clock for %u\n",
+ priv->rate_table[x]);
+ priv->real_rates[x] = priv->rate_table[x];
+ } else {
+ priv->real_rates[x] = clk_get_rate(priv->baud_mux_clk);
+ }
+ }
+ clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate);
+}
+
+static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+ u32 baud)
+{
+ u32 percent;
+ u32 best_percent = UINT_MAX;
+ u32 quot;
+ u32 best_quot = 1;
+ u32 rate;
+ int best_index = -1;
+ u64 hires_rate;
+ u64 hires_baud;
+ u64 hires_err;
+ int rc;
+ int i;
+ int real_baud;
+
+ /* If the Baud Mux Clock was not specified, just return */
+ if (priv->baud_mux_clk == NULL)
+ return;
+
+ /* Find the closest match for specified baud */
+ for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
+ if (priv->real_rates[i] == 0)
+ continue;
+ rate = priv->real_rates[i] / 16;
+ quot = DIV_ROUND_CLOSEST(rate, baud);
+ if (!quot)
+ continue;
+
+ /* increase resolution to get xx.xx percent */
+ hires_rate = (u64)rate * 10000;
+ hires_baud = (u64)baud * 10000;
+
+ hires_err = div_u64(hires_rate, (u64)quot);
+
+ /* get the delta */
+ if (hires_err > hires_baud)
+ hires_err = (hires_err - hires_baud);
+ else
+ hires_err = (hires_baud - hires_err);
+
+ percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
+ dev_dbg(up->dev,
+ "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
+ baud, priv->real_rates[i], percent / 100,
+ percent % 100);
+ if (percent < best_percent) {
+ best_percent = percent;
+ best_index = i;
+ best_quot = quot;
+ }
+ }
+ if (best_index == -1) {
+ dev_err(up->dev, "Error, %d BAUD rate is too fast.\n", baud);
+ return;
+ }
+ rate = priv->real_rates[best_index];
+ rc = clk_set_rate(priv->baud_mux_clk, rate);
+ if (rc)
+ dev_err(up->dev, "Error selecting BAUD MUX clock\n");
+
+ /* Error over 3 percent will cause data errors */
+ if (best_percent > 300)
+ dev_err(up->dev, "Error, baud: %d has %u.%u%% error\n",
+ baud, percent / 100, percent % 100);
+
+ real_baud = rate / 16 / best_quot;
+ dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", rate);
+ dev_dbg(up->dev, "Requested baud: %u, Actual baud: %u\n",
+ baud, real_baud);
+
+ /* calc nanoseconds for 1.5 characters time at the given baud rate */
+ i = NSEC_PER_SEC / real_baud / 10;
+ i += (i / 2);
+ priv->char_wait = ns_to_ktime(i);
+
+ up->uartclk = rate;
+}
+
+static void brcmstb_set_termios(struct uart_port *up,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct uart_8250_port *p8250 = up_to_u8250p(up);
+ struct brcmuart_priv *priv = up->private_data;
+
+ if (priv->dma_enabled)
+ stop_rx_dma(p8250);
+ set_clock_mux(up, priv, tty_termios_baud_rate(termios));
+ serial8250_do_set_termios(up, termios, old);
+ if (p8250->mcr & UART_MCR_AFE)
+ p8250->port.status |= UPSTAT_AUTOCTS;
+ if (priv->dma_enabled)
+ start_rx_dma(p8250);
+}
+
+static int brcmuart_handle_irq(struct uart_port *p)
+{
+ unsigned int iir = serial_port_in(p, UART_IIR);
+ struct brcmuart_priv *priv = p->private_data;
+ struct uart_8250_port *up = up_to_u8250p(p);
+ unsigned int status;
+ unsigned long flags;
+ unsigned int ier;
+ unsigned int mcr;
+ int handled = 0;
+
+ /*
+ * There's a bug in some 8250 cores where we get a timeout
+ * interrupt but there is no data ready.
+ */
+ if (((iir & UART_IIR_ID) == UART_IIR_RX_TIMEOUT) && !(priv->shutdown)) {
+ spin_lock_irqsave(&p->lock, flags);
+ status = serial_port_in(p, UART_LSR);
+ if ((status & UART_LSR_DR) == 0) {
+
+ ier = serial_port_in(p, UART_IER);
+ /*
+ * if Receive Data Interrupt is enabled and
+ * we're uing hardware flow control, deassert
+ * RTS and wait for any chars in the pipline to
+ * arrive and then check for DR again.
+ */
+ if ((ier & UART_IER_RDI) && (up->mcr & UART_MCR_AFE)) {
+ ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ serial_port_out(p, UART_IER, ier);
+ mcr = serial_port_in(p, UART_MCR);
+ mcr &= ~UART_MCR_RTS;
+ serial_port_out(p, UART_MCR, mcr);
+ hrtimer_start(&priv->hrt, priv->char_wait,
+ HRTIMER_MODE_REL);
+ } else {
+ serial_port_in(p, UART_RX);
+ }
+
+ handled = 1;
+ }
+ spin_unlock_irqrestore(&p->lock, flags);
+ if (handled)
+ return 1;
+ }
+ return serial8250_handle_irq(p, iir);
+}
+
+static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t)
+{
+ struct brcmuart_priv *priv = container_of(t, struct brcmuart_priv, hrt);
+ struct uart_port *p = priv->up;
+ struct uart_8250_port *up = up_to_u8250p(p);
+ unsigned int status;
+ unsigned long flags;
+
+ if (priv->shutdown)
+ return HRTIMER_NORESTART;
+
+ spin_lock_irqsave(&p->lock, flags);
+ status = serial_port_in(p, UART_LSR);
+
+ /*
+ * If a character did not arrive after the timeout, clear the false
+ * receive timeout.
+ */
+ if ((status & UART_LSR_DR) == 0) {
+ serial_port_in(p, UART_RX);
+ priv->rx_bad_timeout_no_char++;
+ } else {
+ priv->rx_bad_timeout_late_char++;
+ }
+
+ /* re-enable receive unless upper layer has disabled it */
+ if ((up->ier & (UART_IER_RLSI | UART_IER_RDI)) ==
+ (UART_IER_RLSI | UART_IER_RDI)) {
+ status = serial_port_in(p, UART_IER);
+ status |= (UART_IER_RLSI | UART_IER_RDI);
+ serial_port_out(p, UART_IER, status);
+ status = serial_port_in(p, UART_MCR);
+ status |= UART_MCR_RTS;
+ serial_port_out(p, UART_MCR, status);
+ }
+ spin_unlock_irqrestore(&p->lock, flags);
+ return HRTIMER_NORESTART;
+}
+
+static const struct of_device_id brcmuart_dt_ids[] = {
+ {
+ .compatible = "brcm,bcm7278-uart",
+ .data = brcmstb_rate_table_7278,
+ },
+ {
+ .compatible = "brcm,bcm7271-uart",
+ .data = brcmstb_rate_table,
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, brcmuart_dt_ids);
+
+static void brcmuart_free_bufs(struct device *dev, struct brcmuart_priv *priv)
+{
+ if (priv->rx_bufs)
+ dma_free_coherent(dev, priv->rx_size, priv->rx_bufs,
+ priv->rx_addr);
+ if (priv->tx_buf)
+ dma_free_coherent(dev, priv->tx_size, priv->tx_buf,
+ priv->tx_addr);
+}
+
+static void brcmuart_throttle(struct uart_port *port)
+{
+ struct brcmuart_priv *priv = port->private_data;
+
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_MASK_SET, UDMA_RX_INTERRUPTS);
+}
+
+static void brcmuart_unthrottle(struct uart_port *port)
+{
+ struct brcmuart_priv *priv = port->private_data;
+
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_MASK_CLEAR,
+ UDMA_RX_INTERRUPTS);
+}
+
+static int debugfs_stats_show(struct seq_file *s, void *unused)
+{
+ struct brcmuart_priv *priv = s->private;
+
+ seq_printf(s, "rx_err:\t\t\t\t%u\n",
+ priv->rx_err);
+ seq_printf(s, "rx_timeout:\t\t\t%u\n",
+ priv->rx_timeout);
+ seq_printf(s, "rx_abort:\t\t\t%u\n",
+ priv->rx_abort);
+ seq_printf(s, "rx_bad_timeout_late_char:\t%u\n",
+ priv->rx_bad_timeout_late_char);
+ seq_printf(s, "rx_bad_timeout_no_char:\t\t%u\n",
+ priv->rx_bad_timeout_no_char);
+ seq_printf(s, "rx_missing_close_timeout:\t%u\n",
+ priv->rx_missing_close_timeout);
+ if (priv->dma_enabled) {
+ seq_printf(s, "dma_rx_partial_buf:\t\t%llu\n",
+ priv->dma_rx_partial_buf);
+ seq_printf(s, "dma_rx_full_buf:\t\t%llu\n",
+ priv->dma_rx_full_buf);
+ }
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(debugfs_stats);
+
+static void brcmuart_init_debugfs(struct brcmuart_priv *priv,
+ const char *device)
+{
+ priv->debugfs_dir = debugfs_create_dir(device, brcmuart_debugfs_root);
+ debugfs_create_file("stats", 0444, priv->debugfs_dir, priv,
+ &debugfs_stats_fops);
+}
+
+
+static int brcmuart_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id = NULL;
+ struct uart_8250_port *new_port;
+ struct device *dev = &pdev->dev;
+ struct brcmuart_priv *priv;
+ struct clk *baud_mux_clk;
+ struct uart_8250_port up;
+ struct resource *irq;
+ void __iomem *membase = 0;
+ resource_size_t mapbase = 0;
+ u32 clk_rate = 0;
+ int ret;
+ int x;
+ int dma_irq;
+ static const char * const reg_names[REGS_MAX] = {
+ "uart", "dma_rx", "dma_tx", "dma_intr2", "dma_arb"
+ };
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq) {
+ dev_err(dev, "missing irq\n");
+ return -EINVAL;
+ }
+ priv = devm_kzalloc(dev, sizeof(struct brcmuart_priv),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ of_id = of_match_node(brcmuart_dt_ids, np);
+ if (!of_id || !of_id->data)
+ priv->rate_table = brcmstb_rate_table;
+ else
+ priv->rate_table = of_id->data;
+
+ for (x = 0; x < REGS_MAX; x++) {
+ regs = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ reg_names[x]);
+ if (!regs)
+ break;
+ priv->regs[x] = devm_ioremap(dev, regs->start,
+ resource_size(regs));
+ if (!priv->regs[x])
+ return -ENOMEM;
+ if (x == REGS_8250) {
+ mapbase = regs->start;
+ membase = priv->regs[x];
+ }
+ }
+
+ /* We should have just the uart base registers or all the registers */
+ if (x != 1 && x != REGS_MAX) {
+ dev_warn(dev, "%s registers not specified\n", reg_names[x]);
+ return -EINVAL;
+ }
+
+ /* if the DMA registers were specified, try to enable DMA */
+ if (x > REGS_DMA_RX) {
+ if (brcmuart_arbitration(priv, 1) == 0) {
+ u32 txrev = 0;
+ u32 rxrev = 0;
+
+ txrev = udma_readl(priv, REGS_DMA_RX, UDMA_RX_REVISION);
+ rxrev = udma_readl(priv, REGS_DMA_TX, UDMA_TX_REVISION);
+ if ((txrev >= UDMA_TX_REVISION_REQUIRED) &&
+ (rxrev >= UDMA_RX_REVISION_REQUIRED)) {
+
+ /* Enable the use of the DMA hardware */
+ priv->dma_enabled = true;
+ } else {
+ brcmuart_arbitration(priv, 0);
+ dev_err(dev,
+ "Unsupported DMA Hardware Revision\n");
+ }
+ } else {
+ dev_err(dev,
+ "Timeout arbitrating for UART DMA hardware\n");
+ }
+ }
+
+ of_property_read_u32(np, "clock-frequency", &clk_rate);
+
+ /* See if a Baud clock has been specified */
+ baud_mux_clk = of_clk_get_by_name(np, "sw_baud");
+ if (IS_ERR(baud_mux_clk)) {
+ if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_dbg(dev, "BAUD MUX clock not specified\n");
+ } else {
+ dev_dbg(dev, "BAUD MUX clock found\n");
+ ret = clk_prepare_enable(baud_mux_clk);
+ if (ret)
+ return ret;
+ priv->baud_mux_clk = baud_mux_clk;
+ init_real_clk_rates(dev, priv);
+ clk_rate = priv->default_mux_rate;
+ }
+
+ if (clk_rate == 0) {
+ dev_err(dev, "clock-frequency or clk not defined\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not ");
+
+ memset(&up, 0, sizeof(up));
+ up.port.type = PORT_16550A;
+ up.port.uartclk = clk_rate;
+ up.port.dev = dev;
+ up.port.mapbase = mapbase;
+ up.port.membase = membase;
+ up.port.irq = irq->start;
+ up.port.handle_irq = brcmuart_handle_irq;
+ up.port.regshift = 2;
+ up.port.iotype = of_device_is_big_endian(np) ?
+ UPIO_MEM32BE : UPIO_MEM32;
+ up.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
+ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
+ up.port.dev = dev;
+ up.port.private_data = priv;
+ up.capabilities = UART_CAP_FIFO | UART_CAP_AFE;
+ up.port.fifosize = 32;
+
+ /* Check for a fixed line number */
+ ret = of_alias_get_id(np, "serial");
+ if (ret >= 0)
+ up.port.line = ret;
+
+ /* setup HR timer */
+ hrtimer_init(&priv->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ priv->hrt.function = brcmuart_hrtimer_func;
+
+ up.port.shutdown = brcmuart_shutdown;
+ up.port.startup = brcmuart_startup;
+ up.port.throttle = brcmuart_throttle;
+ up.port.unthrottle = brcmuart_unthrottle;
+ up.port.set_termios = brcmstb_set_termios;
+
+ if (priv->dma_enabled) {
+ priv->rx_size = RX_BUF_SIZE * RX_BUFS_COUNT;
+ priv->rx_bufs = dma_alloc_coherent(dev,
+ priv->rx_size,
+ &priv->rx_addr, GFP_KERNEL);
+ if (!priv->rx_bufs)
+ goto err;
+ priv->tx_size = UART_XMIT_SIZE;
+ priv->tx_buf = dma_alloc_coherent(dev,
+ priv->tx_size,
+ &priv->tx_addr, GFP_KERNEL);
+ if (!priv->tx_buf)
+ goto err;
+ }
+
+ ret = serial8250_register_8250_port(&up);
+ if (ret < 0) {
+ dev_err(dev, "unable to register 8250 port\n");
+ goto err;
+ }
+ priv->line = ret;
+ new_port = serial8250_get_port(ret);
+ priv->up = &new_port->port;
+ if (priv->dma_enabled) {
+ dma_irq = platform_get_irq_byname(pdev, "dma");
+ if (dma_irq < 0) {
+ dev_err(dev, "no IRQ resource info\n");
+ goto err1;
+ }
+ ret = devm_request_irq(dev, dma_irq, brcmuart_isr,
+ IRQF_SHARED, "uart DMA irq", &new_port->port);
+ if (ret) {
+ dev_err(dev, "unable to register IRQ handler\n");
+ goto err1;
+ }
+ }
+ platform_set_drvdata(pdev, priv);
+ brcmuart_init_debugfs(priv, dev_name(&pdev->dev));
+ return 0;
+
+err1:
+ serial8250_unregister_port(priv->line);
+err:
+ brcmuart_free_bufs(dev, priv);
+ brcmuart_arbitration(priv, 0);
+ return -ENODEV;
+}
+
+static int brcmuart_remove(struct platform_device *pdev)
+{
+ struct brcmuart_priv *priv = platform_get_drvdata(pdev);
+
+ debugfs_remove_recursive(priv->debugfs_dir);
+ hrtimer_cancel(&priv->hrt);
+ serial8250_unregister_port(priv->line);
+ brcmuart_free_bufs(&pdev->dev, priv);
+ brcmuart_arbitration(priv, 0);
+ return 0;
+}
+
+static int __maybe_unused brcmuart_suspend(struct device *dev)
+{
+ struct brcmuart_priv *priv = dev_get_drvdata(dev);
+
+ serial8250_suspend_port(priv->line);
+ clk_disable_unprepare(priv->baud_mux_clk);
+
+ return 0;
+}
+
+static int __maybe_unused brcmuart_resume(struct device *dev)
+{
+ struct brcmuart_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(priv->baud_mux_clk);
+ if (ret)
+ dev_err(dev, "Error enabling BAUD MUX clock\n");
+
+ /*
+ * The hardware goes back to it's default after suspend
+ * so get the "clk" back in sync.
+ */
+ ret = clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate);
+ if (ret)
+ dev_err(dev, "Error restoring default BAUD MUX clock\n");
+ if (priv->dma_enabled) {
+ if (brcmuart_arbitration(priv, 1)) {
+ dev_err(dev, "Timeout arbitrating for DMA hardware on resume\n");
+ return(-EBUSY);
+ }
+ brcmuart_init_dma_hardware(priv);
+ start_rx_dma(serial8250_get_port(priv->line));
+ }
+ serial8250_resume_port(priv->line);
+ return 0;
+}
+
+static const struct dev_pm_ops brcmuart_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(brcmuart_suspend, brcmuart_resume)
+};
+
+static struct platform_driver brcmuart_platform_driver = {
+ .driver = {
+ .name = "bcm7271-uart",
+ .pm = &brcmuart_dev_pm_ops,
+ .of_match_table = brcmuart_dt_ids,
+ },
+ .probe = brcmuart_probe,
+ .remove = brcmuart_remove,
+};
+
+static int __init brcmuart_init(void)
+{
+ brcmuart_debugfs_root = debugfs_create_dir(
+ brcmuart_platform_driver.driver.name, NULL);
+ return platform_driver_register(&brcmuart_platform_driver);
+}
+module_init(brcmuart_init);
+
+static void __exit brcmuart_deinit(void)
+{
+ platform_driver_unregister(&brcmuart_platform_driver);
+ debugfs_remove_recursive(brcmuart_debugfs_root);
+}
+module_exit(brcmuart_deinit);
+
+MODULE_AUTHOR("Al Cooper");
+MODULE_DESCRIPTION("Broadcom NS16550A compatible serial port driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 2d0e7c7e408d..2f49c580139b 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -354,7 +354,7 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
static void *
__xr17v35x_register_gpio(struct pci_dev *pcidev,
- const struct property_entry *properties)
+ const struct software_node *node)
{
struct platform_device *pdev;
@@ -365,7 +365,7 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev,
pdev->dev.parent = &pcidev->dev;
ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
- if (platform_device_add_properties(pdev, properties) < 0 ||
+ if (device_add_software_node(&pdev->dev, node) < 0 ||
platform_device_add(pdev) < 0) {
platform_device_put(pdev);
return NULL;
@@ -380,12 +380,16 @@ static const struct property_entry exar_gpio_properties[] = {
{ }
};
+static const struct software_node exar_gpio_node = {
+ .properties = exar_gpio_properties,
+};
+
static int xr17v35x_register_gpio(struct pci_dev *pcidev,
struct uart_8250_port *port)
{
if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
port->port.private_data =
- __xr17v35x_register_gpio(pcidev, exar_gpio_properties);
+ __xr17v35x_register_gpio(pcidev, &exar_gpio_node);
return 0;
}
@@ -457,6 +461,10 @@ static const struct property_entry iot2040_gpio_properties[] = {
{ }
};
+static const struct software_node iot2040_gpio_node = {
+ .properties = iot2040_gpio_properties,
+};
+
static int iot2040_register_gpio(struct pci_dev *pcidev,
struct uart_8250_port *port)
{
@@ -468,7 +476,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,
writeb(IOT2040_UARTS_GPIO_HI_MODE, p + UART_EXAR_MPIOSEL_15_8);
port->port.private_data =
- __xr17v35x_register_gpio(pcidev, iot2040_gpio_properties);
+ __xr17v35x_register_gpio(pcidev, &iot2040_gpio_node);
return 0;
}
@@ -547,6 +555,7 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
struct platform_device *pdev = port->port.private_data;
+ device_remove_software_node(&pdev->dev);
platform_device_unregister(pdev);
port->port.private_data = NULL;
}
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index fbcc90c31ca1..4e75d2e4f87c 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -30,15 +30,14 @@ struct fsl8250_data {
int fsl8250_handle_irq(struct uart_port *port)
{
unsigned char lsr, orig_lsr;
- unsigned long flags;
unsigned int iir;
struct uart_8250_port *up = up_to_u8250p(port);
- spin_lock_irqsave(&up->port.lock, flags);
+ spin_lock(&up->port.lock);
iir = port->serial_in(port, UART_IIR);
if (iir & UART_IIR_NO_INT) {
- spin_unlock_irqrestore(&up->port.lock, flags);
+ spin_unlock(&up->port.lock);
return 0;
}
@@ -46,7 +45,7 @@ int fsl8250_handle_irq(struct uart_port *port)
if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
up->lsr_saved_flags &= ~UART_LSR_BI;
port->serial_in(port, UART_RX);
- spin_unlock_irqrestore(&up->port.lock, flags);
+ spin_unlock(&up->port.lock);
return 1;
}
@@ -82,7 +81,9 @@ int fsl8250_handle_irq(struct uart_port *port)
serial8250_tx_chars(up);
up->lsr_saved_flags = orig_lsr;
- uart_unlock_and_check_sysrq(&up->port, flags);
+
+ uart_unlock_and_check_sysrq(&up->port);
+
return 1;
}
EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
@@ -104,11 +105,8 @@ static int fsl8250_acpi_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- if (irq != -EPROBE_DEFER)
- dev_err(dev, "cannot get irq\n");
+ if (irq < 0)
return irq;
- }
memset(&port8250, 0, sizeof(port8250));
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index 65e9045dafe6..0b077b45d6a9 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -318,6 +318,7 @@ static const struct of_device_id of_platform_serial_table[] = {
{ .compatible = "mrvl,mmp-uart",
.data = (void *)PORT_XSCALE, },
{ .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
+ { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, },
{ .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
{ /* end of list */ },
};
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 23e0decde33e..8ac11eaeca51 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1143,7 +1143,6 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = up->port.private_data;
unsigned char status;
- unsigned long flags;
u8 iir;
serial8250_rpm_get(up);
@@ -1154,7 +1153,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
return IRQ_HANDLED;
}
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock(&port->lock);
status = serial_port_in(port, UART_LSR);
@@ -1179,7 +1178,8 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
}
}
- uart_unlock_and_check_sysrq(port, flags);
+ uart_unlock_and_check_sysrq(port);
+
serial8250_rpm_put(up);
return 1;
}
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index b0af13074cd3..d45dab1ab316 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1466,13 +1466,11 @@ EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
{
- struct uart_8250_em485 *em485;
- struct uart_8250_port *p;
+ struct uart_8250_em485 *em485 = container_of(t, struct uart_8250_em485,
+ stop_tx_timer);
+ struct uart_8250_port *p = em485->port;
unsigned long flags;
- em485 = container_of(t, struct uart_8250_em485, stop_tx_timer);
- p = em485->port;
-
serial8250_rpm_get(p);
spin_lock_irqsave(&p->port.lock, flags);
if (em485->active_timer == &em485->stop_tx_timer) {
@@ -1482,16 +1480,13 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
}
spin_unlock_irqrestore(&p->port.lock, flags);
serial8250_rpm_put(p);
+
return HRTIMER_NORESTART;
}
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
{
- long sec = msec / 1000;
- long nsec = (msec % 1000) * 1000000;
- ktime_t t = ktime_set(sec, nsec);
-
- hrtimer_start(hrt, t, HRTIMER_MODE_REL);
+ hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
}
static void __stop_tx_rs485(struct uart_8250_port *p)
@@ -1633,19 +1628,18 @@ static inline void start_tx_rs485(struct uart_port *port)
static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t)
{
- struct uart_8250_em485 *em485;
- struct uart_8250_port *p;
+ struct uart_8250_em485 *em485 = container_of(t, struct uart_8250_em485,
+ start_tx_timer);
+ struct uart_8250_port *p = em485->port;
unsigned long flags;
- em485 = container_of(t, struct uart_8250_em485, start_tx_timer);
- p = em485->port;
-
spin_lock_irqsave(&p->port.lock, flags);
if (em485->active_timer == &em485->start_tx_timer) {
__start_tx(&p->port);
em485->active_timer = NULL;
}
spin_unlock_irqrestore(&p->port.lock, flags);
+
return HRTIMER_NORESTART;
}
@@ -1885,14 +1879,13 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
{
unsigned char status;
- unsigned long flags;
struct uart_8250_port *up = up_to_u8250p(port);
bool skip_rx = false;
if (iir & UART_IIR_NO_INT)
return 0;
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock(&port->lock);
status = serial_port_in(port, UART_LSR);
@@ -1918,7 +1911,8 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
(up->ier & UART_IER_THRI))
serial8250_tx_chars(up);
- uart_unlock_and_check_sysrq(port, flags);
+ uart_unlock_and_check_sysrq(port);
+
return 1;
}
EXPORT_SYMBOL_GPL(serial8250_handle_irq);
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 603137da4736..d1b3c2373fa4 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -15,8 +15,7 @@ config SERIAL_8250
here are those that are setting up dedicated Ethernet WWW/FTP
servers, or users that have one of the various bus mice instead of a
serial mouse and don't intend to use their machine's standard serial
- port for anything. (Note that the Cyclades multi serial port driver
- does not need this driver built in for it to work.)
+ port for anything.
To compile this driver as a module, choose M here: the
module will be called 8250.
@@ -226,7 +225,7 @@ config SERIAL_8250_MANY_PORTS
serial port hardware which acts similar to standard serial port
hardware. If you only use the standard COM 1/2/3/4 ports, you can
say N here to save some memory. You can also say Y if you have an
- "intelligent" multiport card such as Cyclades, Digiboards, etc.
+ "intelligent" multiport card such as Digiboards, etc.
#
# Multi-port serial cards
@@ -404,7 +403,8 @@ config SERIAL_8250_RT288X
config SERIAL_8250_OMAP
tristate "Support for OMAP internal UART (8250 based driver)"
- depends on SERIAL_8250 && (ARCH_OMAP2PLUS || ARCH_K3)
+ depends on SERIAL_8250
+ depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST
help
If you have a machine based on an Texas Instruments OMAP CPU you
can enable its onboard serial ports by enabling this option.
@@ -440,7 +440,8 @@ config SERIAL_8250_LPC18XX
config SERIAL_8250_MT6577
tristate "Mediatek serial port support"
- depends on SERIAL_8250 && ARCH_MEDIATEK
+ depends on SERIAL_8250
+ depends on ARCH_MEDIATEK || COMPILE_TEST
help
If you have a Mediatek based board and want to use the
serial port, say Y to this option. If unsure, say N.
@@ -510,6 +511,16 @@ config SERIAL_8250_TEGRA
Select this option if you have machine with an NVIDIA Tegra SoC and
wish to enable 8250 serial driver for the Tegra serial interfaces.
+config SERIAL_8250_BCM7271
+ tristate "Broadcom 8250 based serial port"
+ depends on SERIAL_8250 && (ARCH_BRCMSTB || COMPILE_TEST)
+ default ARCH_BRCMSTB
+ help
+ If you have a Broadcom STB based board and want to use the
+ enhanced features of the Broadcom 8250 based serial port,
+ including DMA support and high accuracy BAUD rates, say
+ Y to this option. If unsure, say N.
+
config SERIAL_OF_PLATFORM
tristate "Devicetree based probing for 8250 ports"
depends on SERIAL_8250 && OF
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index a8bfb654d490..b9bcd73c8997 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o
obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o
+obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index 35ff6627c61b..63ea9c4da3d5 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -456,11 +456,11 @@ static int simple_config(struct pcmcia_device *link)
* its base address, then try to grab any standard serial port
* address, and finally try to get any free port.
*/
- if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
- goto found_port;
-
- dev_warn(&link->dev, "no usable port range found, giving up\n");
- return -1;
+ ret = pcmcia_loop_config(link, simple_config_check_notpicky, NULL);
+ if (ret) {
+ dev_warn(&link->dev, "no usable port range found, giving up\n");
+ return ret;
+ }
found_port:
if (info->multi && (info->manfid == MANFID_3COM))
@@ -474,7 +474,7 @@ found_port:
ret = pcmcia_enable_device(link);
if (ret != 0)
- return -1;
+ return ret;
return setup_serial(link, info, link->resource[0]->start, link->irq);
}
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 0c4cd4a348f4..682f9171c82c 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
config SERIAL_AMBA_PL010
tristate "ARM AMBA PL010 serial port support"
- depends on ARM_AMBA
+ depends on ARM_AMBA || COMPILE_TEST
select SERIAL_CORE
help
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
@@ -198,7 +198,7 @@ config SERIAL_KGDB_NMI
config SERIAL_MESON
tristate "Meson serial port support"
- depends on ARCH_MESON
+ depends on ARCH_MESON || COMPILE_TEST
select SERIAL_CORE
help
This enables the driver for the on-chip UARTs of the Amlogic
@@ -236,7 +236,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG
tristate "Samsung SoC serial support"
- depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_APPLE || COMPILE_TEST
select SERIAL_CORE
help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@@ -278,7 +278,7 @@ config SERIAL_SAMSUNG_CONSOLE
config SERIAL_TEGRA
tristate "NVIDIA Tegra20/30 SoC serial controller"
- depends on ARCH_TEGRA && TEGRA20_APB_DMA
+ depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST
select SERIAL_CORE
help
Support for the on-chip UARTs on the NVIDIA Tegra series SOCs
@@ -289,7 +289,8 @@ config SERIAL_TEGRA
config SERIAL_TEGRA_TCU
tristate "NVIDIA Tegra Combined UART"
- depends on ARCH_TEGRA && TEGRA_HSP_MBOX
+ depends on MAILBOX
+ depends on (ARCH_TEGRA && TEGRA_HSP_MBOX) || COMPILE_TEST
select SERIAL_CORE
help
Support for the mailbox-based TCU (Tegra Combined UART) serial port.
@@ -498,6 +499,7 @@ config SERIAL_IMX_EARLYCON
bool "Earlycon on IMX serial port"
depends on ARCH_MXC || COMPILE_TEST
depends on OF
+ select SERIAL_CORE
select SERIAL_EARLYCON
select SERIAL_CORE_CONSOLE
default y if SERIAL_IMX_CONSOLE
@@ -851,7 +853,8 @@ config SERIAL_MPC52xx_CONSOLE_BAUD
config SERIAL_ICOM
tristate "IBM Multiport Serial Adapter"
- depends on PCI && PPC_PSERIES
+ depends on PCI
+ depends on PPC_PSERIES || COMPILE_TEST
select SERIAL_CORE
select FW_LOADER
help
@@ -920,7 +923,7 @@ config SERIAL_JSM
config SERIAL_MSM
tristate "MSM on-chip serial port support"
- depends on ARCH_QCOM
+ depends on ARCH_QCOM || COMPILE_TEST
select SERIAL_CORE
config SERIAL_MSM_CONSOLE
@@ -946,7 +949,7 @@ config SERIAL_QCOM_GENI_CONSOLE
config SERIAL_VT8500
bool "VIA VT8500 on-chip serial port support"
- depends on ARCH_VT8500
+ depends on ARCH_VT8500 || COMPILE_TEST
select SERIAL_CORE
config SERIAL_VT8500_CONSOLE
@@ -956,7 +959,7 @@ config SERIAL_VT8500_CONSOLE
config SERIAL_OMAP
tristate "OMAP serial port support"
- depends on ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || COMPILE_TEST
select SERIAL_CORE
help
If you have a machine based on an Texas Instruments OMAP CPU you
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index d0ca9cf29b62..23c4e0e79694 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -131,9 +131,7 @@ static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
uart_insert_char(port, 0, 0, ch, flag);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 0e487ce091ac..7c5f4e966b59 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -243,9 +243,7 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
flag);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
static void altera_uart_tx_chars(struct altera_uart *pp)
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 3f96edfe569c..e744b953ca34 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -159,9 +159,7 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
ignore_char:
status = readb(uap->port.membase + UART01x_FR);
}
- spin_unlock(&uap->port.lock);
tty_flip_buffer_push(&uap->port.state->port);
- spin_lock(&uap->port.lock);
}
static void pl010_tx_chars(struct uart_amba_port *uap)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 4ead0c9048a8..78682c12156a 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -937,12 +937,10 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
fifotaken = pl011_fifo_to_tty(uap);
}
- spin_unlock(&uap->port.lock);
dev_vdbg(uap->port.dev,
"Took %d chars from DMA buffer and %d chars from the FIFO\n",
dma_count, fifotaken);
tty_flip_buffer_push(port);
- spin_lock(&uap->port.lock);
}
static void pl011_dma_rx_irq(struct uart_amba_port *uap)
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index e8d56e899ec7..d8c937bdf3f9 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -117,9 +117,7 @@ static void apbuart_rx_chars(struct uart_port *port)
status = UART_GET_STATUS(port);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
static void apbuart_tx_chars(struct uart_port *port)
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index c2be7cf91399..4379ca4842ae 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -385,9 +385,7 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
tty_insert_flip_char(port, ch, TTY_NORMAL);
} while (max_count-- > 0);
- spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
- spin_lock(&up->port.lock);
}
static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 17c3fc398fc6..1a9444b6b57e 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -236,9 +236,7 @@ static void arc_serial_rx_chars(struct uart_port *port, unsigned int status)
if (!(uart_handle_sysrq_char(port, ch)))
uart_insert_char(port, status, RXOERR, ch, flg);
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
} while (!((status = UART_GET_STATUS(port)) & RXEMPTY));
}
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index a24e5c2b30bc..058886d9045b 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1178,13 +1178,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
1,
DMA_FROM_DEVICE);
- /*
- * Drop the lock here since it might end up calling
- * uart_start(), which takes the lock.
- */
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
}
@@ -1576,13 +1570,7 @@ static void atmel_rx_from_ring(struct uart_port *port)
uart_insert_char(port, status, ATMEL_US_OVRE, c.ch, flg);
}
- /*
- * Drop the lock here since it might end up calling
- * uart_start(), which takes the lock.
- */
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
static void atmel_release_rx_pdc(struct uart_port *port)
@@ -1667,13 +1655,7 @@ static void atmel_rx_from_pdc(struct uart_port *port)
}
} while (head >= pdc->dma_size);
- /*
- * Drop the lock here since it might end up calling
- * uart_start(), which takes the lock.
- */
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
atmel_uart_writel(port, ATMEL_US_IER,
ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index 5674da2b76f0..5fb0e84f7fd1 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -294,9 +294,7 @@ static void bcm_uart_do_rx(struct uart_port *port)
} while (--max_count);
- spin_unlock(&port->lock);
tty_flip_buffer_push(tty_port);
- spin_lock(&port->lock);
}
/*
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c
index 94af7a5ea497..9e9abfc4824a 100644
--- a/drivers/tty/serial/icom.c
+++ b/drivers/tty/serial/icom.c
@@ -829,9 +829,7 @@ ignore_char:
}
icom_port->next_rcv = rcv_buff;
- spin_unlock(&icom_port->uart_port.lock);
tty_flip_buffer_push(port);
- spin_lock(&icom_port->uart_port.lock);
}
static void process_interrupt(u16 port_int_reg,
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 8257597d034d..7d5a8dfa3e91 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -394,11 +394,7 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2)
static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
{
- long sec = msec / MSEC_PER_SEC;
- long nsec = (msec % MSEC_PER_SEC) * 1000000;
- ktime_t t = ktime_set(sec, nsec);
-
- hrtimer_start(hrt, t, HRTIMER_MODE_REL);
+ hrtimer_start(hrt, ms_to_ktime(msec), HRTIMER_MODE_REL);
}
/* called with port.lock taken and irqs off */
@@ -922,14 +918,8 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
struct imx_port *sport = dev_id;
unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4;
irqreturn_t ret = IRQ_NONE;
- unsigned long flags = 0;
- /*
- * IRQs might not be disabled upon entering this interrupt handler,
- * e.g. when interrupt handlers are forced to be threaded. To support
- * this scenario as well, disable IRQs when acquiring the spinlock.
- */
- spin_lock_irqsave(&sport->port.lock, flags);
+ spin_lock(&sport->port.lock);
usr1 = imx_uart_readl(sport, USR1);
usr2 = imx_uart_readl(sport, USR2);
@@ -999,7 +989,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
ret = IRQ_HANDLED;
}
- spin_unlock_irqrestore(&sport->port.lock, flags);
+ spin_unlock(&sport->port.lock);
return ret;
}
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c
index 512b77195e9f..8e42a7682c63 100644
--- a/drivers/tty/serial/jsm/jsm_tty.c
+++ b/drivers/tty/serial/jsm/jsm_tty.c
@@ -603,18 +603,22 @@ void jsm_input(struct jsm_channel *ch)
if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
for (i = 0; i < s; i++) {
+ u8 chr = ch->ch_rqueue[tail + i];
+ u8 error = ch->ch_equeue[tail + i];
+ char flag = TTY_NORMAL;
+
/*
- * Give the Linux ld the flags in the
- * format it likes.
+ * Give the Linux ld the flags in the format it
+ * likes.
*/
- if (*(ch->ch_equeue + tail + i) & UART_LSR_BI)
- tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_BREAK);
- else if (*(ch->ch_equeue +tail +i) & UART_LSR_PE)
- tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_PARITY);
- else if (*(ch->ch_equeue +tail +i) & UART_LSR_FE)
- tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_FRAME);
- else
- tty_insert_flip_char(port, *(ch->ch_rqueue +tail +i), TTY_NORMAL);
+ if (error & UART_LSR_BI)
+ flag = TTY_BREAK;
+ else if (error & UART_LSR_PE)
+ flag = TTY_PARITY;
+ else if (error & UART_LSR_FE)
+ flag = TTY_FRAME;
+
+ tty_insert_flip_char(port, chr, flag);
}
} else {
tty_insert_flip_string(port, ch->ch_rqueue + tail, s);
diff --git a/drivers/tty/serial/kgdb_nmi.c b/drivers/tty/serial/kgdb_nmi.c
index 6004c0c1d173..db059b66438e 100644
--- a/drivers/tty/serial/kgdb_nmi.c
+++ b/drivers/tty/serial/kgdb_nmi.c
@@ -373,9 +373,7 @@ int kgdb_unregister_nmi_console(void)
if (ret)
return ret;
- ret = tty_unregister_driver(kgdb_nmi_tty_driver);
- if (ret)
- return ret;
+ tty_unregister_driver(kgdb_nmi_tty_driver);
put_tty_driver(kgdb_nmi_tty_driver);
return 0;
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index 64842f3539e1..0b06770642cb 100644
--- a/drivers/tty/serial/liteuart.c
+++ b/drivers/tty/serial/liteuart.c
@@ -270,8 +270,8 @@ static int liteuart_probe(struct platform_device *pdev)
/* get membase */
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
- if (!port->membase)
- return -ENXIO;
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
/* values not from device tree */
port->dev = &pdev->dev;
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index 1fa098d7aec4..b199d7859961 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -273,9 +273,7 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
}
static void __serial_lpc32xx_tx(struct uart_port *port)
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index 1b61d26bb7af..8534d6e45a1d 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -273,7 +273,7 @@ struct max310x_port {
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio;
#endif
- struct max310x_one p[0];
+ struct max310x_one p[];
};
static struct uart_driver max310x_uart = {
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 09c88c48fb7b..c7cec7d03620 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -319,9 +319,7 @@ static void mcf_rx_chars(struct mcf_uart *pp)
uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
/****************************************************************************/
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 69eeef9edfa5..529cd0289056 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -226,9 +226,7 @@ static void meson_receive_chars(struct uart_port *port)
} while (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY));
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
}
static irqreturn_t meson_uart_interrupt(int irq, void *dev_id)
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index af1700445251..2704dc988e4a 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1421,9 +1421,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
}
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
return psc_ops->raw_rx_rdy(port);
}
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 770c182e2208..fcef7a961430 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -757,9 +757,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
count -= r_count;
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
if (misr & (UART_IMR_RXSTALE))
msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
@@ -819,9 +817,7 @@ static void msm_handle_rx(struct uart_port *port)
tty_insert_flip_char(tport, c, flag);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
}
static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count)
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 76b94d0ff586..84e8158088cd 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -159,6 +159,8 @@ struct uart_omap_port {
u32 calc_latency;
struct work_struct qos_work;
bool is_suspending;
+
+ unsigned int rs485_tx_filter_count;
};
#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
@@ -302,7 +304,8 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_OMAP_SCR, up->scr);
res = (port->rs485.flags & SER_RS485_RTS_AFTER_SEND) ?
1 : 0;
- if (gpiod_get_value(up->rts_gpiod) != res) {
+ if (up->rts_gpiod &&
+ gpiod_get_value(up->rts_gpiod) != res) {
if (port->rs485.delay_rts_after_send > 0)
mdelay(
port->rs485.delay_rts_after_send);
@@ -328,19 +331,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
- if ((port->rs485.flags & SER_RS485_ENABLED) &&
- !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
- /*
- * Empty the RX FIFO, we are not interested in anything
- * received during the half-duplex transmission.
- */
- serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_RCVR);
- /* Re-enable RX interrupts */
- up->ier |= UART_IER_RLSI | UART_IER_RDI;
- up->port.read_status_mask |= UART_LSR_DR;
- serial_out(up, UART_IER, up->ier);
- }
-
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
@@ -366,6 +356,10 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
serial_out(up, UART_TX, up->port.x_char);
up->port.icount.tx++;
up->port.x_char = 0;
+ if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
+ !(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
+ up->rs485_tx_filter_count++;
+
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
@@ -377,6 +371,10 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr)
serial_out(up, UART_TX, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
up->port.icount.tx++;
+ if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
+ !(up->port.rs485.flags & SER_RS485_RX_DURING_TX))
+ up->rs485_tx_filter_count++;
+
if (uart_circ_empty(xmit))
break;
} while (--count > 0);
@@ -411,7 +409,7 @@ static void serial_omap_start_tx(struct uart_port *port)
/* if rts not already enabled */
res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
- if (gpiod_get_value(up->rts_gpiod) != res) {
+ if (up->rts_gpiod && gpiod_get_value(up->rts_gpiod) != res) {
gpiod_set_value(up->rts_gpiod, res);
if (port->rs485.delay_rts_before_send > 0)
mdelay(port->rs485.delay_rts_before_send);
@@ -420,7 +418,7 @@ static void serial_omap_start_tx(struct uart_port *port)
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX))
- serial_omap_stop_rx(port);
+ up->rs485_tx_filter_count = 0;
serial_omap_enable_ier_thri(up);
pm_runtime_mark_last_busy(up->dev);
@@ -491,8 +489,13 @@ static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)
* Read one data character out to avoid stalling the receiver according
* to the table 23-246 of the omap4 TRM.
*/
- if (likely(lsr & UART_LSR_DR))
+ if (likely(lsr & UART_LSR_DR)) {
serial_in(up, UART_RX);
+ if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
+ !(up->port.rs485.flags & SER_RS485_RX_DURING_TX) &&
+ up->rs485_tx_filter_count)
+ up->rs485_tx_filter_count--;
+ }
up->port.icount.rx++;
flag = TTY_NORMAL;
@@ -543,6 +546,13 @@ static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
return;
ch = serial_in(up, UART_RX);
+ if ((up->port.rs485.flags & SER_RS485_ENABLED) &&
+ !(up->port.rs485.flags & SER_RS485_RX_DURING_TX) &&
+ up->rs485_tx_filter_count) {
+ up->rs485_tx_filter_count--;
+ return;
+ }
+
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1407,18 +1417,13 @@ serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485)
/* store new config */
port->rs485 = *rs485;
- /*
- * Just as a precaution, only allow rs485
- * to be enabled if the gpio pin is valid
- */
if (up->rts_gpiod) {
/* enable / disable rts */
val = (port->rs485.flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
val = (port->rs485.flags & val) ? 1 : 0;
gpiod_set_value(up->rts_gpiod, val);
- } else
- port->rs485.flags &= ~SER_RS485_ENABLED;
+ }
/* Enable interrupts */
up->ier = mode;
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index abc6042f0378..91f1eb0058d7 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -247,9 +247,7 @@ static void owl_uart_receive_chars(struct uart_port *port)
stat = owl_uart_read(port, OWL_UART_STAT);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
static irqreturn_t owl_uart_irq(int irq, void *dev_id)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index a7363bc66c11..f0351e6f0ef6 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -236,7 +236,6 @@ struct eg20t_port {
void *rx_buf_virt;
dma_addr_t rx_buf_dma;
- struct dentry *debugfs;
#define IRQ_NAME_SIZE 17
char irq_name[IRQ_NAME_SIZE];
@@ -292,8 +291,6 @@ static const int trigger_level_64[4] = { 1, 16, 32, 56 };
static const int trigger_level_16[4] = { 1, 4, 8, 14 };
static const int trigger_level_1[4] = { 1, 1, 1, 1 };
-#ifdef CONFIG_DEBUG_FS
-
#define PCH_REGS_BUFSIZE 1024
@@ -353,7 +350,6 @@ static const struct file_operations port_regs_ops = {
.read = port_show_regs,
.llseek = default_llseek,
};
-#endif /* CONFIG_DEBUG_FS */
static const struct dmi_system_id pch_uart_dmi_table[] = {
{
@@ -1735,9 +1731,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
int fifosize;
int port_type;
struct pch_uart_driver_data *board;
-#ifdef CONFIG_DEBUG_FS
- char name[32]; /* for debugfs file name */
-#endif
+ char name[32];
board = &drv_dat[id->driver_data];
port_type = board->port_type;
@@ -1813,11 +1807,9 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
if (ret < 0)
goto init_port_hal_free;
-#ifdef CONFIG_DEBUG_FS
- snprintf(name, sizeof(name), "uart%d_regs", board->line_no);
- priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO,
- NULL, priv, &port_regs_ops);
-#endif
+ snprintf(name, sizeof(name), "uart%d_regs", priv->port.line);
+ debugfs_create_file(name, S_IFREG | S_IRUGO, NULL, priv,
+ &port_regs_ops);
return priv;
@@ -1835,10 +1827,10 @@ init_port_alloc_err:
static void pch_uart_exit_port(struct eg20t_port *priv)
{
+ char name[32];
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove(priv->debugfs);
-#endif
+ snprintf(name, sizeof(name), "uart%d_regs", priv->port.line);
+ debugfs_remove(debugfs_lookup(name, NULL));
uart_remove_one_port(&pch_uart_driver, &priv->port);
free_page((unsigned long)priv->rxbuf.buf);
}
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 0d85b55ea823..00bb88a71606 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -818,7 +818,6 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
u32 s_irq_status;
u32 geni_status;
struct uart_port *uport = dev;
- unsigned long flags;
bool drop_rx = false;
struct tty_port *tport = &uport->state->port;
struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
@@ -826,7 +825,8 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
if (uport->suspended)
return IRQ_NONE;
- spin_lock_irqsave(&uport->lock, flags);
+ spin_lock(&uport->lock);
+
m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS);
s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
geni_status = readl(uport->membase + SE_GENI_STATUS);
@@ -861,7 +861,7 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
qcom_geni_serial_handle_rx(uport, drop_rx);
out_unlock:
- uart_unlock_and_check_sysrq(uport, flags);
+ uart_unlock_and_check_sysrq(uport);
return IRQ_HANDLED;
}
diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c
index 85366e059258..d550d8fa2fab 100644
--- a/drivers/tty/serial/rda-uart.c
+++ b/drivers/tty/serial/rda-uart.c
@@ -398,9 +398,7 @@ static void rda_uart_receive_chars(struct uart_port *port)
status = rda_uart_read(port, RDA_UART_STATUS);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
static irqreturn_t rda_interrupt(int irq, void *dev_id)
diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c
index 5690c09cc041..d60abffab70e 100644
--- a/drivers/tty/serial/rp2.c
+++ b/drivers/tty/serial/rp2.c
@@ -424,9 +424,7 @@ static void rp2_rx_chars(struct rp2_uart_port *up)
up->port.icount.rx++;
}
- spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
- spin_lock(&up->port.lock);
}
static void rp2_tx_chars(struct rp2_uart_port *up)
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index f5fab1dd96bc..697b6a002a16 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -223,9 +223,7 @@ sa1100_rx_chars(struct sa1100_port *sport)
UTSR0_TO_SM(UART_GET_UTSR0(sport));
}
- spin_unlock(&sport->port.lock);
tty_flip_buffer_push(&sport->port.state->port);
- spin_lock(&sport->port.lock);
}
static void sa1100_tx_chars(struct sa1100_port *sport)
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 8ae3e03fbd8c..d9e4b67a12a0 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -56,9 +56,16 @@
/* flag to ignore all characters coming in */
#define RXSTAT_DUMMY_READ (0x10000000)
+enum s3c24xx_port_type {
+ TYPE_S3C24XX,
+ TYPE_S3C6400,
+ TYPE_APPLE_S5L,
+};
+
struct s3c24xx_uart_info {
char *name;
- unsigned int type;
+ enum s3c24xx_port_type type;
+ unsigned int port_type;
unsigned int fifosize;
unsigned long rx_fifomask;
unsigned long rx_fifoshift;
@@ -70,6 +77,7 @@ struct s3c24xx_uart_info {
unsigned long num_clks;
unsigned long clksel_mask;
unsigned long clksel_shift;
+ unsigned long ucon_mask;
/* uart port features */
@@ -144,6 +152,8 @@ struct s3c24xx_uart_port {
#endif
};
+static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport);
+
/* conversion functions */
#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
@@ -228,16 +238,6 @@ static int s3c24xx_serial_txempty_nofifo(struct uart_port *port)
return rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;
}
-/*
- * s3c64xx and later SoC's include the interrupt mask and status registers in
- * the controller itself, unlike the s3c24xx SoC's which have these registers
- * in the interrupt controller. Check if the port type is s3c64xx or higher.
- */
-static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)
-{
- return to_ourport(port)->info->type == PORT_S3C6400;
-}
-
static void s3c24xx_serial_rx_enable(struct uart_port *port)
{
struct s3c24xx_uart_port *ourport = to_ourport(port);
@@ -289,10 +289,17 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port)
if (!ourport->tx_enabled)
return;
- if (s3c24xx_serial_has_interrupt_mask(port))
+ switch (ourport->info->type) {
+ case TYPE_S3C6400:
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
- else
+ break;
+ case TYPE_APPLE_S5L:
+ s3c24xx_clear_bit(port, APPLE_S5L_UCON_TXTHRESH_ENA, S3C2410_UCON);
+ break;
+ default:
disable_irq_nosync(ourport->tx_irq);
+ break;
+ }
if (dma && dma->tx_chan && ourport->tx_in_progress == S3C24XX_TX_DMA) {
dmaengine_pause(dma->tx_chan);
@@ -353,10 +360,17 @@ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
u32 ucon;
/* Mask Tx interrupt */
- if (s3c24xx_serial_has_interrupt_mask(port))
+ switch (ourport->info->type) {
+ case TYPE_S3C6400:
s3c24xx_set_bit(port, S3C64XX_UINTM_TXD, S3C64XX_UINTM);
- else
+ break;
+ case TYPE_APPLE_S5L:
+ WARN_ON(1); // No DMA
+ break;
+ default:
disable_irq_nosync(ourport->tx_irq);
+ break;
+ }
/* Enable tx dma mode */
ucon = rd_regl(port, S3C2410_UCON);
@@ -386,13 +400,28 @@ static void enable_tx_pio(struct s3c24xx_uart_port *ourport)
wr_regl(port, S3C2410_UCON, ucon);
/* Unmask Tx interrupt */
- if (s3c24xx_serial_has_interrupt_mask(port))
+ switch (ourport->info->type) {
+ case TYPE_S3C6400:
s3c24xx_clear_bit(port, S3C64XX_UINTM_TXD,
S3C64XX_UINTM);
- else
+ break;
+ case TYPE_APPLE_S5L:
+ ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
+ wr_regl(port, S3C2410_UCON, ucon);
+ break;
+ default:
enable_irq(ourport->tx_irq);
+ break;
+ }
ourport->tx_mode = S3C24XX_TX_PIO;
+
+ /*
+ * The Apple version only has edge triggered TX IRQs, so we need
+ * to kick off the process by sending some characters here.
+ */
+ if (ourport->info->type == TYPE_APPLE_S5L)
+ s3c24xx_serial_tx_chars(ourport);
}
static void s3c24xx_serial_start_tx_pio(struct s3c24xx_uart_port *ourport)
@@ -513,11 +542,19 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
if (ourport->rx_enabled) {
dev_dbg(port->dev, "stopping rx\n");
- if (s3c24xx_serial_has_interrupt_mask(port))
+ switch (ourport->info->type) {
+ case TYPE_S3C6400:
s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
S3C64XX_UINTM);
- else
+ break;
+ case TYPE_APPLE_S5L:
+ s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
+ s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
+ break;
+ default:
disable_irq_nosync(ourport->rx_irq);
+ break;
+ }
ourport->rx_enabled = 0;
}
if (dma && dma->rx_chan) {
@@ -651,14 +688,18 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
/* set Rx mode to DMA mode */
ucon = rd_regl(port, S3C2410_UCON);
- ucon &= ~(S3C64XX_UCON_TIMEOUT_MASK |
- S3C64XX_UCON_EMPTYINT_EN |
- S3C64XX_UCON_DMASUS_EN |
- S3C64XX_UCON_TIMEOUT_EN |
- S3C64XX_UCON_RXMODE_MASK);
- ucon |= 0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
- S3C64XX_UCON_TIMEOUT_EN |
- S3C64XX_UCON_RXMODE_CPU;
+ ucon &= ~S3C64XX_UCON_RXMODE_MASK;
+ ucon |= S3C64XX_UCON_RXMODE_CPU;
+
+ /* Apple types use these bits for IRQ masks */
+ if (ourport->info->type != TYPE_APPLE_S5L) {
+ ucon &= ~(S3C64XX_UCON_TIMEOUT_MASK |
+ S3C64XX_UCON_EMPTYINT_EN |
+ S3C64XX_UCON_DMASUS_EN |
+ S3C64XX_UCON_TIMEOUT_EN);
+ ucon |= 0xf << S3C64XX_UCON_TIMEOUT_SHIFT |
+ S3C64XX_UCON_TIMEOUT_EN;
+ }
wr_regl(port, S3C2410_UCON, ucon);
ourport->rx_mode = S3C24XX_RX_PIO;
@@ -674,13 +715,12 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
struct s3c24xx_uart_dma *dma = ourport->dma;
struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
struct tty_port *t = &port->state->port;
- unsigned long flags;
struct dma_tx_state state;
utrstat = rd_regl(port, S3C2410_UTRSTAT);
rd_regl(port, S3C2410_UFSTAT);
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock(&port->lock);
if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) {
s3c64xx_start_rx_dma(ourport);
@@ -709,7 +749,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT);
finish:
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock(&port->lock);
return IRQ_HANDLED;
}
@@ -805,16 +845,15 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
- unsigned long flags;
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock(&port->lock);
s3c24xx_serial_rx_drain_fifo(ourport);
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock(&port->lock);
return IRQ_HANDLED;
}
-static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
+static irqreturn_t s3c24xx_serial_rx_irq(int irq, void *dev_id)
{
struct s3c24xx_uart_port *ourport = dev_id;
@@ -823,16 +862,12 @@ static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
return s3c24xx_serial_rx_chars_pio(dev_id);
}
-static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
+static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
{
- struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
- unsigned long flags;
int count, dma_count = 0;
- spin_lock_irqsave(&port->lock, flags);
-
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
if (ourport->dma && ourport->dma->tx_chan &&
@@ -849,7 +884,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
wr_reg(port, S3C2410_UTXH, port->x_char);
port->icount.tx++;
port->x_char = 0;
- goto out;
+ return;
}
/* if there isn't anything more to transmit, or the uart is now
@@ -858,7 +893,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
s3c24xx_serial_stop_tx(port);
- goto out;
+ return;
}
/* try and drain the buffer... */
@@ -880,7 +915,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (!count && dma_count) {
s3c24xx_serial_start_tx_dma(ourport, dma_count);
- goto out;
+ return;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
@@ -891,9 +926,18 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (uart_circ_empty(xmit))
s3c24xx_serial_stop_tx(port);
+}
-out:
- spin_unlock_irqrestore(&port->lock, flags);
+static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
+{
+ struct s3c24xx_uart_port *ourport = id;
+ struct uart_port *port = &ourport->port;
+
+ spin_lock(&port->lock);
+
+ s3c24xx_serial_tx_chars(ourport);
+
+ spin_unlock(&port->lock);
return IRQ_HANDLED;
}
@@ -906,16 +950,37 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
irqreturn_t ret = IRQ_HANDLED;
if (pend & S3C64XX_UINTM_RXD_MSK) {
- ret = s3c24xx_serial_rx_chars(irq, id);
+ ret = s3c24xx_serial_rx_irq(irq, id);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
}
if (pend & S3C64XX_UINTM_TXD_MSK) {
- ret = s3c24xx_serial_tx_chars(irq, id);
+ ret = s3c24xx_serial_tx_irq(irq, id);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
}
return ret;
}
+/* interrupt handler for Apple SoC's.*/
+static irqreturn_t apple_serial_handle_irq(int irq, void *id)
+{
+ struct s3c24xx_uart_port *ourport = id;
+ struct uart_port *port = &ourport->port;
+ unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
+ irqreturn_t ret = IRQ_NONE;
+
+ if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
+ wr_regl(port, S3C2410_UTRSTAT,
+ APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO);
+ ret = s3c24xx_serial_rx_irq(irq, id);
+ }
+ if (pend & APPLE_S5L_UTRSTAT_TXTHRESH) {
+ wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_TXTHRESH);
+ ret = s3c24xx_serial_tx_irq(irq, id);
+ }
+
+ return ret;
+}
+
static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
@@ -1098,27 +1163,62 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (ourport->tx_claimed) {
- if (!s3c24xx_serial_has_interrupt_mask(port))
- free_irq(ourport->tx_irq, ourport);
+ free_irq(ourport->tx_irq, ourport);
ourport->tx_enabled = 0;
ourport->tx_claimed = 0;
ourport->tx_mode = 0;
}
if (ourport->rx_claimed) {
- if (!s3c24xx_serial_has_interrupt_mask(port))
- free_irq(ourport->rx_irq, ourport);
+ free_irq(ourport->rx_irq, ourport);
ourport->rx_claimed = 0;
ourport->rx_enabled = 0;
}
- /* Clear pending interrupts and mask all interrupts */
- if (s3c24xx_serial_has_interrupt_mask(port)) {
- free_irq(port->irq, ourport);
+ if (ourport->dma)
+ s3c24xx_serial_release_dma(ourport);
- wr_regl(port, S3C64XX_UINTP, 0xf);
- wr_regl(port, S3C64XX_UINTM, 0xf);
- }
+ ourport->tx_in_progress = 0;
+}
+
+static void s3c64xx_serial_shutdown(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ ourport->tx_enabled = 0;
+ ourport->tx_mode = 0;
+ ourport->rx_enabled = 0;
+
+ free_irq(port->irq, ourport);
+
+ wr_regl(port, S3C64XX_UINTP, 0xf);
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+
+ if (ourport->dma)
+ s3c24xx_serial_release_dma(ourport);
+
+ ourport->tx_in_progress = 0;
+}
+
+static void apple_s5l_serial_shutdown(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ unsigned int ucon;
+
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTO_ENA_MSK);
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
+
+ free_irq(port->irq, ourport);
+
+ ourport->tx_enabled = 0;
+ ourport->tx_mode = 0;
+ ourport->rx_enabled = 0;
if (ourport->dma)
s3c24xx_serial_release_dma(ourport);
@@ -1133,7 +1233,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
ourport->rx_enabled = 1;
- ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
+ ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_irq, 0,
s3c24xx_serial_portname(port), ourport);
if (ret != 0) {
@@ -1147,7 +1247,7 @@ static int s3c24xx_serial_startup(struct uart_port *port)
ourport->tx_enabled = 1;
- ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
+ ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_irq, 0,
s3c24xx_serial_portname(port), ourport);
if (ret) {
@@ -1193,9 +1293,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)
/* For compatibility with s3c24xx Soc's */
ourport->rx_enabled = 1;
- ourport->rx_claimed = 1;
ourport->tx_enabled = 0;
- ourport->tx_claimed = 1;
spin_lock_irqsave(&port->lock, flags);
@@ -1215,6 +1313,45 @@ static int s3c64xx_serial_startup(struct uart_port *port)
return ret;
}
+static int apple_s5l_serial_startup(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ unsigned long flags;
+ unsigned int ufcon;
+ int ret;
+
+ wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
+
+ ret = request_irq(port->irq, apple_serial_handle_irq, 0,
+ s3c24xx_serial_portname(port), ourport);
+ if (ret) {
+ dev_err(port->dev, "cannot get irq %d\n", port->irq);
+ return ret;
+ }
+
+ /* For compatibility with s3c24xx Soc's */
+ ourport->rx_enabled = 1;
+ ourport->tx_enabled = 0;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ufcon = rd_regl(port, S3C2410_UFCON);
+ ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+ if (!uart_console(port))
+ ufcon |= S3C2410_UFCON_RESETTX;
+ wr_regl(port, S3C2410_UFCON, ufcon);
+
+ enable_rx_pio(ourport);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Enable Rx Interrupt */
+ s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
+ s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
+
+ return ret;
+}
+
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@@ -1535,41 +1672,26 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
static const char *s3c24xx_serial_type(struct uart_port *port)
{
- switch (port->type) {
- case PORT_S3C2410:
- return "S3C2410";
- case PORT_S3C2440:
- return "S3C2440";
- case PORT_S3C2412:
- return "S3C2412";
- case PORT_S3C6400:
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ switch (ourport->info->type) {
+ case TYPE_S3C24XX:
+ return "S3C24XX";
+ case TYPE_S3C6400:
return "S3C6400/10";
+ case TYPE_APPLE_S5L:
+ return "APPLE S5L";
default:
return NULL;
}
}
-#define MAP_SIZE (0x100)
-
-static void s3c24xx_serial_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, MAP_SIZE);
-}
-
-static int s3c24xx_serial_request_port(struct uart_port *port)
-{
- const char *name = s3c24xx_serial_portname(port);
-
- return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
-}
-
static void s3c24xx_serial_config_port(struct uart_port *port, int flags)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
- if (flags & UART_CONFIG_TYPE &&
- s3c24xx_serial_request_port(port) == 0)
- port->type = info->type;
+ if (flags & UART_CONFIG_TYPE)
+ port->type = info->port_type;
}
/*
@@ -1580,7 +1702,7 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
- if (ser->type != PORT_UNKNOWN && ser->type != info->type)
+ if (ser->type != PORT_UNKNOWN && ser->type != info->port_type)
return -EINVAL;
return 0;
@@ -1608,7 +1730,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c);
#endif
-static struct uart_ops s3c24xx_serial_ops = {
+static const struct uart_ops s3c24xx_serial_ops = {
.pm = s3c24xx_serial_pm,
.tx_empty = s3c24xx_serial_tx_empty,
.get_mctrl = s3c24xx_serial_get_mctrl,
@@ -1621,8 +1743,48 @@ static struct uart_ops s3c24xx_serial_ops = {
.shutdown = s3c24xx_serial_shutdown,
.set_termios = s3c24xx_serial_set_termios,
.type = s3c24xx_serial_type,
- .release_port = s3c24xx_serial_release_port,
- .request_port = s3c24xx_serial_request_port,
+ .config_port = s3c24xx_serial_config_port,
+ .verify_port = s3c24xx_serial_verify_port,
+#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
+ .poll_get_char = s3c24xx_serial_get_poll_char,
+ .poll_put_char = s3c24xx_serial_put_poll_char,
+#endif
+};
+
+static const struct uart_ops s3c64xx_serial_ops = {
+ .pm = s3c24xx_serial_pm,
+ .tx_empty = s3c24xx_serial_tx_empty,
+ .get_mctrl = s3c24xx_serial_get_mctrl,
+ .set_mctrl = s3c24xx_serial_set_mctrl,
+ .stop_tx = s3c24xx_serial_stop_tx,
+ .start_tx = s3c24xx_serial_start_tx,
+ .stop_rx = s3c24xx_serial_stop_rx,
+ .break_ctl = s3c24xx_serial_break_ctl,
+ .startup = s3c64xx_serial_startup,
+ .shutdown = s3c64xx_serial_shutdown,
+ .set_termios = s3c24xx_serial_set_termios,
+ .type = s3c24xx_serial_type,
+ .config_port = s3c24xx_serial_config_port,
+ .verify_port = s3c24xx_serial_verify_port,
+#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
+ .poll_get_char = s3c24xx_serial_get_poll_char,
+ .poll_put_char = s3c24xx_serial_put_poll_char,
+#endif
+};
+
+static const struct uart_ops apple_s5l_serial_ops = {
+ .pm = s3c24xx_serial_pm,
+ .tx_empty = s3c24xx_serial_tx_empty,
+ .get_mctrl = s3c24xx_serial_get_mctrl,
+ .set_mctrl = s3c24xx_serial_set_mctrl,
+ .stop_tx = s3c24xx_serial_stop_tx,
+ .start_tx = s3c24xx_serial_start_tx,
+ .stop_rx = s3c24xx_serial_stop_rx,
+ .break_ctl = s3c24xx_serial_break_ctl,
+ .startup = apple_s5l_serial_startup,
+ .shutdown = apple_s5l_serial_shutdown,
+ .set_termios = s3c24xx_serial_set_termios,
+ .type = s3c24xx_serial_type,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
@@ -1706,14 +1868,9 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
unsigned long ucon = rd_regl(port, S3C2410_UCON);
- unsigned int ucon_mask;
- ucon_mask = info->clksel_mask;
- if (info->type == PORT_S3C2440)
- ucon_mask |= S3C2440_UCON0_DIVMASK;
-
- ucon &= ucon_mask;
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+ ucon &= (info->clksel_mask | info->ucon_mask);
+ wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
/* reset both fifos */
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
@@ -1868,10 +2025,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
/* setup info for port */
port->dev = &platdev->dev;
- /* Startup sequence is different for s3c64xx and higher SoC's */
- if (s3c24xx_serial_has_interrupt_mask(port))
- s3c24xx_serial_ops.startup = s3c64xx_serial_startup;
-
port->uartclk = 1;
if (cfg->uart_flags & UPF_CONS_FLOW) {
@@ -1889,8 +2042,8 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
dev_dbg(port->dev, "resource %pR)\n", res);
- port->membase = devm_ioremap(port->dev, res->start, resource_size(res));
- if (!port->membase) {
+ port->membase = devm_ioremap_resource(port->dev, res);
+ if (IS_ERR(port->membase)) {
dev_err(port->dev, "failed to remap controller address\n");
return -EBUSY;
}
@@ -1905,11 +2058,16 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->tx_irq = ret + 1;
}
- if (!s3c24xx_serial_has_interrupt_mask(port)) {
+ switch (ourport->info->type) {
+ case TYPE_S3C24XX:
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
+ break;
+ default:
+ break;
}
+
/*
* DMA is currently supported only on DT platforms, if DMA properties
* are specified.
@@ -1945,10 +2103,26 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
pr_warn("uart: failed to enable baudclk\n");
/* Keep all interrupts masked and cleared */
- if (s3c24xx_serial_has_interrupt_mask(port)) {
+ switch (ourport->info->type) {
+ case TYPE_S3C6400:
wr_regl(port, S3C64XX_UINTM, 0xf);
wr_regl(port, S3C64XX_UINTP, 0xf);
wr_regl(port, S3C64XX_UINTSP, 0xf);
+ break;
+ case TYPE_APPLE_S5L: {
+ unsigned int ucon;
+
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTO_ENA_MSK);
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
+ break;
+ }
+ default:
+ break;
}
dev_dbg(port->dev, "port: map=%pa, mem=%p, irq=%d (%d,%d), clock=%u\n",
@@ -2019,6 +2193,18 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
+ switch (ourport->info->type) {
+ case TYPE_S3C24XX:
+ ourport->port.ops = &s3c24xx_serial_ops;
+ break;
+ case TYPE_S3C6400:
+ ourport->port.ops = &s3c64xx_serial_ops;
+ break;
+ case TYPE_APPLE_S5L:
+ ourport->port.ops = &apple_s5l_serial_ops;
+ break;
+ }
+
if (np) {
of_property_read_u32(np,
"samsung,uart-fifosize", &ourport->port.fifosize);
@@ -2142,7 +2328,8 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
if (port) {
/* restore IRQ mask */
- if (s3c24xx_serial_has_interrupt_mask(port)) {
+ switch (ourport->info->type) {
+ case TYPE_S3C6400: {
unsigned int uintm = 0xf;
if (ourport->tx_enabled)
@@ -2156,6 +2343,47 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
if (!IS_ERR(ourport->baudclk))
clk_disable_unprepare(ourport->baudclk);
clk_disable_unprepare(ourport->clk);
+ break;
+ }
+ case TYPE_APPLE_S5L: {
+ unsigned int ucon;
+ int ret;
+
+ ret = clk_prepare_enable(ourport->clk);
+ if (ret) {
+ dev_err(dev, "clk_enable clk failed: %d\n", ret);
+ return ret;
+ }
+ if (!IS_ERR(ourport->baudclk)) {
+ ret = clk_prepare_enable(ourport->baudclk);
+ if (ret) {
+ dev_err(dev, "clk_enable baudclk failed: %d\n", ret);
+ clk_disable_unprepare(ourport->clk);
+ return ret;
+ }
+ }
+
+ ucon = rd_regl(port, S3C2410_UCON);
+
+ ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTO_ENA_MSK);
+
+ if (ourport->tx_enabled)
+ ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
+ if (ourport->rx_enabled)
+ ucon |= APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
+ APPLE_S5L_UCON_RXTO_ENA_MSK;
+
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ if (!IS_ERR(ourport->baudclk))
+ clk_disable_unprepare(ourport->baudclk);
+ clk_disable_unprepare(ourport->clk);
+ break;
+ }
+ default:
+ break;
}
}
@@ -2380,7 +2608,8 @@ static struct console s3c24xx_serial_console = {
static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2410 UART",
- .type = PORT_S3C2410,
+ .type = TYPE_S3C24XX,
+ .port_type = PORT_S3C2410,
.fifosize = 16,
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
@@ -2407,7 +2636,8 @@ static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2412 UART",
- .type = PORT_S3C2412,
+ .type = TYPE_S3C24XX,
+ .port_type = PORT_S3C2412,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
@@ -2436,7 +2666,8 @@ static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C2440 UART",
- .type = PORT_S3C2440,
+ .type = TYPE_S3C24XX,
+ .port_type = PORT_S3C2440,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
@@ -2449,6 +2680,7 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
.num_clks = 4,
.clksel_mask = S3C2412_UCON_CLKMASK,
.clksel_shift = S3C2412_UCON_CLKSHIFT,
+ .ucon_mask = S3C2440_UCON0_DIVMASK,
},
.def_cfg = &(struct s3c2410_uartcfg) {
.ucon = S3C2410_UCON_DEFAULT,
@@ -2464,7 +2696,8 @@ static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S3C6400 UART",
- .type = PORT_S3C6400,
+ .type = TYPE_S3C6400,
+ .port_type = PORT_S3C6400,
.fifosize = 64,
.has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
@@ -2492,7 +2725,8 @@ static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung S5PV210 UART",
- .type = PORT_S3C6400,
+ .type = TYPE_S3C6400,
+ .port_type = PORT_S3C6400,
.has_divslot = 1,
.rx_fifomask = S5PV210_UFSTAT_RXMASK,
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
@@ -2520,7 +2754,8 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#define EXYNOS_COMMON_SERIAL_DRV_DATA \
.info = &(struct s3c24xx_uart_info) { \
.name = "Samsung Exynos UART", \
- .type = PORT_S3C6400, \
+ .type = TYPE_S3C6400, \
+ .port_type = PORT_S3C6400, \
.has_divslot = 1, \
.rx_fifomask = S5PV210_UFSTAT_RXMASK, \
.rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \
@@ -2556,6 +2791,34 @@ static struct s3c24xx_serial_drv_data exynos5433_serial_drv_data = {
#define EXYNOS5433_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#endif
+#ifdef CONFIG_ARCH_APPLE
+static struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Apple S5L UART",
+ .type = TYPE_APPLE_S5L,
+ .port_type = PORT_8250,
+ .fifosize = 16,
+ .rx_fifomask = S3C2410_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2410_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2410_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2410_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL0,
+ .num_clks = 1,
+ .clksel_mask = 0,
+ .clksel_shift = 0,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = APPLE_S5L_UCON_DEFAULT,
+ .ufcon = S3C2410_UFCON_DEFAULT,
+ },
+};
+#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)&s5l_serial_drv_data)
+#else
+#define S5L_SERIAL_DRV_DATA ((kernel_ulong_t)NULL)
+#endif
+
static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
{
.name = "s3c2410-uart",
@@ -2578,6 +2841,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
}, {
.name = "exynos5433-uart",
.driver_data = EXYNOS5433_SERIAL_DRV_DATA,
+ }, {
+ .name = "s5l-uart",
+ .driver_data = S5L_SERIAL_DRV_DATA,
},
{ },
};
@@ -2599,6 +2865,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
.data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
{ .compatible = "samsung,exynos5433-uart",
.data = (void *)EXYNOS5433_SERIAL_DRV_DATA },
+ { .compatible = "apple,s5l-uart",
+ .data = (void *)S5L_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
@@ -2730,6 +2998,23 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
s5pv210_early_console_setup);
+
+/* Apple S5L */
+static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
+ const char *opt)
+{
+ /* Close enough to S3C2410 for earlycon... */
+ device->port.private_data = &s3c2410_early_console_data;
+
+#ifdef CONFIG_ARM64
+ /* ... but we need to override the existing fixmap entry as nGnRnE */
+ __set_fixmap(FIX_EARLYCON_MEM_BASE, device->port.mapbase,
+ __pgprot(PROT_DEVICE_nGnRnE));
+#endif
+ return samsung_early_console_setup(device, opt);
+}
+
+OF_EARLYCON_DECLARE(s5l, "apple,s5l-uart", apple_s5l_early_console_setup);
#endif
MODULE_ALIAS("platform:samsung-uart");
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index f86ec2d2635b..9adb8362578c 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1196,7 +1196,7 @@ static int sc16is7xx_probe(struct device *dev,
ret = regmap_read(regmap,
SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
if (ret < 0)
- return ret;
+ return -EPROBE_DEFER;
/* Alloc port structure */
s = devm_kzalloc(dev, struct_size(s, p, devtype->nr_uart), GFP_KERNEL);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index ba31e97d3d96..87f7127b57e6 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -759,8 +759,6 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
struct uart_port *uport;
int ret = -ENODEV;
- memset(retinfo, 0, sizeof(*retinfo));
-
/*
* Ensure the state we copy is consistent and no hardware changes
* occur as we go
@@ -1305,7 +1303,7 @@ static int uart_set_rs485_config(struct uart_port *port,
unsigned long flags;
if (!port->rs485_config)
- return -ENOIOCTLCMD;
+ return -ENOTTY;
if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
return -EFAULT;
@@ -1329,7 +1327,7 @@ static int uart_get_iso7816_config(struct uart_port *port,
struct serial_iso7816 aux;
if (!port->iso7816_config)
- return -ENOIOCTLCMD;
+ return -ENOTTY;
spin_lock_irqsave(&port->lock, flags);
aux = port->iso7816;
@@ -1349,7 +1347,7 @@ static int uart_set_iso7816_config(struct uart_port *port,
unsigned long flags;
if (!port->iso7816_config)
- return -ENOIOCTLCMD;
+ return -ENOTTY;
if (copy_from_user(&iso7816, iso7816_user, sizeof(*iso7816_user)))
return -EFAULT;
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 7a07e7272de1..0a7e5b74bc1d 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -330,9 +330,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status)
up->port.ignore_status_mask = next_ignore_status_mask;
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
- spin_unlock(&up->port.lock);
+
tty_flip_buffer_push(&up->port.state->port);
- spin_lock(&up->port.lock);
+
*status = disr;
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index e1179e74a2b8..ef37fdf37612 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -2124,7 +2124,7 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
unsigned short scscr, scsptr;
unsigned long flags;
- /* check wheter the port has SCSPTR */
+ /* check whether the port has SCSPTR */
if (!sci_getreg(port, SCSPTR)->size) {
/*
* Not supported by hardware. Most parts couple break and rx
@@ -2609,21 +2609,10 @@ done:
udelay(DIV_ROUND_UP(10 * 1000000, baud));
}
- /*
- * Calculate delay for 2 DMA buffers (4 FIFO).
- * See serial_core.c::uart_update_timeout().
- * With 10 bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above
- * function calculates 1 jiffie for the data plus 5 jiffies for the
- * "slop(e)." Then below we calculate 5 jiffies (20ms) for 2 DMA
- * buffers (4 FIFO sizes), but when performing a faster transfer, the
- * value obtained by this formula is too small. Therefore, if the value
- * is smaller than 20ms, use 20ms as the timeout value for DMA.
- */
+ /* Calculate delay for 2 DMA buffers (4 FIFO). */
s->rx_frame = (10000 * bits) / (baud / 100);
#ifdef CONFIG_SERIAL_SH_SCI_DMA
s->rx_timeout = s->buf_len_rx * 2 * s->rx_frame;
- if (s->rx_timeout < 20)
- s->rx_timeout = 20;
#endif
if ((termios->c_cflag & CREAD) != 0)
diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index 328d5a78792f..0ac0371f943b 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -448,9 +448,7 @@ static void __ssp_receive_chars(struct sifive_serial_port *ssp)
uart_insert_char(&ssp->port, 0, 0, ch, TTY_NORMAL);
}
- spin_unlock(&ssp->port.lock);
tty_flip_buffer_push(&ssp->port.state->port);
- spin_lock(&ssp->port.lock);
}
/**
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index b3675cf25a69..c2ae7b392b86 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -218,8 +218,7 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
u32 sr;
char flag;
- if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
- pm_wakeup_event(tport->tty->dev, 0);
+ spin_lock(&port->lock);
while (stm32_usart_pending_rx(port, &sr, &stm32_port->last_res,
threaded)) {
@@ -271,14 +270,14 @@ static void stm32_usart_receive_chars(struct uart_port *port, bool threaded)
}
}
- if (uart_handle_sysrq_char(port, c))
+ if (uart_prepare_sysrq_char(port, c))
continue;
uart_insert_char(port, sr, USART_SR_ORE, c, flag);
}
- spin_unlock(&port->lock);
+ uart_unlock_and_check_sysrq(port);
+
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
}
static void stm32_usart_tx_dma_complete(void *arg)
@@ -286,12 +285,16 @@ static void stm32_usart_tx_dma_complete(void *arg)
struct uart_port *port = arg;
struct stm32_port *stm32port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32port->info->ofs;
+ unsigned long flags;
+ dmaengine_terminate_async(stm32port->tx_ch);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
stm32port->tx_dma_busy = false;
/* Let's see if we have pending data to send */
+ spin_lock_irqsave(&port->lock, flags);
stm32_usart_transmit_chars(port);
+ spin_unlock_irqrestore(&port->lock, flags);
}
static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
@@ -303,7 +306,7 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
* Enables TX FIFO threashold irq when FIFO is enabled,
* or TX empty irq when FIFO is disabled
*/
- if (stm32_port->fifoen)
+ if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
stm32_usart_set_bits(port, ofs->cr3, USART_CR3_TXFTIE);
else
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
@@ -314,7 +317,7 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- if (stm32_port->fifoen)
+ if (stm32_port->fifoen && stm32_port->txftcfg >= 0)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_TXFTIE);
else
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
@@ -455,29 +458,34 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
+ struct tty_port *tport = &port->state->port;
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
u32 sr;
- spin_lock(&port->lock);
-
sr = readl_relaxed(port->membase + ofs->isr);
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
writel_relaxed(USART_ICR_RTOCF,
port->membase + ofs->icr);
- if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG)
+ if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
+ /* Clear wake up flag and disable wake up interrupt */
writel_relaxed(USART_ICR_WUCF,
port->membase + ofs->icr);
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
+ if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
+ pm_wakeup_event(tport->tty->dev, 0);
+ }
if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
stm32_usart_receive_chars(port, false);
- if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch))
+ if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
+ spin_lock(&port->lock);
stm32_usart_transmit_chars(port);
-
- spin_unlock(&port->lock);
+ spin_unlock(&port->lock);
+ }
if (stm32_port->rx_ch)
return IRQ_WAKE_THREAD;
@@ -490,13 +498,9 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
struct uart_port *port = ptr;
struct stm32_port *stm32_port = to_stm32_port(port);
- spin_lock(&port->lock);
-
if (stm32_port->rx_ch)
stm32_usart_receive_chars(port, true);
- spin_unlock(&port->lock);
-
return IRQ_HANDLED;
}
@@ -505,7 +509,10 @@ static unsigned int stm32_usart_tx_empty(struct uart_port *port)
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- return readl_relaxed(port->membase + ofs->isr) & USART_SR_TXE;
+ if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
+ return TIOCSER_TEMT;
+
+ return 0;
}
static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -584,6 +591,19 @@ static void stm32_usart_start_tx(struct uart_port *port)
stm32_usart_transmit_chars(port);
}
+/* Flush the transmit buffer. */
+static void stm32_usart_flush_buffer(struct uart_port *port)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+
+ if (stm32_port->tx_ch) {
+ dmaengine_terminate_async(stm32_port->tx_ch);
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
+ stm32_port->tx_dma_busy = false;
+ }
+}
+
/* Throttle the remote when input buffer is about to overflow. */
static void stm32_usart_throttle(struct uart_port *port)
{
@@ -634,33 +654,30 @@ static int stm32_usart_startup(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
const char *name = to_platform_device(port->dev)->name;
u32 val;
int ret;
ret = request_threaded_irq(port->irq, stm32_usart_interrupt,
stm32_usart_threaded_interrupt,
- IRQF_NO_SUSPEND, name, port);
+ IRQF_ONESHOT | IRQF_NO_SUSPEND,
+ name, port);
if (ret)
return ret;
+ if (stm32_port->swap) {
+ val = readl_relaxed(port->membase + ofs->cr2);
+ val |= USART_CR2_SWAP;
+ writel_relaxed(val, port->membase + ofs->cr2);
+ }
+
/* RX FIFO Flush */
if (ofs->rqr != UNDEF_REG)
- stm32_usart_set_bits(port, ofs->rqr, USART_RQR_RXFRQ);
+ writel_relaxed(USART_RQR_RXFRQ, port->membase + ofs->rqr);
- /* Tx and RX FIFO configuration */
- if (stm32_port->fifoen) {
- val = readl_relaxed(port->membase + ofs->cr3);
- val &= ~(USART_CR3_TXFTCFG_MASK | USART_CR3_RXFTCFG_MASK);
- val |= USART_CR3_TXFTCFG_HALF << USART_CR3_TXFTCFG_SHIFT;
- val |= USART_CR3_RXFTCFG_HALF << USART_CR3_RXFTCFG_SHIFT;
- writel_relaxed(val, port->membase + ofs->cr3);
- }
-
- /* RX FIFO enabling */
- val = stm32_port->cr1_irq | USART_CR1_RE;
- if (stm32_port->fifoen)
- val |= USART_CR1_FIFOEN;
+ /* RX enabling */
+ val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
stm32_usart_set_bits(port, ofs->cr1, val);
return 0;
@@ -691,6 +708,11 @@ static void stm32_usart_shutdown(struct uart_port *port)
if (ret)
dev_err(port->dev, "Transmission is not complete\n");
+ /* flush RX & TX FIFO */
+ if (ofs->rqr != UNDEF_REG)
+ writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
+ port->membase + ofs->rqr);
+
stm32_usart_clr_bits(port, ofs->cr1, val);
free_irq(port->irq, port);
@@ -737,8 +759,9 @@ static void stm32_usart_set_termios(struct uart_port *port,
unsigned int baud, bits;
u32 usartdiv, mantissa, fraction, oversampling;
tcflag_t cflag = termios->c_cflag;
- u32 cr1, cr2, cr3;
+ u32 cr1, cr2, cr3, isr;
unsigned long flags;
+ int ret;
if (!stm32_port->hw_flow_control)
cflag &= ~CRTSCTS;
@@ -747,21 +770,37 @@ static void stm32_usart_set_termios(struct uart_port *port,
spin_lock_irqsave(&port->lock, flags);
+ ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
+ isr,
+ (isr & USART_SR_TC),
+ 10, 100000);
+
+ /* Send the TC error message only when ISR_TC is not set. */
+ if (ret)
+ dev_err(port->dev, "Transmission is not complete\n");
+
/* Stop serial port and reset value */
writel_relaxed(0, port->membase + ofs->cr1);
/* flush RX & TX FIFO */
if (ofs->rqr != UNDEF_REG)
- stm32_usart_set_bits(port, ofs->rqr,
- USART_RQR_TXFRQ | USART_RQR_RXFRQ);
+ writel_relaxed(USART_RQR_TXFRQ | USART_RQR_RXFRQ,
+ port->membase + ofs->rqr);
cr1 = USART_CR1_TE | USART_CR1_RE;
if (stm32_port->fifoen)
cr1 |= USART_CR1_FIFOEN;
- cr2 = 0;
+ cr2 = stm32_port->swap ? USART_CR2_SWAP : 0;
+
+ /* Tx and RX FIFO configuration */
cr3 = readl_relaxed(port->membase + ofs->cr3);
- cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTCFG_MASK | USART_CR3_RXFTIE
- | USART_CR3_TXFTCFG_MASK;
+ cr3 &= USART_CR3_TXFTIE | USART_CR3_RXFTIE;
+ if (stm32_port->fifoen) {
+ if (stm32_port->txftcfg >= 0)
+ cr3 |= stm32_port->txftcfg << USART_CR3_TXFTCFG_SHIFT;
+ if (stm32_port->rxftcfg >= 0)
+ cr3 |= stm32_port->rxftcfg << USART_CR3_RXFTCFG_SHIFT;
+ }
if (cflag & CSTOPB)
cr2 |= USART_CR2_STOP_2B;
@@ -790,7 +829,8 @@ static void stm32_usart_set_termios(struct uart_port *port,
, bits);
if (ofs->rtor != UNDEF_REG && (stm32_port->rx_ch ||
- stm32_port->fifoen)) {
+ (stm32_port->fifoen &&
+ stm32_port->rxftcfg >= 0))) {
if (cflag & CSTOPB)
bits = bits + 3; /* 1 start bit + 2 stop bits */
else
@@ -817,12 +857,6 @@ static void stm32_usart_set_termios(struct uart_port *port,
cr3 |= USART_CR3_CTSE | USART_CR3_RTSE;
}
- /* Handle modem control interrupts */
- if (UART_ENABLE_MS(port, termios->c_cflag))
- stm32_usart_enable_ms(port);
- else
- stm32_usart_disable_ms(port);
-
usartdiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
/*
@@ -892,12 +926,24 @@ static void stm32_usart_set_termios(struct uart_port *port,
cr1 &= ~(USART_CR1_DEDT_MASK | USART_CR1_DEAT_MASK);
}
+ /* Configure wake up from low power on start bit detection */
+ if (stm32_port->wakeup_src) {
+ cr3 &= ~USART_CR3_WUS_MASK;
+ cr3 |= USART_CR3_WUS_START_BIT;
+ }
+
writel_relaxed(cr3, port->membase + ofs->cr3);
writel_relaxed(cr2, port->membase + ofs->cr2);
writel_relaxed(cr1, port->membase + ofs->cr1);
stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
spin_unlock_irqrestore(&port->lock, flags);
+
+ /* Handle modem control interrupts */
+ if (UART_ENABLE_MS(port, termios->c_cflag))
+ stm32_usart_enable_ms(port);
+ else
+ stm32_usart_disable_ms(port);
}
static const char *stm32_usart_type(struct uart_port *port)
@@ -962,6 +1008,7 @@ static const struct uart_ops stm32_uart_ops = {
.break_ctl = stm32_usart_break_ctl,
.startup = stm32_usart_startup,
.shutdown = stm32_usart_shutdown,
+ .flush_buffer = stm32_usart_flush_buffer,
.set_termios = stm32_usart_set_termios,
.pm = stm32_usart_pm,
.type = stm32_usart_type,
@@ -971,6 +1018,39 @@ static const struct uart_ops stm32_uart_ops = {
.verify_port = stm32_usart_verify_port,
};
+/*
+ * STM32H7 RX & TX FIFO threshold configuration (CR3 RXFTCFG / TXFTCFG)
+ * Note: 1 isn't a valid value in RXFTCFG / TXFTCFG. In this case,
+ * RXNEIE / TXEIE can be used instead of threshold irqs: RXFTIE / TXFTIE.
+ * So, RXFTCFG / TXFTCFG bitfields values are encoded as array index + 1.
+ */
+static const u32 stm32h7_usart_fifo_thresh_cfg[] = { 1, 2, 4, 8, 12, 14, 16 };
+
+static void stm32_usart_get_ftcfg(struct platform_device *pdev, const char *p,
+ int *ftcfg)
+{
+ u32 bytes, i;
+
+ /* DT option to get RX & TX FIFO threshold (default to 8 bytes) */
+ if (of_property_read_u32(pdev->dev.of_node, p, &bytes))
+ bytes = 8;
+
+ for (i = 0; i < ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg); i++)
+ if (stm32h7_usart_fifo_thresh_cfg[i] >= bytes)
+ break;
+ if (i >= ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg))
+ i = ARRAY_SIZE(stm32h7_usart_fifo_thresh_cfg) - 1;
+
+ dev_dbg(&pdev->dev, "%s set to %d bytes\n", p,
+ stm32h7_usart_fifo_thresh_cfg[i]);
+
+ /* Provide FIFO threshold ftcfg (1 is invalid: threshold irq unused) */
+ if (i)
+ *ftcfg = i - 1;
+ else
+ *ftcfg = -EINVAL;
+}
+
static void stm32_usart_deinit_port(struct stm32_port *stm32port)
{
clk_disable_unprepare(stm32port->clk);
@@ -1000,13 +1080,19 @@ static int stm32_usart_init_port(struct stm32_port *stm32port,
if (ret)
return ret;
- if (stm32port->info->cfg.has_wakeup) {
- stm32port->wakeirq = platform_get_irq_optional(pdev, 1);
- if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO)
- return stm32port->wakeirq ? : -ENODEV;
- }
+ stm32port->wakeup_src = stm32port->info->cfg.has_wakeup &&
+ of_property_read_bool(pdev->dev.of_node, "wakeup-source");
+
+ stm32port->swap = stm32port->info->cfg.has_swap &&
+ of_property_read_bool(pdev->dev.of_node, "rx-tx-swap");
stm32port->fifoen = stm32port->info->cfg.has_fifo;
+ if (stm32port->fifoen) {
+ stm32_usart_get_ftcfg(pdev, "rx-threshold",
+ &stm32port->rxftcfg);
+ stm32_usart_get_ftcfg(pdev, "tx-threshold",
+ &stm32port->txftcfg);
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
@@ -1106,6 +1192,13 @@ static int stm32_usart_of_dma_rx_probe(struct stm32_port *stm32port,
struct dma_async_tx_descriptor *desc = NULL;
int ret;
+ /*
+ * Using DMA and threaded handler for the console could lead to
+ * deadlocks.
+ */
+ if (uart_console(port))
+ return -ENODEV;
+
/* Request DMA RX channel */
stm32port->rx_ch = dma_request_slave_channel(dev, "rx");
if (!stm32port->rx_ch) {
@@ -1239,23 +1332,13 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (stm32port->wakeirq > 0) {
- ret = device_init_wakeup(&pdev->dev, true);
- if (ret)
- goto err_uninit;
-
- ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
- stm32port->wakeirq);
+ if (stm32port->wakeup_src) {
+ device_set_wakeup_capable(&pdev->dev, true);
+ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq);
if (ret)
goto err_nowup;
-
- device_set_wakeup_enable(&pdev->dev, false);
}
- ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
- if (ret)
- goto err_wirq;
-
ret = stm32_usart_of_dma_rx_probe(stm32port, pdev);
if (ret)
dev_info(&pdev->dev, "interrupt mode used for rx (no dma)\n");
@@ -1269,19 +1352,47 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+
+ ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
+ if (ret)
+ goto err_port;
+
pm_runtime_put_sync(&pdev->dev);
return 0;
-err_wirq:
- if (stm32port->wakeirq > 0)
+err_port:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ if (stm32port->rx_ch) {
+ dmaengine_terminate_async(stm32port->rx_ch);
+ dma_release_channel(stm32port->rx_ch);
+ }
+
+ if (stm32port->rx_dma_buf)
+ dma_free_coherent(&pdev->dev,
+ RX_BUF_L, stm32port->rx_buf,
+ stm32port->rx_dma_buf);
+
+ if (stm32port->tx_ch) {
+ dmaengine_terminate_async(stm32port->tx_ch);
+ dma_release_channel(stm32port->tx_ch);
+ }
+
+ if (stm32port->tx_dma_buf)
+ dma_free_coherent(&pdev->dev,
+ TX_BUF_L, stm32port->tx_buf,
+ stm32port->tx_dma_buf);
+
+ if (stm32port->wakeup_src)
dev_pm_clear_wake_irq(&pdev->dev);
err_nowup:
- if (stm32port->wakeirq > 0)
- device_init_wakeup(&pdev->dev, false);
+ if (stm32port->wakeup_src)
+ device_set_wakeup_capable(&pdev->dev, false);
-err_uninit:
stm32_usart_deinit_port(stm32port);
return ret;
@@ -1295,11 +1406,20 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
int err;
pm_runtime_get_sync(&pdev->dev);
+ err = uart_remove_one_port(&stm32_usart_driver, port);
+ if (err)
+ return(err);
+
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
- if (stm32_port->rx_ch)
+ if (stm32_port->rx_ch) {
+ dmaengine_terminate_async(stm32_port->rx_ch);
dma_release_channel(stm32_port->rx_ch);
+ }
if (stm32_port->rx_dma_buf)
dma_free_coherent(&pdev->dev,
@@ -1308,27 +1428,24 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
- if (stm32_port->tx_ch)
+ if (stm32_port->tx_ch) {
+ dmaengine_terminate_async(stm32_port->tx_ch);
dma_release_channel(stm32_port->tx_ch);
+ }
if (stm32_port->tx_dma_buf)
dma_free_coherent(&pdev->dev,
TX_BUF_L, stm32_port->tx_buf,
stm32_port->tx_dma_buf);
- if (stm32_port->wakeirq > 0) {
+ if (stm32_port->wakeup_src) {
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
stm32_usart_deinit_port(stm32_port);
- err = uart_remove_one_port(&stm32_usart_driver, port);
-
- pm_runtime_disable(&pdev->dev);
- pm_runtime_put_noidle(&pdev->dev);
-
- return err;
+ return 0;
}
#ifdef CONFIG_SERIAL_STM32_CONSOLE
@@ -1354,13 +1471,10 @@ static void stm32_usart_console_write(struct console *co, const char *s,
u32 old_cr1, new_cr1;
int locked = 1;
- local_irq_save(flags);
- if (port->sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = spin_trylock(&port->lock);
+ if (oops_in_progress)
+ locked = spin_trylock_irqsave(&port->lock, flags);
else
- spin_lock(&port->lock);
+ spin_lock_irqsave(&port->lock, flags);
/* Save and disable interrupts, enable the transmitter */
old_cr1 = readl_relaxed(port->membase + ofs->cr1);
@@ -1374,8 +1488,7 @@ static void stm32_usart_console_write(struct console *co, const char *s,
writel_relaxed(old_cr1, port->membase + ofs->cr1);
if (locked)
- spin_unlock(&port->lock);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
}
static int stm32_usart_console_setup(struct console *co, char *options)
@@ -1436,23 +1549,20 @@ static void __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
- const struct stm32_usart_config *cfg = &stm32_port->info->cfg;
- u32 val;
- if (stm32_port->wakeirq <= 0)
+ if (!stm32_port->wakeup_src)
return;
+ /*
+ * Enable low-power wake-up and wake-up irq if argument is set to
+ * "enable", disable low-power wake-up and wake-up irq otherwise
+ */
if (enable) {
- stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_UESM);
- val = readl_relaxed(port->membase + ofs->cr3);
- val &= ~USART_CR3_WUS_MASK;
- /* Enable Wake up interrupt from low power on start bit */
- val |= USART_CR3_WUS_START_BIT | USART_CR3_WUFIE;
- writel_relaxed(val, port->membase + ofs->cr3);
- stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+ stm32_usart_set_bits(port, ofs->cr3, USART_CR3_WUFIE);
} else {
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_UESM);
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
}
}
@@ -1462,10 +1572,8 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
uart_suspend_port(&stm32_usart_driver, port);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, true);
- else
- stm32_usart_serial_en_wakeup(port, false);
/*
* When "no_console_suspend" is enabled, keep the pinctrl default state
@@ -1474,7 +1582,7 @@ static int __maybe_unused stm32_usart_serial_suspend(struct device *dev)
* capabilities.
*/
if (console_suspend_enabled || !uart_console(port)) {
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) || device_wakeup_path(dev))
pinctrl_pm_select_idle_state(dev);
else
pinctrl_pm_select_sleep_state(dev);
@@ -1489,7 +1597,7 @@ static int __maybe_unused stm32_usart_serial_resume(struct device *dev)
pinctrl_pm_select_default_state(dev);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) || device_wakeup_path(dev))
stm32_usart_serial_en_wakeup(port, false);
return uart_resume_port(&stm32_usart_driver, port);
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index cb4f327c46db..07ac291328cd 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -25,6 +25,7 @@ struct stm32_usart_offsets {
struct stm32_usart_config {
u8 uart_enable_bit; /* USART_CR1_UE */
bool has_7bits_data;
+ bool has_swap;
bool has_wakeup;
bool has_fifo;
int fifosize;
@@ -76,6 +77,7 @@ struct stm32_usart_info stm32f7_info = {
.cfg = {
.uart_enable_bit = 0,
.has_7bits_data = true,
+ .has_swap = true,
.fifosize = 1,
}
};
@@ -97,6 +99,7 @@ struct stm32_usart_info stm32h7_info = {
.cfg = {
.uart_enable_bit = 0,
.has_7bits_data = true,
+ .has_swap = true,
.has_wakeup = true,
.has_fifo = true,
.fifosize = 16,
@@ -127,9 +130,6 @@ struct stm32_usart_info stm32h7_info = {
/* Dummy bits */
#define USART_SR_DUMMY_RX BIT(16)
-/* USART_ICR (F7) */
-#define USART_CR_TC BIT(6)
-
/* USART_DR */
#define USART_DR_MASK GENMASK(8, 0)
@@ -216,12 +216,6 @@ struct stm32_usart_info stm32h7_info = {
#define USART_CR3_TXFTCFG_MASK GENMASK(31, 29) /* H7 */
#define USART_CR3_TXFTCFG_SHIFT 29 /* H7 */
-/* TX FIFO threashold set to half of its depth */
-#define USART_CR3_TXFTCFG_HALF 0x2
-
-/* RX FIFO threashold set to half of its depth */
-#define USART_CR3_RXFTCFG_HALF 0x2
-
/* USART_GTPR */
#define USART_GTPR_PSC_MASK GENMASK(7, 0)
#define USART_GTPR_GT_MASK GENMASK(15, 8)
@@ -271,8 +265,11 @@ struct stm32_port {
int last_res;
bool tx_dma_busy; /* dma tx busy */
bool hw_flow_control;
+ bool swap; /* swap RX & TX pins */
bool fifoen;
- int wakeirq;
+ int rxftcfg; /* RX FIFO threshold CFG */
+ int txftcfg; /* TX FIFO threshold CFG */
+ bool wakeup_src;
int rdr_mask; /* receive data register mask */
struct mctrl_gpios *gpios; /* modem control gpios */
};
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 319e5ceb6130..12c2468f2b0e 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -466,12 +466,8 @@ static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id)
if (status & UART_LSR_THRE)
transmit_chars(up);
- spin_unlock_irqrestore(&up->port.lock, flags);
-
tty_flip_buffer_push(&up->port.state->port);
- spin_lock_irqsave(&up->port.lock, flags);
-
} while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT));
spin_unlock_irqrestore(&up->port.lock, flags);
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
index aaf8748a6147..52687c65ad74 100644
--- a/drivers/tty/serial/tegra-tcu.c
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -282,6 +282,7 @@ static const struct of_device_id tegra_tcu_match[] = {
{ .compatible = "nvidia,tegra194-tcu" },
{ }
};
+MODULE_DEVICE_TABLE(of, tegra_tcu_match);
static struct platform_driver tegra_tcu_driver = {
.driver = {
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
index 2126e6e6dfd1..08941eabe7b1 100644
--- a/drivers/tty/serial/timbuart.c
+++ b/drivers/tty/serial/timbuart.c
@@ -87,9 +87,7 @@ static void timbuart_rx_chars(struct uart_port *port)
tty_insert_flip_char(tport, ch, TTY_NORMAL);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
dev_dbg(port->dev, "%s - total read %d bytes\n",
__func__, port->icount.rx);
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 764e992438b2..c5edd56ff830 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -184,9 +184,7 @@ static void handle_rx(struct uart_port *port)
tty_insert_flip_char(tport, c, flag);
}
- spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
- spin_lock(&port->lock);
}
static void handle_tx(struct uart_port *port)
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index a14c5d996473..67a2db621e2b 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -301,9 +301,8 @@ static void cdns_uart_handle_rx(void *dev_id, unsigned int isrstatus)
tty_insert_flip_char(&port->state->port, data, status);
isrstatus = 0;
}
- spin_unlock(&port->lock);
+
tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
}
/**
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
index 644173786bf0..5523cf7bd1c2 100644
--- a/drivers/tty/synclink_gt.c
+++ b/drivers/tty/synclink_gt.c
@@ -137,37 +137,14 @@ MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
*/
static struct tty_driver *serial_driver;
-static int open(struct tty_struct *tty, struct file * filp);
-static void close(struct tty_struct *tty, struct file * filp);
-static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-
-static int write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int put_char(struct tty_struct *tty, unsigned char ch);
-static void send_xchar(struct tty_struct *tty, char ch);
static void wait_until_sent(struct tty_struct *tty, int timeout);
-static int write_room(struct tty_struct *tty);
-static void flush_chars(struct tty_struct *tty);
static void flush_buffer(struct tty_struct *tty);
-static void tx_hold(struct tty_struct *tty);
static void tx_release(struct tty_struct *tty);
-static int ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
-static int chars_in_buffer(struct tty_struct *tty);
-static void throttle(struct tty_struct * tty);
-static void unthrottle(struct tty_struct * tty);
-static int set_break(struct tty_struct *tty, int break_state);
-
/*
- * generic HDLC support and callbacks
+ * generic HDLC support
*/
-#if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(struct slgt_info *info);
-static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
-static int hdlcdev_init(struct slgt_info *info);
-static void hdlcdev_exit(struct slgt_info *info);
-#endif
/*
@@ -186,9 +163,6 @@ struct cond_wait {
wait_queue_entry_t wait;
unsigned int data;
};
-static void init_cond_wait(struct cond_wait *w, unsigned int data);
-static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
static void flush_cond_wait(struct cond_wait **head);
/*
@@ -443,12 +417,8 @@ static void shutdown(struct slgt_info *info);
static void program_hw(struct slgt_info *info);
static void change_params(struct slgt_info *info);
-static int register_test(struct slgt_info *info);
-static int irq_test(struct slgt_info *info);
-static int loopback_test(struct slgt_info *info);
static int adapter_test(struct slgt_info *info);
-static void reset_adapter(struct slgt_info *info);
static void reset_port(struct slgt_info *info);
static void async_mode(struct slgt_info *info);
static void sync_mode(struct slgt_info *info);
@@ -457,14 +427,12 @@ static void rx_stop(struct slgt_info *info);
static void rx_start(struct slgt_info *info);
static void reset_rbufs(struct slgt_info *info);
static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
-static void rdma_reset(struct slgt_info *info);
static bool rx_get_frame(struct slgt_info *info);
static bool rx_get_buf(struct slgt_info *info);
static void tx_start(struct slgt_info *info);
static void tx_stop(struct slgt_info *info);
static void tx_set_idle(struct slgt_info *info);
-static unsigned int free_tbuf_count(struct slgt_info *info);
static unsigned int tbuf_bytes(struct slgt_info *info);
static void reset_tbufs(struct slgt_info *info);
static void tdma_reset(struct slgt_info *info);
@@ -472,26 +440,10 @@ static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count)
static void get_signals(struct slgt_info *info);
static void set_signals(struct slgt_info *info);
-static void enable_loopback(struct slgt_info *info);
static void set_rate(struct slgt_info *info, u32 data_rate);
-static int bh_action(struct slgt_info *info);
-static void bh_handler(struct work_struct *work);
static void bh_transmit(struct slgt_info *info);
-static void isr_serial(struct slgt_info *info);
-static void isr_rdma(struct slgt_info *info);
static void isr_txeom(struct slgt_info *info, unsigned short status);
-static void isr_tdma(struct slgt_info *info);
-
-static int alloc_dma_bufs(struct slgt_info *info);
-static void free_dma_bufs(struct slgt_info *info);
-static int alloc_desc(struct slgt_info *info);
-static void free_desc(struct slgt_info *info);
-static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-
-static int alloc_tmp_rbuf(struct slgt_info *info);
-static void free_tmp_rbuf(struct slgt_info *info);
static void tx_timeout(struct timer_list *t);
static void rx_timeout(struct timer_list *t);
@@ -509,10 +461,6 @@ static int tx_abort(struct slgt_info *info);
static int rx_enable(struct slgt_info *info, int enable);
static int modem_input_wait(struct slgt_info *info,int arg);
static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
-static int tiocmget(struct tty_struct *tty);
-static int tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear);
-static int set_break(struct tty_struct *tty, int break_state);
static int get_interface(struct slgt_info *info, int __user *if_mode);
static int set_interface(struct slgt_info *info, int if_mode);
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
@@ -526,9 +474,6 @@ static int set_xctrl(struct slgt_info *info, int if_mode);
/*
* driver functions
*/
-static void add_device(struct slgt_info *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
-static int claim_resources(struct slgt_info *info);
static void release_resources(struct slgt_info *info);
/*
@@ -3566,8 +3511,6 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
info->max_frame_size = 4096;
info->base_clock = 14745600;
info->rbuf_fill_level = DMABUFSIZE;
- info->port.close_delay = 5*HZ/10;
- info->port.closing_wait = 30*HZ;
init_waitqueue_head(&info->status_event_wait_q);
init_waitqueue_head(&info->event_wait_q);
spin_lock_init(&info->netlock);
@@ -3705,7 +3648,6 @@ static const struct tty_operations ops = {
static void slgt_cleanup(void)
{
- int rc;
struct slgt_info *info;
struct slgt_info *tmp;
@@ -3714,9 +3656,7 @@ static void slgt_cleanup(void)
if (serial_driver) {
for (info=slgt_device_list ; info != NULL ; info=info->next_device)
tty_unregister_device(serial_driver, info->line);
- rc = tty_unregister_driver(serial_driver);
- if (rc)
- DBGERR(("tty_unregister_driver error=%d\n", rc));
+ tty_unregister_driver(serial_driver);
put_tty_driver(serial_driver);
}
@@ -5018,7 +4958,7 @@ static int loopback_test(struct slgt_info *info)
#define TESTFRAMESIZE 20
unsigned long timeout;
- u16 count = TESTFRAMESIZE;
+ u16 count;
unsigned char buf[TESTFRAMESIZE];
int rc = -ENODEV;
unsigned long flags;
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 959f9e121cc6..6628792431dc 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -118,6 +118,7 @@ static const struct sysrq_key_op sysrq_loglevel_op = {
static void sysrq_handle_SAK(int key)
{
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
+
schedule_work(SAK_work);
}
static const struct sysrq_key_op sysrq_SAK_op = {
@@ -547,22 +548,22 @@ static int sysrq_key_table_key2index(int key)
*/
static const struct sysrq_key_op *__sysrq_get_key_op(int key)
{
- const struct sysrq_key_op *op_p = NULL;
- int i;
+ const struct sysrq_key_op *op_p = NULL;
+ int i;
i = sysrq_key_table_key2index(key);
if (i != -1)
- op_p = sysrq_key_table[i];
+ op_p = sysrq_key_table[i];
- return op_p;
+ return op_p;
}
static void __sysrq_put_key_op(int key, const struct sysrq_key_op *op_p)
{
- int i = sysrq_key_table_key2index(key);
+ int i = sysrq_key_table_key2index(key);
- if (i != -1)
- sysrq_key_table[i] = op_p;
+ if (i != -1)
+ sysrq_key_table[i] = op_p;
}
void __handle_sysrq(int key, bool check_mask)
@@ -586,8 +587,8 @@ void __handle_sysrq(int key, bool check_mask)
orig_log_level = console_loglevel;
console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
- op_p = __sysrq_get_key_op(key);
- if (op_p) {
+ op_p = __sysrq_get_key_op(key);
+ if (op_p) {
/*
* Should we check for enabled operations (/proc/sysrq-trigger
* should not) and is the invoked operation enabled?
@@ -636,13 +637,13 @@ static int sysrq_reset_downtime_ms;
/* Simple translation table for the SysRq keys */
static const unsigned char sysrq_xlate[KEY_CNT] =
- "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
- "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
- "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
- "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
- "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
- "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
- "\r\000/"; /* 0x60 - 0x6f */
+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+ "\r\000/"; /* 0x60 - 0x6f */
struct sysrq_state {
struct input_handle handle;
@@ -1107,7 +1108,7 @@ int sysrq_toggle_support(int enable_mask)
EXPORT_SYMBOL_GPL(sysrq_toggle_support);
static int __sysrq_swap_key_ops(int key, const struct sysrq_key_op *insert_op_p,
- const struct sysrq_key_op *remove_op_p)
+ const struct sysrq_key_op *remove_op_p)
{
int retval;
diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
new file mode 100644
index 000000000000..b710c5ef89ab
--- /dev/null
+++ b/drivers/tty/tty.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TTY core internal functions
+ */
+
+#ifndef _TTY_INTERNAL_H
+#define _TTY_INTERNAL_H
+
+#define tty_msg(fn, tty, f, ...) \
+ fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__)
+
+#define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__)
+#define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__)
+#define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__)
+#define tty_err(tty, f, ...) tty_msg(pr_err, tty, f, ##__VA_ARGS__)
+
+#define tty_info_ratelimited(tty, f, ...) \
+ tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
+
+/*
+ * Lock subclasses for tty locks
+ *
+ * TTY_LOCK_NORMAL is for normal ttys and master ptys.
+ * TTY_LOCK_SLAVE is for slave ptys only.
+ *
+ * Lock subclasses are necessary for handling nested locking with pty pairs.
+ * tty locks which use nested locking:
+ *
+ * legacy_mutex - Nested tty locks are necessary for releasing pty pairs.
+ * The stable lock order is master pty first, then slave pty.
+ * termios_rwsem - The stable lock order is tty_buffer lock->termios_rwsem.
+ * Subclassing this lock enables the slave pty to hold its
+ * termios_rwsem when claiming the master tty_buffer lock.
+ * tty_buffer lock - slave ptys can claim nested buffer lock when handling
+ * signal chars. The stable lock order is slave pty, then
+ * master.
+ */
+enum {
+ TTY_LOCK_NORMAL = 0,
+ TTY_LOCK_SLAVE,
+};
+
+/* Values for tty->flow_change */
+#define TTY_THROTTLE_SAFE 1
+#define TTY_UNTHROTTLE_SAFE 2
+
+static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
+{
+ tty->flow_change = val;
+}
+
+static inline void tty_set_flow_change(struct tty_struct *tty, int val)
+{
+ tty->flow_change = val;
+ smp_mb();
+}
+
+int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
+void tty_ldisc_unlock(struct tty_struct *tty);
+
+int __tty_check_change(struct tty_struct *tty, int sig);
+int tty_check_change(struct tty_struct *tty);
+void __stop_tty(struct tty_struct *tty);
+void __start_tty(struct tty_struct *tty);
+void tty_vhangup_session(struct tty_struct *tty);
+void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
+int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
+void session_clear_tty(struct pid *session);
+void tty_buffer_free_all(struct tty_port *port);
+void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
+void tty_buffer_init(struct tty_port *port);
+void tty_buffer_set_lock_subclass(struct tty_port *port);
+bool tty_buffer_restart_work(struct tty_port *port);
+bool tty_buffer_cancel_work(struct tty_port *port);
+void tty_buffer_flush_work(struct tty_port *port);
+speed_t tty_termios_input_baud_rate(struct ktermios *termios);
+void tty_ldisc_hangup(struct tty_struct *tty, bool reset);
+int tty_ldisc_reinit(struct tty_struct *tty, int disc);
+long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
+ struct file *file, unsigned int cmd, unsigned long arg);
+void tty_default_fops(struct file_operations *fops);
+struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
+int tty_alloc_file(struct file *file);
+void tty_add_file(struct tty_struct *tty, struct file *file);
+void tty_free_file(struct file *file);
+int tty_release(struct inode *inode, struct file *filp);
+
+#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
+
+int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
+void tty_ldisc_release(struct tty_struct *tty);
+int __must_check tty_ldisc_init(struct tty_struct *tty);
+void tty_ldisc_deinit(struct tty_struct *tty);
+
+void tty_sysctl_init(void);
+
+/* tty_audit.c */
+#ifdef CONFIG_AUDIT
+void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size);
+void tty_audit_tiocsti(struct tty_struct *tty, char ch);
+#else
+static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
+ size_t size)
+{
+}
+static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
+{
+}
+#endif
+
+ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
+
+#endif
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index 32898aabcd06..ca7afd7b2716 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -10,6 +10,7 @@
#include <linux/audit.h>
#include <linux/slab.h>
#include <linux/tty.h>
+#include "tty.h"
struct tty_audit_buf {
struct mutex mutex; /* Protects all data below */
diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c
index 6551b188b736..48b5de659c77 100644
--- a/drivers/tty/tty_baudrate.c
+++ b/drivers/tty/tty_baudrate.c
@@ -8,6 +8,7 @@
#include <linux/termios.h>
#include <linux/tty.h>
#include <linux/export.h>
+#include "tty.h"
/*
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6d4995a5f318..9733469a14b2 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -17,7 +17,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/ratelimit.h>
-
+#include "tty.h"
#define MIN_TTYB_SIZE 256
#define TTYB_ALIGN_MASK 255
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 391bada4cedb..5b5e99604989 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -108,6 +108,7 @@
#include <linux/kmod.h>
#include <linux/nsproxy.h>
+#include "tty.h"
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
@@ -546,7 +547,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* This is available to the pty code so if the master closes, if the
* slave is a redirect it can release the redirect.
*/
-struct file *tty_release_redirect(struct tty_struct *tty)
+static struct file *tty_release_redirect(struct tty_struct *tty)
{
struct file *f = NULL;
@@ -559,7 +560,6 @@ struct file *tty_release_redirect(struct tty_struct *tty)
return f;
}
-EXPORT_SYMBOL_GPL(tty_release_redirect);
/**
* __tty_hangup - actual handler for hangup events
@@ -1195,8 +1195,6 @@ int tty_send_xchar(struct tty_struct *tty, char ch)
return 0;
}
-static char ptychar[] = "pqrstuvwxyzabcde";
-
/**
* pty_line_name - generate name for a pty
* @driver: the tty driver in use
@@ -1210,6 +1208,7 @@ static char ptychar[] = "pqrstuvwxyzabcde";
*/
static void pty_line_name(struct tty_driver *driver, int index, char *p)
{
+ static const char ptychar[] = "pqrstuvwxyzabcde";
int i = index + driver->name_base;
/* ->name is initialized to "ttyp", but "tty" is expected */
sprintf(p, "%s%c%x",
@@ -2530,14 +2529,14 @@ out:
* @p: pointer to result
*
* Obtain the modem status bits from the tty driver if the feature
- * is supported. Return -EINVAL if it is not available.
+ * is supported. Return -ENOTTY if it is not available.
*
* Locking: none (up to the driver)
*/
static int tty_tiocmget(struct tty_struct *tty, int __user *p)
{
- int retval = -EINVAL;
+ int retval = -ENOTTY;
if (tty->ops->tiocmget) {
retval = tty->ops->tiocmget(tty);
@@ -2555,7 +2554,7 @@ static int tty_tiocmget(struct tty_struct *tty, int __user *p)
* @p: pointer to desired bits
*
* Set the modem status bits from the tty driver if the feature
- * is supported. Return -EINVAL if it is not available.
+ * is supported. Return -ENOTTY if it is not available.
*
* Locking: none (up to the driver)
*/
@@ -2567,7 +2566,7 @@ static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd,
unsigned int set, clear, val;
if (tty->ops->tiocmset == NULL)
- return -EINVAL;
+ return -ENOTTY;
retval = get_user(val, p);
if (retval)
@@ -2607,7 +2606,7 @@ int tty_get_icount(struct tty_struct *tty,
if (tty->ops->get_icount)
return tty->ops->get_icount(tty, icount);
else
- return -EINVAL;
+ return -ENOTTY;
}
EXPORT_SYMBOL_GPL(tty_get_icount);
@@ -2625,26 +2624,31 @@ static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
return 0;
}
-static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *ss)
+static int tty_set_serial(struct tty_struct *tty, struct serial_struct *ss)
{
- static DEFINE_RATELIMIT_STATE(depr_flags,
- DEFAULT_RATELIMIT_INTERVAL,
- DEFAULT_RATELIMIT_BURST);
char comm[TASK_COMM_LEN];
- struct serial_struct v;
int flags;
- if (copy_from_user(&v, ss, sizeof(*ss)))
- return -EFAULT;
+ flags = ss->flags & ASYNC_DEPRECATED;
- flags = v.flags & ASYNC_DEPRECATED;
+ if (flags)
+ pr_warn_ratelimited("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
+ __func__, get_task_comm(comm, current), flags);
- if (flags && __ratelimit(&depr_flags))
- pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
- __func__, get_task_comm(comm, current), flags);
if (!tty->ops->set_serial)
return -ENOTTY;
- return tty->ops->set_serial(tty, &v);
+
+ return tty->ops->set_serial(tty, ss);
+}
+
+static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *ss)
+{
+ struct serial_struct v;
+
+ if (copy_from_user(&v, ss, sizeof(*ss)))
+ return -EFAULT;
+
+ return tty_set_serial(tty, &v);
}
static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user *ss)
@@ -2842,13 +2846,8 @@ struct serial_struct32 {
static int compat_tty_tiocsserial(struct tty_struct *tty,
struct serial_struct32 __user *ss)
{
- static DEFINE_RATELIMIT_STATE(depr_flags,
- DEFAULT_RATELIMIT_INTERVAL,
- DEFAULT_RATELIMIT_BURST);
- char comm[TASK_COMM_LEN];
struct serial_struct32 v32;
struct serial_struct v;
- int flags;
if (copy_from_user(&v32, ss, sizeof(*ss)))
return -EFAULT;
@@ -2859,14 +2858,7 @@ static int compat_tty_tiocsserial(struct tty_struct *tty,
v.port_high = v32.port_high;
v.iomap_base = 0;
- flags = v.flags & ASYNC_DEPRECATED;
-
- if (flags && __ratelimit(&depr_flags))
- pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
- __func__, get_task_comm(comm, current), flags);
- if (!tty->ops->set_serial)
- return -ENOTTY;
- return tty->ops->set_serial(tty, &v);
+ return tty_set_serial(tty, &v);
}
static int compat_tty_tiocgserial(struct tty_struct *tty,
@@ -3524,21 +3516,14 @@ EXPORT_SYMBOL(tty_register_driver);
/*
* Called by a tty driver to unregister itself.
*/
-int tty_unregister_driver(struct tty_driver *driver)
+void tty_unregister_driver(struct tty_driver *driver)
{
-#if 0
- /* FIXME */
- if (driver->refcount)
- return -EBUSY;
-#endif
unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
driver->num);
mutex_lock(&tty_mutex);
list_del(&driver->tty_drivers);
mutex_unlock(&tty_mutex);
- return 0;
}
-
EXPORT_SYMBOL(tty_unregister_driver);
dev_t tty_devnum(struct tty_struct *tty)
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 4de1c6ddb8ff..41f7449d0464 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -21,6 +21,7 @@
#include <linux/bitops.h>
#include <linux/mutex.h>
#include <linux/compat.h>
+#include "tty.h"
#include <asm/io.h>
#include <linux/uaccess.h>
@@ -57,8 +58,7 @@ int tty_chars_in_buffer(struct tty_struct *tty)
{
if (tty->ops->chars_in_buffer)
return tty->ops->chars_in_buffer(tty);
- else
- return 0;
+ return 0;
}
EXPORT_SYMBOL(tty_chars_in_buffer);
@@ -774,8 +774,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
case TCSETX:
case TCSETXW:
case TCSETXF:
- return -EINVAL;
-#endif
+ return -ENOTTY;
+#endif
case TIOCGSOFTCAR:
copy_termios(real_tty, &kterm);
ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c
index 4b751b9285ad..7813dc910a19 100644
--- a/drivers/tty/tty_jobctrl.c
+++ b/drivers/tty/tty_jobctrl.c
@@ -11,6 +11,7 @@
#include <linux/tty.h>
#include <linux/fcntl.h>
#include <linux/uaccess.h>
+#include "tty.h"
static int is_ignored(int sig)
{
@@ -75,6 +76,7 @@ void proc_clear_tty(struct task_struct *p)
{
unsigned long flags;
struct tty_struct *tty;
+
spin_lock_irqsave(&p->sighand->siglock, flags);
tty = p->signal->tty;
p->signal->tty = NULL;
@@ -173,6 +175,7 @@ EXPORT_SYMBOL_GPL(get_current_tty);
void session_clear_tty(struct pid *session)
{
struct task_struct *p;
+
do_each_pid_task(session, PIDTYPE_SID, p) {
proc_clear_tty(p);
} while_each_pid_task(session, PIDTYPE_SID, p);
@@ -202,8 +205,10 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty) {
p->signal->tty = NULL;
- /* We defer the dereferences outside fo
- the tasklist lock */
+ /*
+ * We defer the dereferences outside of
+ * the tasklist lock.
+ */
refs++;
}
if (!p->signal->leader) {
@@ -240,10 +245,10 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
* it wants to disassociate itself from its controlling tty.
*
* It performs the following functions:
- * (1) Sends a SIGHUP and SIGCONT to the foreground process group
- * (2) Clears the tty from being controlling the session
- * (3) Clears the controlling tty for all processes in the
- * session group.
+ * (1) Sends a SIGHUP and SIGCONT to the foreground process group
+ * (2) Clears the tty from being controlling the session
+ * (3) Clears the controlling tty for all processes in the
+ * session group.
*
* The argument on_exit is set to 1 if called when a process is
* exiting; it is 0 if called by the ioctl TIOCNOTTY.
@@ -269,6 +274,7 @@ void disassociate_ctty(int on_exit)
tty_vhangup_session(tty);
} else {
struct pid *tty_pgrp = tty_get_pgrp(tty);
+
if (tty_pgrp) {
kill_pgrp(tty_pgrp, SIGHUP, on_exit);
if (!on_exit)
@@ -280,6 +286,7 @@ void disassociate_ctty(int on_exit)
} else if (on_exit) {
struct pid *old_pgrp;
+
spin_lock_irq(&current->sighand->siglock);
old_pgrp = current->signal->tty_old_pgrp;
current->signal->tty_old_pgrp = NULL;
@@ -324,10 +331,13 @@ void disassociate_ctty(int on_exit)
*/
void no_tty(void)
{
- /* FIXME: Review locking here. The tty_lock never covered any race
- between a new association and proc_clear_tty but possible we need
- to protect against this anyway */
+ /*
+ * FIXME: Review locking here. The tty_lock never covered any race
+ * between a new association and proc_clear_tty but possibly we need
+ * to protect against this anyway.
+ */
struct task_struct *tsk = current;
+
disassociate_ctty(0);
proc_clear_tty(tsk);
}
@@ -531,7 +541,7 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
/*
* (tty == real_tty) is a cheap way of
* testing if the tty is NOT a master pty.
- */
+ */
if (tty == real_tty && current->signal->tty != real_tty)
return -ENOTTY;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 1ba74d6f5e5c..03f414172f34 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -19,6 +19,7 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/ratelimit.h>
+#include "tty.h"
#undef LDISC_DEBUG_HANGUP
@@ -147,7 +148,7 @@ static int tty_ldisc_autoload = IS_BUILTIN(CONFIG_LDISC_AUTOLOAD);
* Returns: -EINVAL if the discipline index is not [N_TTY..NR_LDISCS] or
* if the discipline is not registered
* -EAGAIN if request_module() failed to load or register the
- * the discipline
+ * discipline
* -ENOMEM if allocation failure
*
* Otherwise, returns a pointer to the discipline and bumps the
@@ -459,7 +460,7 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
if (ld->ops->open) {
int ret;
- /* BTM here locks versus a hangup event */
+ /* BTM here locks versus a hangup event */
ret = ld->ops->open(tty);
if (ret)
clear_bit(TTY_LDISC_OPEN, &tty->flags);
@@ -508,7 +509,8 @@ static int tty_ldisc_failto(struct tty_struct *tty, int ld)
return PTR_ERR(disc);
tty->ldisc = disc;
tty_set_termios_ldisc(tty, ld);
- if ((r = tty_ldisc_open(tty, disc)) < 0)
+ r = tty_ldisc_open(tty, disc);
+ if (r < 0)
tty_ldisc_put(disc);
return r;
}
@@ -529,9 +531,11 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
const char *name = tty_name(tty);
pr_warn("Falling back ldisc for %s.\n", name);
- /* The traditional behaviour is to fall back to N_TTY, we
- want to avoid falling back to N_NULL unless we have no
- choice to avoid the risk of breaking anything */
+ /*
+ * The traditional behaviour is to fall back to N_TTY, we
+ * want to avoid falling back to N_NULL unless we have no
+ * choice to avoid the risk of breaking anything
+ */
if (tty_ldisc_failto(tty, N_TTY) < 0 &&
tty_ldisc_failto(tty, N_NULL) < 0)
panic("Couldn't open N_NULL ldisc for %s.", name);
@@ -600,17 +604,21 @@ int tty_set_ldisc(struct tty_struct *tty, int disc)
up_read(&tty->termios_rwsem);
}
- /* At this point we hold a reference to the new ldisc and a
- reference to the old ldisc, or we hold two references to
- the old ldisc (if it was restored as part of error cleanup
- above). In either case, releasing a single reference from
- the old ldisc is correct. */
+ /*
+ * At this point we hold a reference to the new ldisc and a
+ * reference to the old ldisc, or we hold two references to
+ * the old ldisc (if it was restored as part of error cleanup
+ * above). In either case, releasing a single reference from
+ * the old ldisc is correct.
+ */
new_ldisc = old_ldisc;
out:
tty_ldisc_unlock(tty);
- /* Restart the work queue in case no characters kick it off. Safe if
- already running */
+ /*
+ * Restart the work queue in case no characters kick it off. Safe if
+ * already running
+ */
tty_buffer_restart_work(tty->port);
err:
tty_ldisc_put(new_ldisc); /* drop the extra reference */
@@ -771,6 +779,7 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
{
int retval = tty_ldisc_open(tty, tty->ldisc);
+
if (retval)
return retval;
@@ -811,8 +820,10 @@ void tty_ldisc_release(struct tty_struct *tty)
tty_ldisc_kill(o_tty);
tty_ldisc_unlock_pair(tty, o_tty);
- /* And the memory resources remaining (buffers, termios) will be
- disposed of when the kref hits zero */
+ /*
+ * And the memory resources remaining (buffers, termios) will be
+ * disposed of when the kref hits zero
+ */
tty_ldisc_debug(tty, "released\n");
}
@@ -829,6 +840,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_release);
int tty_ldisc_init(struct tty_struct *tty)
{
struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
+
if (IS_ERR(ld))
return PTR_ERR(ld);
tty->ldisc = ld;
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 2640635ee177..393518a24cfe 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -4,6 +4,7 @@
#include <linux/kallsyms.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
+#include "tty.h"
/* Legacy tty mutex glue */
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 346d20f4a486..303c198fbf5c 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/serdev.h>
+#include "tty.h"
static int tty_port_default_receive_buf(struct tty_port *port,
const unsigned char *p,
diff --git a/drivers/tty/vcc.c b/drivers/tty/vcc.c
index e2d6205f83ce..0a3a71e14df4 100644
--- a/drivers/tty/vcc.c
+++ b/drivers/tty/vcc.c
@@ -14,16 +14,9 @@
#include <asm/vio.h>
#include <asm/ldc.h>
-#define DRV_MODULE_NAME "vcc"
-#define DRV_MODULE_VERSION "1.1"
-#define DRV_MODULE_RELDATE "July 1, 2017"
-
-static char version[] =
- DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
-
MODULE_DESCRIPTION("Sun LDOM virtual console concentrator driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_VERSION("1.1");
struct vcc_port {
struct vio_driver_state vio;
@@ -59,16 +52,14 @@ struct vcc_port {
#define VCC_CTL_BREAK -1
#define VCC_CTL_HUP -2
-static const char vcc_driver_name[] = "vcc";
-static const char vcc_device_node[] = "vcc";
static struct tty_driver *vcc_tty_driver;
static struct vcc_port *vcc_table[VCC_MAX_PORTS];
static DEFINE_SPINLOCK(vcc_table_lock);
-int vcc_dbg;
-int vcc_dbg_ldc;
-int vcc_dbg_vio;
+static unsigned int vcc_dbg;
+static unsigned int vcc_dbg_ldc;
+static unsigned int vcc_dbg_vio;
module_param(vcc_dbg, uint, 0664);
module_param(vcc_dbg_ldc, uint, 0664);
@@ -735,11 +726,6 @@ static int vcc_open(struct tty_struct *tty, struct file *vcc_file)
{
struct vcc_port *port;
- if (unlikely(!tty)) {
- pr_err("VCC: open: Invalid TTY handle\n");
- return -ENXIO;
- }
-
if (tty->count > 1)
return -EBUSY;
@@ -773,11 +759,6 @@ static int vcc_open(struct tty_struct *tty, struct file *vcc_file)
static void vcc_close(struct tty_struct *tty, struct file *vcc_file)
{
- if (unlikely(!tty)) {
- pr_err("VCC: close: Invalid TTY handle\n");
- return;
- }
-
if (unlikely(tty->count > 1))
return;
@@ -805,11 +786,6 @@ static void vcc_hangup(struct tty_struct *tty)
{
struct vcc_port *port;
- if (unlikely(!tty)) {
- pr_err("VCC: hangup: Invalid TTY handle\n");
- return;
- }
-
port = vcc_get_ne(tty->index);
if (unlikely(!port)) {
pr_err("VCC: hangup: Failed to find VCC port\n");
@@ -839,11 +815,6 @@ static int vcc_write(struct tty_struct *tty, const unsigned char *buf,
int tosend = 0;
int rv = -EINVAL;
- if (unlikely(!tty)) {
- pr_err("VCC: write: Invalid TTY handle\n");
- return -ENXIO;
- }
-
port = vcc_get_ne(tty->index);
if (unlikely(!port)) {
pr_err("VCC: write: Failed to find VCC port");
@@ -904,15 +875,10 @@ static int vcc_write_room(struct tty_struct *tty)
struct vcc_port *port;
u64 num;
- if (unlikely(!tty)) {
- pr_err("VCC: write_room: Invalid TTY handle\n");
- return -ENXIO;
- }
-
port = vcc_get_ne(tty->index);
if (unlikely(!port)) {
pr_err("VCC: write_room: Failed to find VCC port\n");
- return -ENODEV;
+ return 0;
}
num = VCC_BUFF_LEN - port->chars_in_buffer;
@@ -927,15 +893,10 @@ static int vcc_chars_in_buffer(struct tty_struct *tty)
struct vcc_port *port;
u64 num;
- if (unlikely(!tty)) {
- pr_err("VCC: chars_in_buffer: Invalid TTY handle\n");
- return -ENXIO;
- }
-
port = vcc_get_ne(tty->index);
if (unlikely(!port)) {
pr_err("VCC: chars_in_buffer: Failed to find VCC port\n");
- return -ENODEV;
+ return 0;
}
num = port->chars_in_buffer;
@@ -950,11 +911,6 @@ static int vcc_break_ctl(struct tty_struct *tty, int state)
struct vcc_port *port;
unsigned long flags;
- if (unlikely(!tty)) {
- pr_err("VCC: break_ctl: Invalid TTY handle\n");
- return -ENXIO;
- }
-
port = vcc_get_ne(tty->index);
if (unlikely(!port)) {
pr_err("VCC: break_ctl: Failed to find VCC port\n");
@@ -985,11 +941,6 @@ static int vcc_install(struct tty_driver *driver, struct tty_struct *tty)
struct tty_port *port_tty;
int ret;
- if (unlikely(!tty)) {
- pr_err("VCC: install: Invalid TTY handle\n");
- return -ENXIO;
- }
-
if (tty->index >= VCC_MAX_PORTS)
return -EINVAL;
@@ -1024,11 +975,6 @@ static void vcc_cleanup(struct tty_struct *tty)
{
struct vcc_port *port;
- if (unlikely(!tty)) {
- pr_err("VCC: cleanup: Invalid TTY handle\n");
- return;
- }
-
port = vcc_get(tty->index, true);
if (port) {
port->tty = NULL;
@@ -1066,16 +1012,14 @@ static int vcc_tty_init(void)
{
int rv;
- pr_info("VCC: %s\n", version);
-
vcc_tty_driver = tty_alloc_driver(VCC_MAX_PORTS, VCC_TTY_FLAGS);
if (IS_ERR(vcc_tty_driver)) {
pr_err("VCC: TTY driver alloc failed\n");
return PTR_ERR(vcc_tty_driver);
}
- vcc_tty_driver->driver_name = vcc_driver_name;
- vcc_tty_driver->name = vcc_device_node;
+ vcc_tty_driver->driver_name = "vcc";
+ vcc_tty_driver->name = "vcc";
vcc_tty_driver->minor_start = VCC_MINOR_START;
vcc_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 77638629c562..5d2309742718 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -2186,7 +2186,7 @@ void vt_reset_unicode(int console)
}
/**
- * vt_get_shiftstate - shift bit state
+ * vt_get_shift_state - shift bit state
*
* Report the shift bits from the keyboard state. We have to export
* this to support some oddities in the vt layer.
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 284b07224c55..01645e87b3d5 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1381,6 +1381,7 @@ struct vc_data *vc_deallocate(unsigned int currcons)
atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
vcs_remove_sysfs(currcons);
visual_deinit(vc);
+ con_free_unimap(vc);
put_pid(vc->vt_pid);
vc_uniscr_set(vc, NULL);
kfree(vc->vc_screenbuf);
@@ -4448,7 +4449,7 @@ void poke_blanked_console(void)
might_sleep();
/* This isn't perfectly race free, but a race here would be mostly harmless,
- * at worse, we'll do a spurrious blank and it's unlikely
+ * at worst, we'll do a spurious blank and it's unlikely
*/
del_timer(&console_timer);
blank_timer_expired = 0;
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 701dfb32b129..bb3d39307d93 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1042,7 +1042,7 @@ static int mos7720_write_room(struct tty_struct *tty)
mos7720_port = usb_get_serial_port_data(port);
if (mos7720_port == NULL)
- return -ENODEV;
+ return 0;
/* FIXME: Locking */
for (i = 0; i < NUM_URBS; ++i) {
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 962c12be9774..39258f9d36a0 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -79,7 +79,6 @@ static struct uni_pagedir *vgacon_uni_pagedir;
static int vgacon_refcount;
/* Description of the hardware situation */
-static bool vga_init_done;
static unsigned long vga_vram_base __read_mostly; /* Base of video memory */
static unsigned long vga_vram_end __read_mostly; /* End of video memory */
static unsigned int vga_vram_size __read_mostly; /* Size of video memory */
@@ -96,7 +95,7 @@ static bool vga_is_gfx;
static bool vga_512_chars;
static int vga_video_font_height;
static int vga_scan_lines __read_mostly;
-static unsigned int vga_rolled_over;
+static unsigned int vga_rolled_over; /* last vc_origin offset before wrap */
static bool vgacon_text_mode_force;
static bool vga_hardscroll_enabled;
@@ -359,8 +358,6 @@ static const char *vgacon_startup(void)
vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
vgacon_yres = vga_scan_lines;
- vga_init_done = true;
-
return display_desc;
}
diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
deleted file mode 100644
index 05ee0f19448a..000000000000
--- a/include/linux/cyclades.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* $Revision: 3.0 $$Date: 1998/11/02 14:20:59 $
- * linux/include/linux/cyclades.h
- *
- * This file was initially written by
- * Randolph Bentson <bentson@grieg.seaslug.org> and is maintained by
- * Ivan Passos <ivan@cyclades.com>.
- *
- * This file contains the general definitions for the cyclades.c driver
- *$Log: cyclades.h,v $
- *Revision 3.1 2002/01/29 11:36:16 henrique
- *added throttle field on struct cyclades_port to indicate whether the
- *port is throttled or not
- *
- *Revision 3.1 2000/04/19 18:52:52 ivan
- *converted address fields to unsigned long and added fields for physical
- *addresses on cyclades_card structure;
- *
- *Revision 3.0 1998/11/02 14:20:59 ivan
- *added nports field on cyclades_card structure;
- *
- *Revision 2.5 1998/08/03 16:57:01 ivan
- *added cyclades_idle_stats structure;
- *
- *Revision 2.4 1998/06/01 12:09:53 ivan
- *removed closing_wait2 from cyclades_port structure;
- *
- *Revision 2.3 1998/03/16 18:01:12 ivan
- *changes in the cyclades_port structure to get it closer to the
- *standard serial port structure;
- *added constants for new ioctls;
- *
- *Revision 2.2 1998/02/17 16:50:00 ivan
- *changes in the cyclades_port structure (addition of shutdown_wait and
- *chip_rev variables);
- *added constants for new ioctls and for CD1400 rev. numbers.
- *
- *Revision 2.1 1997/10/24 16:03:00 ivan
- *added rflow (which allows enabling the CD1400 special flow control
- *feature) and rtsdtr_inv (which allows DTR/RTS pin inversion) to
- *cyclades_port structure;
- *added Alpha support
- *
- *Revision 2.0 1997/06/30 10:30:00 ivan
- *added some new doorbell command constants related to IOCTLW and
- *UART error signaling
- *
- *Revision 1.8 1997/06/03 15:30:00 ivan
- *added constant ZFIRM_HLT
- *added constant CyPCI_Ze_win ( = 2 * Cy_PCI_Zwin)
- *
- *Revision 1.7 1997/03/26 10:30:00 daniel
- *new entries at the end of cyclades_port struct to reallocate
- *variables illegally allocated within card memory.
- *
- *Revision 1.6 1996/09/09 18:35:30 bentson
- *fold in changes for Cyclom-Z -- including structures for
- *communicating with board as well modest changes to original
- *structures to support new features.
- *
- *Revision 1.5 1995/11/13 21:13:31 bentson
- *changes suggested by Michael Chastain <mec@duracef.shout.net>
- *to support use of this file in non-kernel applications
- *
- *
- */
-#ifndef _LINUX_CYCLADES_H
-#define _LINUX_CYCLADES_H
-
-#include <uapi/linux/cyclades.h>
-
-
-/* Per card data structure */
-struct cyclades_card {
- void __iomem *base_addr;
- union {
- void __iomem *p9050;
- struct RUNTIME_9060 __iomem *p9060;
- } ctl_addr;
- struct BOARD_CTRL __iomem *board_ctrl; /* cyz specific */
- int irq;
- unsigned int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */
- unsigned int first_line; /* minor number of first channel on card */
- unsigned int nports; /* Number of ports in the card */
- int bus_index; /* address shift - 0 for ISA, 1 for PCI */
- int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */
- u32 hw_ver;
- spinlock_t card_lock;
- struct cyclades_port *ports;
-};
-
-/***************************************
- * Memory access functions/macros *
- * (required to support Alpha systems) *
- ***************************************/
-
-#define cy_writeb(port,val) do { writeb((val), (port)); mb(); } while (0)
-#define cy_writew(port,val) do { writew((val), (port)); mb(); } while (0)
-#define cy_writel(port,val) do { writel((val), (port)); mb(); } while (0)
-
-/*
- * Statistics counters
- */
-struct cyclades_icount {
- __u32 cts, dsr, rng, dcd, tx, rx;
- __u32 frame, parity, overrun, brk;
- __u32 buf_overrun;
-};
-
-/*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
- *
- * For definitions of the flags field, see tty.h
- */
-
-struct cyclades_port {
- int magic;
- struct tty_port port;
- struct cyclades_card *card;
- union {
- struct {
- void __iomem *base_addr;
- } cyy;
- struct {
- struct CH_CTRL __iomem *ch_ctrl;
- struct BUF_CTRL __iomem *buf_ctrl;
- } cyz;
- } u;
- int line;
- int flags; /* defined in tty.h */
- int type; /* UART type */
- int read_status_mask;
- int ignore_status_mask;
- int timeout;
- int xmit_fifo_size;
- int cor1,cor2,cor3,cor4,cor5;
- int tbpr,tco,rbpr,rco;
- int baud;
- int rflow;
- int rtsdtr_inv;
- int chip_rev;
- int custom_divisor;
- u8 x_char; /* to be pushed out ASAP */
- int breakon;
- int breakoff;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- int default_threshold;
- int default_timeout;
- unsigned long rflush_count;
- struct cyclades_monitor mon;
- struct cyclades_idle_stats idle_stats;
- struct cyclades_icount icount;
- struct completion shutdown_wait;
- int throttle;
-#ifdef CONFIG_CYZ_INTR
- struct timer_list rx_full_timer;
-#endif
-};
-
-#define CLOSING_WAIT_DELAY 30*HZ
-#define CY_CLOSING_WAIT_NONE ASYNC_CLOSING_WAIT_NONE
-#define CY_CLOSING_WAIT_INF ASYNC_CLOSING_WAIT_INF
-
-
-#define CyMAX_CHIPS_PER_CARD 8
-#define CyMAX_CHAR_FIFO 12
-#define CyPORTS_PER_CHIP 4
-#define CD1400_MAX_SPEED 115200
-
-#define CyISA_Ywin 0x2000
-
-#define CyPCI_Ywin 0x4000
-#define CyPCI_Yctl 0x80
-#define CyPCI_Zctl CTRL_WINDOW_SIZE
-#define CyPCI_Zwin 0x80000
-#define CyPCI_Ze_win (2 * CyPCI_Zwin)
-
-#define PCI_DEVICE_ID_MASK 0x06
-
-/**** CD1400 registers ****/
-
-#define CD1400_REV_G 0x46
-#define CD1400_REV_J 0x48
-
-#define CyRegSize 0x0400
-#define Cy_HwReset 0x1400
-#define Cy_ClrIntr 0x1800
-#define Cy_EpldRev 0x1e00
-
-/* Global Registers */
-
-#define CyGFRCR (0x40*2)
-#define CyRevE (44)
-#define CyCAR (0x68*2)
-#define CyCHAN_0 (0x00)
-#define CyCHAN_1 (0x01)
-#define CyCHAN_2 (0x02)
-#define CyCHAN_3 (0x03)
-#define CyGCR (0x4B*2)
-#define CyCH0_SERIAL (0x00)
-#define CyCH0_PARALLEL (0x80)
-#define CySVRR (0x67*2)
-#define CySRModem (0x04)
-#define CySRTransmit (0x02)
-#define CySRReceive (0x01)
-#define CyRICR (0x44*2)
-#define CyTICR (0x45*2)
-#define CyMICR (0x46*2)
-#define CyICR0 (0x00)
-#define CyICR1 (0x01)
-#define CyICR2 (0x02)
-#define CyICR3 (0x03)
-#define CyRIR (0x6B*2)
-#define CyTIR (0x6A*2)
-#define CyMIR (0x69*2)
-#define CyIRDirEq (0x80)
-#define CyIRBusy (0x40)
-#define CyIRUnfair (0x20)
-#define CyIRContext (0x1C)
-#define CyIRChannel (0x03)
-#define CyPPR (0x7E*2)
-#define CyCLOCK_20_1MS (0x27)
-#define CyCLOCK_25_1MS (0x31)
-#define CyCLOCK_25_5MS (0xf4)
-#define CyCLOCK_60_1MS (0x75)
-#define CyCLOCK_60_2MS (0xea)
-
-/* Virtual Registers */
-
-#define CyRIVR (0x43*2)
-#define CyTIVR (0x42*2)
-#define CyMIVR (0x41*2)
-#define CyIVRMask (0x07)
-#define CyIVRRxEx (0x07)
-#define CyIVRRxOK (0x03)
-#define CyIVRTxOK (0x02)
-#define CyIVRMdmOK (0x01)
-#define CyTDR (0x63*2)
-#define CyRDSR (0x62*2)
-#define CyTIMEOUT (0x80)
-#define CySPECHAR (0x70)
-#define CyBREAK (0x08)
-#define CyPARITY (0x04)
-#define CyFRAME (0x02)
-#define CyOVERRUN (0x01)
-#define CyMISR (0x4C*2)
-/* see CyMCOR_ and CyMSVR_ for bits*/
-#define CyEOSRR (0x60*2)
-
-/* Channel Registers */
-
-#define CyLIVR (0x18*2)
-#define CyMscsr (0x01)
-#define CyTdsr (0x02)
-#define CyRgdsr (0x03)
-#define CyRedsr (0x07)
-#define CyCCR (0x05*2)
-/* Format 1 */
-#define CyCHAN_RESET (0x80)
-#define CyCHIP_RESET (0x81)
-#define CyFlushTransFIFO (0x82)
-/* Format 2 */
-#define CyCOR_CHANGE (0x40)
-#define CyCOR1ch (0x02)
-#define CyCOR2ch (0x04)
-#define CyCOR3ch (0x08)
-/* Format 3 */
-#define CySEND_SPEC_1 (0x21)
-#define CySEND_SPEC_2 (0x22)
-#define CySEND_SPEC_3 (0x23)
-#define CySEND_SPEC_4 (0x24)
-/* Format 4 */
-#define CyCHAN_CTL (0x10)
-#define CyDIS_RCVR (0x01)
-#define CyENB_RCVR (0x02)
-#define CyDIS_XMTR (0x04)
-#define CyENB_XMTR (0x08)
-#define CySRER (0x06*2)
-#define CyMdmCh (0x80)
-#define CyRxData (0x10)
-#define CyTxRdy (0x04)
-#define CyTxMpty (0x02)
-#define CyNNDT (0x01)
-#define CyCOR1 (0x08*2)
-#define CyPARITY_NONE (0x00)
-#define CyPARITY_0 (0x20)
-#define CyPARITY_1 (0xA0)
-#define CyPARITY_E (0x40)
-#define CyPARITY_O (0xC0)
-#define Cy_1_STOP (0x00)
-#define Cy_1_5_STOP (0x04)
-#define Cy_2_STOP (0x08)
-#define Cy_5_BITS (0x00)
-#define Cy_6_BITS (0x01)
-#define Cy_7_BITS (0x02)
-#define Cy_8_BITS (0x03)
-#define CyCOR2 (0x09*2)
-#define CyIXM (0x80)
-#define CyTxIBE (0x40)
-#define CyETC (0x20)
-#define CyAUTO_TXFL (0x60)
-#define CyLLM (0x10)
-#define CyRLM (0x08)
-#define CyRtsAO (0x04)
-#define CyCtsAE (0x02)
-#define CyDsrAE (0x01)
-#define CyCOR3 (0x0A*2)
-#define CySPL_CH_DRANGE (0x80) /* special character detect range */
-#define CySPL_CH_DET1 (0x40) /* enable special character detection
- on SCHR4-SCHR3 */
-#define CyFL_CTRL_TRNSP (0x20) /* Flow Control Transparency */
-#define CySPL_CH_DET2 (0x10) /* Enable special character detection
- on SCHR2-SCHR1 */
-#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */
-#define CyCOR4 (0x1E*2)
-#define CyCOR5 (0x1F*2)
-#define CyCCSR (0x0B*2)
-#define CyRxEN (0x80)
-#define CyRxFloff (0x40)
-#define CyRxFlon (0x20)
-#define CyTxEN (0x08)
-#define CyTxFloff (0x04)
-#define CyTxFlon (0x02)
-#define CyRDCR (0x0E*2)
-#define CySCHR1 (0x1A*2)
-#define CySCHR2 (0x1B*2)
-#define CySCHR3 (0x1C*2)
-#define CySCHR4 (0x1D*2)
-#define CySCRL (0x22*2)
-#define CySCRH (0x23*2)
-#define CyLNC (0x24*2)
-#define CyMCOR1 (0x15*2)
-#define CyMCOR2 (0x16*2)
-#define CyRTPR (0x21*2)
-#define CyMSVR1 (0x6C*2)
-#define CyMSVR2 (0x6D*2)
-#define CyANY_DELTA (0xF0)
-#define CyDSR (0x80)
-#define CyCTS (0x40)
-#define CyRI (0x20)
-#define CyDCD (0x10)
-#define CyDTR (0x02)
-#define CyRTS (0x01)
-#define CyPVSR (0x6F*2)
-#define CyRBPR (0x78*2)
-#define CyRCOR (0x7C*2)
-#define CyTBPR (0x72*2)
-#define CyTCOR (0x76*2)
-
-/* Custom Registers */
-
-#define CyPLX_VER (0x3400)
-#define PLX_9050 0x0b
-#define PLX_9060 0x0c
-#define PLX_9080 0x0d
-
-/***************************************************************************/
-
-#endif /* _LINUX_CYCLADES_H */
diff --git a/include/linux/isicom.h b/include/linux/isicom.h
deleted file mode 100644
index 7de6822d7b1a..000000000000
--- a/include/linux/isicom.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _LINUX_ISICOM_H
-#define _LINUX_ISICOM_H
-
-#define YES 1
-#define NO 0
-
-/*
- * ISICOM Driver definitions ...
- *
- */
-
-#define ISICOM_NAME "ISICom"
-
-/*
- * PCI definitions
- */
-
-#define DEVID_COUNT 9
-#define VENDOR_ID 0x10b5
-
-/*
- * These are now officially allocated numbers
- */
-
-#define ISICOM_NMAJOR 112 /* normal */
-#define ISICOM_CMAJOR 113 /* callout */
-#define ISICOM_MAGIC (('M' << 8) | 'T')
-
-#define WAKEUP_CHARS 256 /* hard coded for now */
-#define TX_SIZE 254
-
-#define BOARD_COUNT 4
-#define PORT_COUNT (BOARD_COUNT*16)
-
-/* character sizes */
-
-#define ISICOM_CS5 0x0000
-#define ISICOM_CS6 0x0001
-#define ISICOM_CS7 0x0002
-#define ISICOM_CS8 0x0003
-
-/* stop bits */
-
-#define ISICOM_1SB 0x0000
-#define ISICOM_2SB 0x0004
-
-/* parity */
-
-#define ISICOM_NOPAR 0x0000
-#define ISICOM_ODPAR 0x0008
-#define ISICOM_EVPAR 0x0018
-
-/* flow control */
-
-#define ISICOM_CTSRTS 0x03
-#define ISICOM_INITIATE_XONXOFF 0x04
-#define ISICOM_RESPOND_XONXOFF 0x08
-
-#define BOARD(line) (((line) >> 4) & 0x3)
-
- /* isi kill queue bitmap */
-
-#define ISICOM_KILLTX 0x01
-#define ISICOM_KILLRX 0x02
-
- /* isi_board status bitmap */
-
-#define FIRMWARE_LOADED 0x0001
-#define BOARD_ACTIVE 0x0002
-#define BOARD_INIT 0x0004
-
- /* isi_port status bitmap */
-
-#define ISI_CTS 0x1000
-#define ISI_DSR 0x2000
-#define ISI_RI 0x4000
-#define ISI_DCD 0x8000
-#define ISI_DTR 0x0100
-#define ISI_RTS 0x0200
-
-
-#define ISI_TXOK 0x0001
-
-#endif /* ISICOM_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index a76ccb697bef..4c3fa5293d76 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1688,37 +1688,8 @@
#define PCI_VENDOR_ID_MICROSEMI 0x11f8
#define PCI_VENDOR_ID_RP 0x11fe
-#define PCI_DEVICE_ID_RP32INTF 0x0001
-#define PCI_DEVICE_ID_RP8INTF 0x0002
-#define PCI_DEVICE_ID_RP16INTF 0x0003
-#define PCI_DEVICE_ID_RP4QUAD 0x0004
-#define PCI_DEVICE_ID_RP8OCTA 0x0005
-#define PCI_DEVICE_ID_RP8J 0x0006
-#define PCI_DEVICE_ID_RP4J 0x0007
-#define PCI_DEVICE_ID_RP8SNI 0x0008
-#define PCI_DEVICE_ID_RP16SNI 0x0009
-#define PCI_DEVICE_ID_RPP4 0x000A
-#define PCI_DEVICE_ID_RPP8 0x000B
-#define PCI_DEVICE_ID_RP4M 0x000D
-#define PCI_DEVICE_ID_RP2_232 0x000E
-#define PCI_DEVICE_ID_RP2_422 0x000F
-#define PCI_DEVICE_ID_URP32INTF 0x0801
-#define PCI_DEVICE_ID_URP8INTF 0x0802
-#define PCI_DEVICE_ID_URP16INTF 0x0803
-#define PCI_DEVICE_ID_URP8OCTA 0x0805
-#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C
-#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D
-#define PCI_DEVICE_ID_CRP16INTF 0x0903
#define PCI_VENDOR_ID_CYCLADES 0x120e
-#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100
-#define PCI_DEVICE_ID_CYCLOM_Y_Hi 0x0101
-#define PCI_DEVICE_ID_CYCLOM_4Y_Lo 0x0102
-#define PCI_DEVICE_ID_CYCLOM_4Y_Hi 0x0103
-#define PCI_DEVICE_ID_CYCLOM_8Y_Lo 0x0104
-#define PCI_DEVICE_ID_CYCLOM_8Y_Hi 0x0105
-#define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200
-#define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201
#define PCI_DEVICE_ID_PC300_RX_2 0x0300
#define PCI_DEVICE_ID_PC300_RX_1 0x0301
#define PCI_DEVICE_ID_PC300_TE_2 0x0310
@@ -2065,8 +2036,6 @@
#define PCI_DEVICE_ID_EXAR_XR17V358 0x0358
#define PCI_VENDOR_ID_MICROGATE 0x13c0
-#define PCI_DEVICE_ID_MICROGATE_USC 0x0010
-#define PCI_DEVICE_ID_MICROGATE_SCA 0x0030
#define PCI_VENDOR_ID_3WARE 0x13C1
#define PCI_DEVICE_ID_3WARE_1000 0x1000
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e1b684e33841..d7ed00f1594e 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -500,19 +500,19 @@ static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int c
return 0;
}
-static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
+static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
{
int sysrq_ch;
if (!port->has_sysrq) {
- spin_unlock_irqrestore(&port->lock, irqflags);
+ spin_unlock(&port->lock);
return;
}
sysrq_ch = port->sysrq_ch;
port->sysrq_ch = 0;
- spin_unlock_irqrestore(&port->lock, irqflags);
+ spin_unlock(&port->lock);
if (sysrq_ch)
handle_sysrq(sysrq_ch);
@@ -526,9 +526,9 @@ static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int c
{
return 0;
}
-static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
+static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
{
- spin_unlock_irqrestore(&port->lock, irqflags);
+ spin_unlock(&port->lock);
}
#endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h
index ca2c5393dc6b..f6c3323fc4c5 100644
--- a/include/linux/serial_s3c.h
+++ b/include/linux/serial_s3c.h
@@ -246,6 +246,22 @@
S5PV210_UFCON_TXTRIG4 | \
S5PV210_UFCON_RXTRIG4)
+#define APPLE_S5L_UCON_RXTO_ENA 9
+#define APPLE_S5L_UCON_RXTHRESH_ENA 12
+#define APPLE_S5L_UCON_TXTHRESH_ENA 13
+#define APPLE_S5L_UCON_RXTO_ENA_MSK (1 << APPLE_S5L_UCON_RXTO_ENA)
+#define APPLE_S5L_UCON_RXTHRESH_ENA_MSK (1 << APPLE_S5L_UCON_RXTHRESH_ENA)
+#define APPLE_S5L_UCON_TXTHRESH_ENA_MSK (1 << APPLE_S5L_UCON_TXTHRESH_ENA)
+
+#define APPLE_S5L_UCON_DEFAULT (S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI)
+
+#define APPLE_S5L_UTRSTAT_RXTHRESH (1<<4)
+#define APPLE_S5L_UTRSTAT_TXTHRESH (1<<5)
+#define APPLE_S5L_UTRSTAT_RXTO (1<<9)
+#define APPLE_S5L_UTRSTAT_ALL_FLAGS (0x3f0)
+
#ifndef __ASSEMBLY__
#include <linux/serial_core.h>
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 95fc2f100f12..e5d6b1f28823 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -17,30 +17,6 @@
/*
- * Lock subclasses for tty locks
- *
- * TTY_LOCK_NORMAL is for normal ttys and master ptys.
- * TTY_LOCK_SLAVE is for slave ptys only.
- *
- * Lock subclasses are necessary for handling nested locking with pty pairs.
- * tty locks which use nested locking:
- *
- * legacy_mutex - Nested tty locks are necessary for releasing pty pairs.
- * The stable lock order is master pty first, then slave pty.
- * termios_rwsem - The stable lock order is tty_buffer lock->termios_rwsem.
- * Subclassing this lock enables the slave pty to hold its
- * termios_rwsem when claiming the master tty_buffer lock.
- * tty_buffer lock - slave ptys can claim nested buffer lock when handling
- * signal chars. The stable lock order is slave pty, then
- * master.
- */
-
-enum {
- TTY_LOCK_NORMAL = 0,
- TTY_LOCK_SLAVE,
-};
-
-/*
* (Note: the *_driver.minor_start values 1, 64, 128, 192 are
* hardcoded at present.)
*/
@@ -284,7 +260,7 @@ struct tty_operations;
struct tty_struct {
int magic;
struct kref kref;
- struct device *dev;
+ struct device *dev; /* class device or NULL (e.g. ptys, serdev) */
struct tty_driver *driver;
const struct tty_operations *ops;
int index;
@@ -373,21 +349,6 @@ struct tty_file_private {
#define TTY_LDISC_CHANGING 20 /* Change pending - non-block IO */
#define TTY_LDISC_HALTED 22 /* Line discipline is halted */
-/* Values for tty->flow_change */
-#define TTY_THROTTLE_SAFE 1
-#define TTY_UNTHROTTLE_SAFE 2
-
-static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
-{
- tty->flow_change = val;
-}
-
-static inline void tty_set_flow_change(struct tty_struct *tty, int val)
-{
- tty->flow_change = val;
- smp_mb();
-}
-
static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file)
{
return file->f_flags & O_NONBLOCK ||
@@ -419,10 +380,6 @@ extern struct tty_struct *tty_kopen_exclusive(dev_t device);
extern struct tty_struct *tty_kopen_shared(dev_t device);
extern void tty_kclose(struct tty_struct *tty);
extern int tty_dev_name_to_number(const char *name, dev_t *number);
-extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
-extern void tty_ldisc_unlock(struct tty_struct *tty);
-extern ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
-extern struct file *tty_release_redirect(struct tty_struct *tty);
#else
static inline void tty_kref_put(struct tty_struct *tty)
{ }
@@ -475,14 +432,10 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
extern const char *tty_driver_name(const struct tty_struct *tty);
extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
-extern int __tty_check_change(struct tty_struct *tty, int sig);
-extern int tty_check_change(struct tty_struct *tty);
-extern void __stop_tty(struct tty_struct *tty);
extern void stop_tty(struct tty_struct *tty);
-extern void __start_tty(struct tty_struct *tty);
extern void start_tty(struct tty_struct *tty);
extern int tty_register_driver(struct tty_driver *driver);
-extern int tty_unregister_driver(struct tty_driver *driver);
+extern void tty_unregister_driver(struct tty_driver *driver);
extern struct device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *dev);
extern struct device *tty_register_device_attr(struct tty_driver *driver,
@@ -506,23 +459,11 @@ extern int tty_get_icount(struct tty_struct *tty,
extern int is_current_pgrp_orphaned(void);
extern void tty_hangup(struct tty_struct *tty);
extern void tty_vhangup(struct tty_struct *tty);
-extern void tty_vhangup_session(struct tty_struct *tty);
extern int tty_hung_up_p(struct file *filp);
extern void do_SAK(struct tty_struct *tty);
extern void __do_SAK(struct tty_struct *tty);
-extern void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
-extern int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
-extern void session_clear_tty(struct pid *session);
extern void no_tty(void);
-extern void tty_buffer_free_all(struct tty_port *port);
-extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
-extern void tty_buffer_init(struct tty_port *port);
-extern void tty_buffer_set_lock_subclass(struct tty_port *port);
-extern bool tty_buffer_restart_work(struct tty_port *port);
-extern bool tty_buffer_cancel_work(struct tty_port *port);
-extern void tty_buffer_flush_work(struct tty_port *port);
extern speed_t tty_termios_baud_rate(struct ktermios *termios);
-extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
extern void tty_termios_encode_baud_rate(struct ktermios *termios,
speed_t ibaud, speed_t obaud);
extern void tty_encode_baud_rate(struct tty_struct *tty,
@@ -550,27 +491,16 @@ extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
extern void tty_ldisc_deref(struct tty_ldisc *);
extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
-extern void tty_ldisc_hangup(struct tty_struct *tty, bool reset);
-extern int tty_ldisc_reinit(struct tty_struct *tty, int disc);
extern const struct seq_operations tty_ldiscs_seq_ops;
extern void tty_wakeup(struct tty_struct *tty);
extern void tty_ldisc_flush(struct tty_struct *tty);
-extern long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
-extern long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
- struct file *file, unsigned int cmd, unsigned long arg);
extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
-extern void tty_default_fops(struct file_operations *fops);
-extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
-extern int tty_alloc_file(struct file *file);
-extern void tty_add_file(struct tty_struct *tty, struct file *file);
-extern void tty_free_file(struct file *file);
extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
extern void tty_release_struct(struct tty_struct *tty, int idx);
-extern int tty_release(struct inode *inode, struct file *filp);
extern void tty_init_termios(struct tty_struct *tty);
extern void tty_save_termios(struct tty_struct *tty);
extern int tty_standard_install(struct tty_driver *driver,
@@ -578,8 +508,6 @@ extern int tty_standard_install(struct tty_driver *driver,
extern struct mutex tty_mutex;
-#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
-
extern void tty_port_init(struct tty_port *port);
extern void tty_port_link_device(struct tty_port *port,
struct tty_driver *driver, unsigned index);
@@ -699,13 +627,8 @@ static inline int tty_port_users(struct tty_port *port)
extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
extern int tty_unregister_ldisc(int disc);
extern int tty_set_ldisc(struct tty_struct *tty, int disc);
-extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
-extern void tty_ldisc_release(struct tty_struct *tty);
-extern int __must_check tty_ldisc_init(struct tty_struct *tty);
-extern void tty_ldisc_deinit(struct tty_struct *tty);
extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
char *f, int count);
-extern void tty_sysctl_init(void);
/* n_tty.c */
extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
@@ -717,20 +640,10 @@ static inline void n_tty_init(void) { }
/* tty_audit.c */
#ifdef CONFIG_AUDIT
-extern void tty_audit_add_data(struct tty_struct *tty, const void *data,
- size_t size);
extern void tty_audit_exit(void);
extern void tty_audit_fork(struct signal_struct *sig);
-extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
extern int tty_audit_push(void);
#else
-static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
- size_t size)
-{
-}
-static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
-{
-}
static inline void tty_audit_exit(void)
{
}
@@ -772,16 +685,4 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {}
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
#endif
-#define tty_msg(fn, tty, f, ...) \
- fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__)
-
-#define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__)
-#define tty_info(tty, f, ...) tty_msg(pr_info, tty, f, ##__VA_ARGS__)
-#define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__)
-#define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__)
-#define tty_err(tty, f, ...) tty_msg(pr_err, tty, f, ##__VA_ARGS__)
-
-#define tty_info_ratelimited(tty, f, ...) \
- tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
-
#endif
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 61c3372d3f32..2f719b471d52 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -228,7 +228,7 @@
*
* Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
* structure to complete. This method is optional and will only be called
- * if provided (otherwise EINVAL will be returned).
+ * if provided (otherwise ENOTTY will be returned).
*/
#include <linux/export.h>
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 572a07976116..31284b55bd4f 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -173,7 +173,6 @@ extern int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
struct tty_ldisc_ops {
- int magic;
char *name;
int num;
int flags;
@@ -218,8 +217,6 @@ struct tty_ldisc {
struct tty_struct *tty;
};
-#define TTY_LDISC_MAGIC 0x5403
-
#define LDISC_FLAG_DEFINED 0x00000001
#define MODULE_ALIAS_LDISC(ldisc) \
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 43c9c5d2bedb..bd76e8e082c0 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -430,8 +430,6 @@ struct nci_uart_ops {
int (*open)(struct nci_uart *nci_uart);
void (*close)(struct nci_uart *nci_uart);
int (*recv)(struct nci_uart *nci_uart, struct sk_buff *skb);
- int (*recv_buf)(struct nci_uart *nci_uart, const u8 *data, char *flags,
- int count);
int (*send)(struct nci_uart *nci_uart, struct sk_buff *skb);
void (*tx_start)(struct nci_uart *nci_uart);
void (*tx_done)(struct nci_uart *nci_uart);
diff --git a/include/uapi/linux/cyclades.h b/include/uapi/linux/cyclades.h
deleted file mode 100644
index fc0add2194a9..000000000000
--- a/include/uapi/linux/cyclades.h
+++ /dev/null
@@ -1,494 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* $Revision: 3.0 $$Date: 1998/11/02 14:20:59 $
- * linux/include/linux/cyclades.h
- *
- * This file was initially written by
- * Randolph Bentson <bentson@grieg.seaslug.org> and is maintained by
- * Ivan Passos <ivan@cyclades.com>.
- *
- * This file contains the general definitions for the cyclades.c driver
- *$Log: cyclades.h,v $
- *Revision 3.1 2002/01/29 11:36:16 henrique
- *added throttle field on struct cyclades_port to indicate whether the
- *port is throttled or not
- *
- *Revision 3.1 2000/04/19 18:52:52 ivan
- *converted address fields to unsigned long and added fields for physical
- *addresses on cyclades_card structure;
- *
- *Revision 3.0 1998/11/02 14:20:59 ivan
- *added nports field on cyclades_card structure;
- *
- *Revision 2.5 1998/08/03 16:57:01 ivan
- *added cyclades_idle_stats structure;
- *
- *Revision 2.4 1998/06/01 12:09:53 ivan
- *removed closing_wait2 from cyclades_port structure;
- *
- *Revision 2.3 1998/03/16 18:01:12 ivan
- *changes in the cyclades_port structure to get it closer to the
- *standard serial port structure;
- *added constants for new ioctls;
- *
- *Revision 2.2 1998/02/17 16:50:00 ivan
- *changes in the cyclades_port structure (addition of shutdown_wait and
- *chip_rev variables);
- *added constants for new ioctls and for CD1400 rev. numbers.
- *
- *Revision 2.1 1997/10/24 16:03:00 ivan
- *added rflow (which allows enabling the CD1400 special flow control
- *feature) and rtsdtr_inv (which allows DTR/RTS pin inversion) to
- *cyclades_port structure;
- *added Alpha support
- *
- *Revision 2.0 1997/06/30 10:30:00 ivan
- *added some new doorbell command constants related to IOCTLW and
- *UART error signaling
- *
- *Revision 1.8 1997/06/03 15:30:00 ivan
- *added constant ZFIRM_HLT
- *added constant CyPCI_Ze_win ( = 2 * Cy_PCI_Zwin)
- *
- *Revision 1.7 1997/03/26 10:30:00 daniel
- *new entries at the end of cyclades_port struct to reallocate
- *variables illegally allocated within card memory.
- *
- *Revision 1.6 1996/09/09 18:35:30 bentson
- *fold in changes for Cyclom-Z -- including structures for
- *communicating with board as well modest changes to original
- *structures to support new features.
- *
- *Revision 1.5 1995/11/13 21:13:31 bentson
- *changes suggested by Michael Chastain <mec@duracef.shout.net>
- *to support use of this file in non-kernel applications
- *
- *
- */
-
-#ifndef _UAPI_LINUX_CYCLADES_H
-#define _UAPI_LINUX_CYCLADES_H
-
-#include <linux/types.h>
-
-struct cyclades_monitor {
- unsigned long int_count;
- unsigned long char_count;
- unsigned long char_max;
- unsigned long char_last;
-};
-
-/*
- * These stats all reflect activity since the device was last initialized.
- * (i.e., since the port was opened with no other processes already having it
- * open)
- */
-struct cyclades_idle_stats {
- __kernel_old_time_t in_use; /* Time device has been in use (secs) */
- __kernel_old_time_t recv_idle; /* Time since last char received (secs) */
- __kernel_old_time_t xmit_idle; /* Time since last char transmitted (secs) */
- unsigned long recv_bytes; /* Bytes received */
- unsigned long xmit_bytes; /* Bytes transmitted */
- unsigned long overruns; /* Input overruns */
- unsigned long frame_errs; /* Input framing errors */
- unsigned long parity_errs; /* Input parity errors */
-};
-
-#define CYCLADES_MAGIC 0x4359
-
-#define CYGETMON 0x435901
-#define CYGETTHRESH 0x435902
-#define CYSETTHRESH 0x435903
-#define CYGETDEFTHRESH 0x435904
-#define CYSETDEFTHRESH 0x435905
-#define CYGETTIMEOUT 0x435906
-#define CYSETTIMEOUT 0x435907
-#define CYGETDEFTIMEOUT 0x435908
-#define CYSETDEFTIMEOUT 0x435909
-#define CYSETRFLOW 0x43590a
-#define CYGETRFLOW 0x43590b
-#define CYSETRTSDTR_INV 0x43590c
-#define CYGETRTSDTR_INV 0x43590d
-#define CYZSETPOLLCYCLE 0x43590e
-#define CYZGETPOLLCYCLE 0x43590f
-#define CYGETCD1400VER 0x435910
-#define CYSETWAIT 0x435912
-#define CYGETWAIT 0x435913
-
-/*************** CYCLOM-Z ADDITIONS ***************/
-
-#define CZIOC ('M' << 8)
-#define CZ_NBOARDS (CZIOC|0xfa)
-#define CZ_BOOT_START (CZIOC|0xfb)
-#define CZ_BOOT_DATA (CZIOC|0xfc)
-#define CZ_BOOT_END (CZIOC|0xfd)
-#define CZ_TEST (CZIOC|0xfe)
-
-#define CZ_DEF_POLL (HZ/25)
-
-#define MAX_BOARD 4 /* Max number of boards */
-#define MAX_DEV 256 /* Max number of ports total */
-#define CYZ_MAX_SPEED 921600
-
-#define CYZ_FIFO_SIZE 16
-
-#define CYZ_BOOT_NWORDS 0x100
-struct CYZ_BOOT_CTRL {
- unsigned short nboard;
- int status[MAX_BOARD];
- int nchannel[MAX_BOARD];
- int fw_rev[MAX_BOARD];
- unsigned long offset;
- unsigned long data[CYZ_BOOT_NWORDS];
-};
-
-
-#ifndef DP_WINDOW_SIZE
-/*
- * Memory Window Sizes
- */
-
-#define DP_WINDOW_SIZE (0x00080000) /* window size 512 Kb */
-#define ZE_DP_WINDOW_SIZE (0x00100000) /* window size 1 Mb (Ze and
- 8Zo V.2 */
-#define CTRL_WINDOW_SIZE (0x00000080) /* runtime regs 128 bytes */
-
-/*
- * CUSTOM_REG - Cyclom-Z/PCI Custom Registers Set. The driver
- * normally will access only interested on the fpga_id, fpga_version,
- * start_cpu and stop_cpu.
- */
-
-struct CUSTOM_REG {
- __u32 fpga_id; /* FPGA Identification Register */
- __u32 fpga_version; /* FPGA Version Number Register */
- __u32 cpu_start; /* CPU start Register (write) */
- __u32 cpu_stop; /* CPU stop Register (write) */
- __u32 misc_reg; /* Miscellaneous Register */
- __u32 idt_mode; /* IDT mode Register */
- __u32 uart_irq_status; /* UART IRQ status Register */
- __u32 clear_timer0_irq; /* Clear timer interrupt Register */
- __u32 clear_timer1_irq; /* Clear timer interrupt Register */
- __u32 clear_timer2_irq; /* Clear timer interrupt Register */
- __u32 test_register; /* Test Register */
- __u32 test_count; /* Test Count Register */
- __u32 timer_select; /* Timer select register */
- __u32 pr_uart_irq_status; /* Prioritized UART IRQ stat Reg */
- __u32 ram_wait_state; /* RAM wait-state Register */
- __u32 uart_wait_state; /* UART wait-state Register */
- __u32 timer_wait_state; /* timer wait-state Register */
- __u32 ack_wait_state; /* ACK wait State Register */
-};
-
-/*
- * RUNTIME_9060 - PLX PCI9060ES local configuration and shared runtime
- * registers. This structure can be used to access the 9060 registers
- * (memory mapped).
- */
-
-struct RUNTIME_9060 {
- __u32 loc_addr_range; /* 00h - Local Address Range */
- __u32 loc_addr_base; /* 04h - Local Address Base */
- __u32 loc_arbitr; /* 08h - Local Arbitration */
- __u32 endian_descr; /* 0Ch - Big/Little Endian Descriptor */
- __u32 loc_rom_range; /* 10h - Local ROM Range */
- __u32 loc_rom_base; /* 14h - Local ROM Base */
- __u32 loc_bus_descr; /* 18h - Local Bus descriptor */
- __u32 loc_range_mst; /* 1Ch - Local Range for Master to PCI */
- __u32 loc_base_mst; /* 20h - Local Base for Master PCI */
- __u32 loc_range_io; /* 24h - Local Range for Master IO */
- __u32 pci_base_mst; /* 28h - PCI Base for Master PCI */
- __u32 pci_conf_io; /* 2Ch - PCI configuration for Master IO */
- __u32 filler1; /* 30h */
- __u32 filler2; /* 34h */
- __u32 filler3; /* 38h */
- __u32 filler4; /* 3Ch */
- __u32 mail_box_0; /* 40h - Mail Box 0 */
- __u32 mail_box_1; /* 44h - Mail Box 1 */
- __u32 mail_box_2; /* 48h - Mail Box 2 */
- __u32 mail_box_3; /* 4Ch - Mail Box 3 */
- __u32 filler5; /* 50h */
- __u32 filler6; /* 54h */
- __u32 filler7; /* 58h */
- __u32 filler8; /* 5Ch */
- __u32 pci_doorbell; /* 60h - PCI to Local Doorbell */
- __u32 loc_doorbell; /* 64h - Local to PCI Doorbell */
- __u32 intr_ctrl_stat; /* 68h - Interrupt Control/Status */
- __u32 init_ctrl; /* 6Ch - EEPROM control, Init Control, etc */
-};
-
-/* Values for the Local Base Address re-map register */
-
-#define WIN_RAM 0x00000001L /* set the sliding window to RAM */
-#define WIN_CREG 0x14000001L /* set the window to custom Registers */
-
-/* Values timer select registers */
-
-#define TIMER_BY_1M 0x00 /* clock divided by 1M */
-#define TIMER_BY_256K 0x01 /* clock divided by 256k */
-#define TIMER_BY_128K 0x02 /* clock divided by 128k */
-#define TIMER_BY_32K 0x03 /* clock divided by 32k */
-
-/****************** ****************** *******************/
-#endif
-
-#ifndef ZFIRM_ID
-/* #include "zfwint.h" */
-/****************** ****************** *******************/
-/*
- * This file contains the definitions for interfacing with the
- * Cyclom-Z ZFIRM Firmware.
- */
-
-/* General Constant definitions */
-
-#define MAX_CHAN 64 /* max number of channels per board */
-
-/* firmware id structure (set after boot) */
-
-#define ID_ADDRESS 0x00000180L /* signature/pointer address */
-#define ZFIRM_ID 0x5557465AL /* ZFIRM/U signature */
-#define ZFIRM_HLT 0x59505B5CL /* ZFIRM needs external power supply */
-#define ZFIRM_RST 0x56040674L /* RST signal (due to FW reset) */
-
-#define ZF_TINACT_DEF 1000 /* default inactivity timeout
- (1000 ms) */
-#define ZF_TINACT ZF_TINACT_DEF
-
-struct FIRM_ID {
- __u32 signature; /* ZFIRM/U signature */
- __u32 zfwctrl_addr; /* pointer to ZFW_CTRL structure */
-};
-
-/* Op. System id */
-
-#define C_OS_LINUX 0x00000030 /* generic Linux system */
-
-/* channel op_mode */
-
-#define C_CH_DISABLE 0x00000000 /* channel is disabled */
-#define C_CH_TXENABLE 0x00000001 /* channel Tx enabled */
-#define C_CH_RXENABLE 0x00000002 /* channel Rx enabled */
-#define C_CH_ENABLE 0x00000003 /* channel Tx/Rx enabled */
-#define C_CH_LOOPBACK 0x00000004 /* Loopback mode */
-
-/* comm_parity - parity */
-
-#define C_PR_NONE 0x00000000 /* None */
-#define C_PR_ODD 0x00000001 /* Odd */
-#define C_PR_EVEN 0x00000002 /* Even */
-#define C_PR_MARK 0x00000004 /* Mark */
-#define C_PR_SPACE 0x00000008 /* Space */
-#define C_PR_PARITY 0x000000ff
-
-#define C_PR_DISCARD 0x00000100 /* discard char with frame/par error */
-#define C_PR_IGNORE 0x00000200 /* ignore frame/par error */
-
-/* comm_data_l - data length and stop bits */
-
-#define C_DL_CS5 0x00000001
-#define C_DL_CS6 0x00000002
-#define C_DL_CS7 0x00000004
-#define C_DL_CS8 0x00000008
-#define C_DL_CS 0x0000000f
-#define C_DL_1STOP 0x00000010
-#define C_DL_15STOP 0x00000020
-#define C_DL_2STOP 0x00000040
-#define C_DL_STOP 0x000000f0
-
-/* interrupt enabling/status */
-
-#define C_IN_DISABLE 0x00000000 /* zero, disable interrupts */
-#define C_IN_TXBEMPTY 0x00000001 /* tx buffer empty */
-#define C_IN_TXLOWWM 0x00000002 /* tx buffer below LWM */
-#define C_IN_RXHIWM 0x00000010 /* rx buffer above HWM */
-#define C_IN_RXNNDT 0x00000020 /* rx no new data timeout */
-#define C_IN_MDCD 0x00000100 /* modem DCD change */
-#define C_IN_MDSR 0x00000200 /* modem DSR change */
-#define C_IN_MRI 0x00000400 /* modem RI change */
-#define C_IN_MCTS 0x00000800 /* modem CTS change */
-#define C_IN_RXBRK 0x00001000 /* Break received */
-#define C_IN_PR_ERROR 0x00002000 /* parity error */
-#define C_IN_FR_ERROR 0x00004000 /* frame error */
-#define C_IN_OVR_ERROR 0x00008000 /* overrun error */
-#define C_IN_RXOFL 0x00010000 /* RX buffer overflow */
-#define C_IN_IOCTLW 0x00020000 /* I/O control w/ wait */
-#define C_IN_MRTS 0x00040000 /* modem RTS drop */
-#define C_IN_ICHAR 0x00080000
-
-/* flow control */
-
-#define C_FL_OXX 0x00000001 /* output Xon/Xoff flow control */
-#define C_FL_IXX 0x00000002 /* output Xon/Xoff flow control */
-#define C_FL_OIXANY 0x00000004 /* output Xon/Xoff (any xon) */
-#define C_FL_SWFLOW 0x0000000f
-
-/* flow status */
-
-#define C_FS_TXIDLE 0x00000000 /* no Tx data in the buffer or UART */
-#define C_FS_SENDING 0x00000001 /* UART is sending data */
-#define C_FS_SWFLOW 0x00000002 /* Tx is stopped by received Xoff */
-
-/* rs_control/rs_status RS-232 signals */
-
-#define C_RS_PARAM 0x80000000 /* Indicates presence of parameter in
- IOCTLM command */
-#define C_RS_RTS 0x00000001 /* RTS */
-#define C_RS_DTR 0x00000004 /* DTR */
-#define C_RS_DCD 0x00000100 /* CD */
-#define C_RS_DSR 0x00000200 /* DSR */
-#define C_RS_RI 0x00000400 /* RI */
-#define C_RS_CTS 0x00000800 /* CTS */
-
-/* commands Host <-> Board */
-
-#define C_CM_RESET 0x01 /* reset/flush buffers */
-#define C_CM_IOCTL 0x02 /* re-read CH_CTRL */
-#define C_CM_IOCTLW 0x03 /* re-read CH_CTRL, intr when done */
-#define C_CM_IOCTLM 0x04 /* RS-232 outputs change */
-#define C_CM_SENDXOFF 0x10 /* send Xoff */
-#define C_CM_SENDXON 0x11 /* send Xon */
-#define C_CM_CLFLOW 0x12 /* Clear flow control (resume) */
-#define C_CM_SENDBRK 0x41 /* send break */
-#define C_CM_INTBACK 0x42 /* Interrupt back */
-#define C_CM_SET_BREAK 0x43 /* Tx break on */
-#define C_CM_CLR_BREAK 0x44 /* Tx break off */
-#define C_CM_CMD_DONE 0x45 /* Previous command done */
-#define C_CM_INTBACK2 0x46 /* Alternate Interrupt back */
-#define C_CM_TINACT 0x51 /* set inactivity detection */
-#define C_CM_IRQ_ENBL 0x52 /* enable generation of interrupts */
-#define C_CM_IRQ_DSBL 0x53 /* disable generation of interrupts */
-#define C_CM_ACK_ENBL 0x54 /* enable acknowledged interrupt mode */
-#define C_CM_ACK_DSBL 0x55 /* disable acknowledged intr mode */
-#define C_CM_FLUSH_RX 0x56 /* flushes Rx buffer */
-#define C_CM_FLUSH_TX 0x57 /* flushes Tx buffer */
-#define C_CM_Q_ENABLE 0x58 /* enables queue access from the
- driver */
-#define C_CM_Q_DISABLE 0x59 /* disables queue access from the
- driver */
-
-#define C_CM_TXBEMPTY 0x60 /* Tx buffer is empty */
-#define C_CM_TXLOWWM 0x61 /* Tx buffer low water mark */
-#define C_CM_RXHIWM 0x62 /* Rx buffer high water mark */
-#define C_CM_RXNNDT 0x63 /* rx no new data timeout */
-#define C_CM_TXFEMPTY 0x64
-#define C_CM_ICHAR 0x65
-#define C_CM_MDCD 0x70 /* modem DCD change */
-#define C_CM_MDSR 0x71 /* modem DSR change */
-#define C_CM_MRI 0x72 /* modem RI change */
-#define C_CM_MCTS 0x73 /* modem CTS change */
-#define C_CM_MRTS 0x74 /* modem RTS drop */
-#define C_CM_RXBRK 0x84 /* Break received */
-#define C_CM_PR_ERROR 0x85 /* Parity error */
-#define C_CM_FR_ERROR 0x86 /* Frame error */
-#define C_CM_OVR_ERROR 0x87 /* Overrun error */
-#define C_CM_RXOFL 0x88 /* RX buffer overflow */
-#define C_CM_CMDERROR 0x90 /* command error */
-#define C_CM_FATAL 0x91 /* fatal error */
-#define C_CM_HW_RESET 0x92 /* reset board */
-
-/*
- * CH_CTRL - This per port structure contains all parameters
- * that control an specific port. It can be seen as the
- * configuration registers of a "super-serial-controller".
- */
-
-struct CH_CTRL {
- __u32 op_mode; /* operation mode */
- __u32 intr_enable; /* interrupt masking */
- __u32 sw_flow; /* SW flow control */
- __u32 flow_status; /* output flow status */
- __u32 comm_baud; /* baud rate - numerically specified */
- __u32 comm_parity; /* parity */
- __u32 comm_data_l; /* data length/stop */
- __u32 comm_flags; /* other flags */
- __u32 hw_flow; /* HW flow control */
- __u32 rs_control; /* RS-232 outputs */
- __u32 rs_status; /* RS-232 inputs */
- __u32 flow_xon; /* xon char */
- __u32 flow_xoff; /* xoff char */
- __u32 hw_overflow; /* hw overflow counter */
- __u32 sw_overflow; /* sw overflow counter */
- __u32 comm_error; /* frame/parity error counter */
- __u32 ichar;
- __u32 filler[7];
-};
-
-
-/*
- * BUF_CTRL - This per channel structure contains
- * all Tx and Rx buffer control for a given channel.
- */
-
-struct BUF_CTRL {
- __u32 flag_dma; /* buffers are in Host memory */
- __u32 tx_bufaddr; /* address of the tx buffer */
- __u32 tx_bufsize; /* tx buffer size */
- __u32 tx_threshold; /* tx low water mark */
- __u32 tx_get; /* tail index tx buf */
- __u32 tx_put; /* head index tx buf */
- __u32 rx_bufaddr; /* address of the rx buffer */
- __u32 rx_bufsize; /* rx buffer size */
- __u32 rx_threshold; /* rx high water mark */
- __u32 rx_get; /* tail index rx buf */
- __u32 rx_put; /* head index rx buf */
- __u32 filler[5]; /* filler to align structures */
-};
-
-/*
- * BOARD_CTRL - This per board structure contains all global
- * control fields related to the board.
- */
-
-struct BOARD_CTRL {
-
- /* static info provided by the on-board CPU */
- __u32 n_channel; /* number of channels */
- __u32 fw_version; /* firmware version */
-
- /* static info provided by the driver */
- __u32 op_system; /* op_system id */
- __u32 dr_version; /* driver version */
-
- /* board control area */
- __u32 inactivity; /* inactivity control */
-
- /* host to FW commands */
- __u32 hcmd_channel; /* channel number */
- __u32 hcmd_param; /* pointer to parameters */
-
- /* FW to Host commands */
- __u32 fwcmd_channel; /* channel number */
- __u32 fwcmd_param; /* pointer to parameters */
- __u32 zf_int_queue_addr; /* offset for INT_QUEUE structure */
-
- /* filler so the structures are aligned */
- __u32 filler[6];
-};
-
-/* Host Interrupt Queue */
-
-#define QUEUE_SIZE (10*MAX_CHAN)
-
-struct INT_QUEUE {
- unsigned char intr_code[QUEUE_SIZE];
- unsigned long channel[QUEUE_SIZE];
- unsigned long param[QUEUE_SIZE];
- unsigned long put;
- unsigned long get;
-};
-
-/*
- * ZFW_CTRL - This is the data structure that includes all other
- * data structures used by the Firmware.
- */
-
-struct ZFW_CTRL {
- struct BOARD_CTRL board_ctrl;
- struct CH_CTRL ch_ctrl[MAX_CHAN];
- struct BUF_CTRL buf_ctrl[MAX_CHAN];
-};
-
-/****************** ****************** *******************/
-#endif
-
-#endif /* _UAPI_LINUX_CYCLADES_H */
diff --git a/include/uapi/linux/major.h b/include/uapi/linux/major.h
index 7e5fa8e15c43..4e5f2b3a3d54 100644
--- a/include/uapi/linux/major.h
+++ b/include/uapi/linux/major.h
@@ -34,8 +34,6 @@
#define GOLDSTAR_CDROM_MAJOR 16
#define OPTICS_CDROM_MAJOR 17
#define SANYO_CDROM_MAJOR 18
-#define CYCLADES_MAJOR 19
-#define CYCLADESAUX_MAJOR 20
#define MITSUMI_X_CDROM_MAJOR 20
#define MFM_ACORN_MAJOR 21 /* ARM Linux /dev/mfm */
#define SCSI_GENERIC_MAJOR 21
diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h
index 93eb3c496ff1..fa6b16e5fdd8 100644
--- a/include/uapi/linux/serial.h
+++ b/include/uapi/linux/serial.h
@@ -52,11 +52,11 @@ struct serial_struct {
#define PORT_16450 2
#define PORT_16550 3
#define PORT_16550A 4
-#define PORT_CIRRUS 5 /* usurped by cyclades.c */
+#define PORT_CIRRUS 5
#define PORT_16650 6
#define PORT_16650V2 7
#define PORT_16750 8
-#define PORT_STARTECH 9 /* usurped by cyclades.c */
+#define PORT_STARTECH 9
#define PORT_16C950 10 /* Oxford Semiconductor */
#define PORT_16654 11
#define PORT_16850 12
diff --git a/include/uapi/linux/tty_flags.h b/include/uapi/linux/tty_flags.h
index 900a32e63424..cf25056d4b27 100644
--- a/include/uapi/linux/tty_flags.h
+++ b/include/uapi/linux/tty_flags.h
@@ -39,7 +39,7 @@
* WARNING: These flags are no longer used and have been superceded by the
* TTY_PORT_ flags in the iflags field (and not userspace-visible)
*/
-#ifndef _KERNEL_
+#ifndef __KERNEL__
#define ASYNCB_INITIALIZED 31 /* Serial port was initialized */
#define ASYNCB_SUSPENDED 30 /* Serial port is suspended */
#define ASYNCB_NORMAL_ACTIVE 29 /* Normal device is active */
@@ -73,15 +73,15 @@
#define ASYNC_MAGIC_MULTIPLIER (1U << ASYNCB_MAGIC_MULTIPLIER)
#define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1)
-#define ASYNC_DEPRECATED (ASYNC_SESSION_LOCKOUT | ASYNC_PGRP_LOCKOUT | \
- ASYNC_CALLOUT_NOHUP | ASYNC_AUTOPROBE)
+#define ASYNC_DEPRECATED (ASYNC_SPLIT_TERMIOS | ASYNC_SESSION_LOCKOUT | \
+ ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP | ASYNC_AUTOPROBE)
#define ASYNC_USR_MASK (ASYNC_SPD_MASK|ASYNC_CALLOUT_NOHUP| \
ASYNC_LOW_LATENCY)
#define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
#define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI)
#define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI)
-#ifndef _KERNEL_
+#ifndef __KERNEL__
/* These flags are no longer used (and were always masked from userspace) */
#define ASYNC_INITIALIZED (1U << ASYNCB_INITIALIZED)
#define ASYNC_NORMAL_ACTIVE (1U << ASYNCB_NORMAL_ACTIVE)
diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c
index 1204c438e87d..9958b37d8f9d 100644
--- a/net/nfc/nci/uart.c
+++ b/net/nfc/nci/uart.c
@@ -229,6 +229,72 @@ static void nci_uart_tty_wakeup(struct tty_struct *tty)
nci_uart_tx_wakeup(nu);
}
+/* -- Default recv_buf handler --
+ *
+ * This handler supposes that NCI frames are sent over UART link without any
+ * framing. It reads NCI header, retrieve the packet size and once all packet
+ * bytes are received it passes it to nci_uart driver for processing.
+ */
+static int nci_uart_default_recv_buf(struct nci_uart *nu, const u8 *data,
+ int count)
+{
+ int chunk_len;
+
+ if (!nu->ndev) {
+ nfc_err(nu->tty->dev,
+ "receive data from tty but no NCI dev is attached yet, drop buffer\n");
+ return 0;
+ }
+
+ /* Decode all incoming data in packets
+ * and enqueue then for processing.
+ */
+ while (count > 0) {
+ /* If this is the first data of a packet, allocate a buffer */
+ if (!nu->rx_skb) {
+ nu->rx_packet_len = -1;
+ nu->rx_skb = nci_skb_alloc(nu->ndev,
+ NCI_MAX_PACKET_SIZE,
+ GFP_ATOMIC);
+ if (!nu->rx_skb)
+ return -ENOMEM;
+ }
+
+ /* Eat byte after byte till full packet header is received */
+ if (nu->rx_skb->len < NCI_CTRL_HDR_SIZE) {
+ skb_put_u8(nu->rx_skb, *data++);
+ --count;
+ continue;
+ }
+
+ /* Header was received but packet len was not read */
+ if (nu->rx_packet_len < 0)
+ nu->rx_packet_len = NCI_CTRL_HDR_SIZE +
+ nci_plen(nu->rx_skb->data);
+
+ /* Compute how many bytes are missing and how many bytes can
+ * be consumed.
+ */
+ chunk_len = nu->rx_packet_len - nu->rx_skb->len;
+ if (count < chunk_len)
+ chunk_len = count;
+ skb_put_data(nu->rx_skb, data, chunk_len);
+ data += chunk_len;
+ count -= chunk_len;
+
+ /* Chcek if packet is fully received */
+ if (nu->rx_packet_len == nu->rx_skb->len) {
+ /* Pass RX packet to driver */
+ if (nu->ops.recv(nu, nu->rx_skb) != 0)
+ nfc_err(nu->tty->dev, "corrupted RX packet\n");
+ /* Next packet will be a new one */
+ nu->rx_skb = NULL;
+ }
+ }
+
+ return 0;
+}
+
/* nci_uart_tty_receive()
*
* Called by tty low level driver when receive data is
@@ -250,7 +316,7 @@ static void nci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
return;
spin_lock(&nu->rx_lock);
- nu->ops.recv_buf(nu, (void *)data, flags, count);
+ nci_uart_default_recv_buf(nu, data, count);
spin_unlock(&nu->rx_lock);
tty_unthrottle(tty);
@@ -321,78 +387,6 @@ static int nci_uart_send(struct nci_uart *nu, struct sk_buff *skb)
return 0;
}
-/* -- Default recv_buf handler --
- *
- * This handler supposes that NCI frames are sent over UART link without any
- * framing. It reads NCI header, retrieve the packet size and once all packet
- * bytes are received it passes it to nci_uart driver for processing.
- */
-static int nci_uart_default_recv_buf(struct nci_uart *nu, const u8 *data,
- char *flags, int count)
-{
- int chunk_len;
-
- if (!nu->ndev) {
- nfc_err(nu->tty->dev,
- "receive data from tty but no NCI dev is attached yet, drop buffer\n");
- return 0;
- }
-
- /* Decode all incoming data in packets
- * and enqueue then for processing.
- */
- while (count > 0) {
- /* If this is the first data of a packet, allocate a buffer */
- if (!nu->rx_skb) {
- nu->rx_packet_len = -1;
- nu->rx_skb = nci_skb_alloc(nu->ndev,
- NCI_MAX_PACKET_SIZE,
- GFP_ATOMIC);
- if (!nu->rx_skb)
- return -ENOMEM;
- }
-
- /* Eat byte after byte till full packet header is received */
- if (nu->rx_skb->len < NCI_CTRL_HDR_SIZE) {
- skb_put_u8(nu->rx_skb, *data++);
- --count;
- continue;
- }
-
- /* Header was received but packet len was not read */
- if (nu->rx_packet_len < 0)
- nu->rx_packet_len = NCI_CTRL_HDR_SIZE +
- nci_plen(nu->rx_skb->data);
-
- /* Compute how many bytes are missing and how many bytes can
- * be consumed.
- */
- chunk_len = nu->rx_packet_len - nu->rx_skb->len;
- if (count < chunk_len)
- chunk_len = count;
- skb_put_data(nu->rx_skb, data, chunk_len);
- data += chunk_len;
- count -= chunk_len;
-
- /* Chcek if packet is fully received */
- if (nu->rx_packet_len == nu->rx_skb->len) {
- /* Pass RX packet to driver */
- if (nu->ops.recv(nu, nu->rx_skb) != 0)
- nfc_err(nu->tty->dev, "corrupted RX packet\n");
- /* Next packet will be a new one */
- nu->rx_skb = NULL;
- }
- }
-
- return 0;
-}
-
-/* -- Default recv handler -- */
-static int nci_uart_default_recv(struct nci_uart *nu, struct sk_buff *skb)
-{
- return nci_recv_frame(nu->ndev, skb);
-}
-
int nci_uart_register(struct nci_uart *nu)
{
if (!nu || !nu->ops.open ||
@@ -402,12 +396,6 @@ int nci_uart_register(struct nci_uart *nu)
/* Set the send callback */
nu->ops.send = nci_uart_send;
- /* Install default handlers if not overridden */
- if (!nu->ops.recv_buf)
- nu->ops.recv_buf = nci_uart_default_recv_buf;
- if (!nu->ops.recv)
- nu->ops.recv = nci_uart_default_recv;
-
/* Add this driver in the driver list */
if (nci_uart_drivers[nu->driver]) {
pr_err("driver %d is already registered\n", nu->driver);
@@ -453,7 +441,6 @@ void nci_uart_set_config(struct nci_uart *nu, int baudrate, int flow_ctrl)
EXPORT_SYMBOL_GPL(nci_uart_set_config);
static struct tty_ldisc_ops nci_uart_ldisc = {
- .magic = TTY_LDISC_MAGIC,
.owner = THIS_MODULE,
.name = "n_nci",
.open = nci_uart_tty_open,
@@ -469,7 +456,6 @@ static struct tty_ldisc_ops nci_uart_ldisc = {
static int __init nci_uart_init(void)
{
- memset(nci_uart_drivers, 0, sizeof(nci_uart_drivers));
return tty_register_ldisc(N_NCI, &nci_uart_ldisc);
}
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 161be8b7d131..61dfa86d444d 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -285,7 +285,6 @@ static void v253_wakeup(struct tty_struct *tty)
}
struct tty_ldisc_ops v253_ops = {
- .magic = TTY_LDISC_MAGIC,
.name = "cx20442",
.owner = THIS_MODULE,
.open = v253_open,
diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c
index 57feb473a579..98198c7cc872 100644
--- a/sound/soc/ti/ams-delta.c
+++ b/sound/soc/ti/ams-delta.c
@@ -395,7 +395,6 @@ static void cx81801_wakeup(struct tty_struct *tty)
}
static struct tty_ldisc_ops cx81801_ops = {
- .magic = TTY_LDISC_MAGIC,
.name = "cx81801",
.owner = THIS_MODULE,
.open = cx81801_open,