aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLidza Louina <lidza.louina@gmail.com>2013-08-01 17:00:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-01 17:42:45 -0400
commit0b99d58902dd82fa51216eb8e0d6ddd8c43e90e4 (patch)
tree87f2935adbdabb707f21ebb32744687eb55ad99c
parentb9cc16c03dab5c43ad962b064f0b76a79a4bb5cb (diff)
staging: dgnc: add dgnc digi driver
This patch adds the DGNC driver. This is a TTY Serial Port Driver for the Digi International Neo and Classic PCI based product line by Digi International <http://www.digi.com>. This driver isn't hooked up to the build system because it doesn't build, it merely adds the driver written by Digi to the kernel tree so that it can be cleaned up and fixed up properly over time. Cc: Mark Hounschell <markh@compro.net> Signed-off-by: Lidza Louina <lidza.louina@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/dgnc/Kconfig6
-rw-r--r--drivers/staging/dgnc/Makefile7
-rw-r--r--drivers/staging/dgnc/Makefile.inc133
-rw-r--r--drivers/staging/dgnc/dgnc_cls.c1412
-rw-r--r--drivers/staging/dgnc/dgnc_cls.h90
-rw-r--r--drivers/staging/dgnc/dgnc_driver.c1028
-rw-r--r--drivers/staging/dgnc/dgnc_driver.h566
-rw-r--r--drivers/staging/dgnc/dgnc_kcompat.h91
-rw-r--r--drivers/staging/dgnc/dgnc_mgmt.c313
-rw-r--r--drivers/staging/dgnc/dgnc_mgmt.h37
-rw-r--r--drivers/staging/dgnc/dgnc_neo.c1977
-rw-r--r--drivers/staging/dgnc/dgnc_neo.h157
-rw-r--r--drivers/staging/dgnc/dgnc_pci.h77
-rw-r--r--drivers/staging/dgnc/dgnc_proc.c1551
-rw-r--r--drivers/staging/dgnc/dgnc_proc.h147
-rw-r--r--drivers/staging/dgnc/dgnc_sysfs.c761
-rw-r--r--drivers/staging/dgnc/dgnc_sysfs.h49
-rw-r--r--drivers/staging/dgnc/dgnc_trace.c187
-rw-r--r--drivers/staging/dgnc/dgnc_trace.h45
-rw-r--r--drivers/staging/dgnc/dgnc_tty.c3648
-rw-r--r--drivers/staging/dgnc/dgnc_tty.h42
-rw-r--r--drivers/staging/dgnc/dgnc_types.h36
-rw-r--r--drivers/staging/dgnc/digi.h419
-rw-r--r--drivers/staging/dgnc/dpacompat.h115
24 files changed, 12894 insertions, 0 deletions
diff --git a/drivers/staging/dgnc/Kconfig b/drivers/staging/dgnc/Kconfig
new file mode 100644
index 000000000000..23daaa5d520e
--- /dev/null
+++ b/drivers/staging/dgnc/Kconfig
@@ -0,0 +1,6 @@
1config DGNC
2 tristate "Digi Neo and Classic PCI Products"
3 default n
4 depends on TTY
5 ---help---
6 Driver for the Digi International Neo and Classic PCI based product line.
diff --git a/drivers/staging/dgnc/Makefile b/drivers/staging/dgnc/Makefile
new file mode 100644
index 000000000000..c4c96dc5a541
--- /dev/null
+++ b/drivers/staging/dgnc/Makefile
@@ -0,0 +1,7 @@
1EXTRA_CFLAGS += -DDG_NAME=\"dgnc-1.3-16\" -DDG_PART=\"40002369_F\"
2
3obj-$(CONFIG_DGNC) += dgnc.o
4
5dgnc-objs := dgnc_cls.o dgnc_driver.o\
6 dgnc_mgmt.o dgnc_neo.o\
7 dgnc_proc.o dgnc_trace.o dgnc_tty.o dgnc_sysfs.o
diff --git a/drivers/staging/dgnc/Makefile.inc b/drivers/staging/dgnc/Makefile.inc
new file mode 100644
index 000000000000..6ca38c731c39
--- /dev/null
+++ b/drivers/staging/dgnc/Makefile.inc
@@ -0,0 +1,133 @@
1#
2# From Makefile.inc
3#
4
5#
6# Common definitions go here.
7#
8
9#
10# TRUE_VERSION is the version string used in the driver build,
11# it is intended to be in the form:
12#
13# 2.0-0
14#
15# A string noting a particular special modification could be
16# used as well. This string will be reported when the driver
17# is loaded, and will be exposed by its /proc/dgnc/info
18# interface.
19#
20TRUE_VERSION="1.3-16"
21
22#
23# DGNC_PART_NUM is the part number string for the driver package.
24# It should be in the form:
25#
26# 40002369_A
27#
28DGNC_PART_NUM=40002369_F
29
30#
31# DGNC_REL_NOTE is the part number string for the driver release
32# notes. It should be in the form:
33#
34# 93000517_A
35#
36DGNC_REL_NOTE=93000517_F
37
38#
39# DGNC_PKG_VER is the "version" number string included in the
40# various documentation and packaging files. It should be
41# in the form:
42#
43# 1.0
44#
45DGNC_PKG_VER=1.3
46
47#
48# DGNC_PKG_REV is the "revision" of this version. Together,
49# a linux module revision is built with:
50#
51# ${DGNC_PKG_VER}-${DGNC_PKG_REV}
52#
53DGNC_PKG_REV=16
54
55#
56# DRP_PKG_DATE is the "date" string included in (for now) the
57# release notes. It should be in the form:
58#
59# 11/04/2003
60#
61DGNC_PKG_DATE=10/17/2008
62
63INIT_DIR= $(shell \
64 if [ -d /etc/rc.d/init.d ]; \
65 then echo "$(RPM_BUILD_ROOT)/etc/rc.d/init.d"; \
66 else echo "$(RPM_BUILD_ROOT)/etc/init.d"; fi)
67
68#
69# Miscelaneous path macro's
70#
71
72PACKAGE= dgnc
73DEVDIR= /dev/dg/$(PACKAGE)
74SRCDIR= /usr/src/dg/$(PACKAGE)
75BINDIR= /usr/bin
76DRVLIBDIR= /etc/$(PACKAGE)
77MANDIR= /usr/man
78USRLIBDIR= /usr/lib
79DGNCDIR= /etc/dgnc
80
81
82INIT_DIR= $(shell \
83 if [ -d /etc/rc.d/init.d ]; \
84 then echo "/etc/rc.d/init.d"; \
85 else echo "/etc/init.d"; fi)
86
87
88#
89# From Makefile
90#
91ifndef MYPWD
92MYPWD = $(shell pwd)
93endif
94
95ifeq ($(KERNDIR),)
96 KERNVERS := $(shell uname -r)
97 KERNDIR :=/lib/modules/${KERNVERS}/
98endif
99
100# Grab version and other important stuff
101
102RPMNAME := $(PACKAGE)-$(TRUE_VERSION)
103
104PARTNUM := $(DGNC_PART_NUM)
105
106RELNOTES := $(DGNC_REL_NOTE)
107
108MODDIR = $(shell echo $(BUILDROOT)/lib/modules/3.4.36-lcrs/misc)
109LSMOD = /sbin/lsmod
110RMMOD = /sbin/rmmod
111INSMOD = /sbin/insmod
112NEW_TTY_LOCKING = No
113NEW_TTY_BUFFERING = No
114REGISTER_TTYS_WITH_SYSFS = No
115
116# Send in some extra things...
117EXTRA_CFLAGS += -I${MYPWD} -I${MYPWD}/include -I${MYPWD}/../../commoninc\
118 -I${MYPWD}/../../dpa -DLINUX -DDG_NAME=\"$(RPMNAME)\"\
119 -DDG_PART=\"$(PARTNUM)\" -DDGNC_TRACER
120
121ifeq ($(NEW_TTY_LOCKING),Yes)
122 EXTRA_CFLAGS += -DNEW_TTY_LOCKING
123endif
124
125ifeq ($(NEW_TTY_BUFFERING),Yes)
126 EXTRA_CFLAGS += -DNEW_TTY_BUFFERING
127endif
128
129ifeq ($(REGISTER_TTYS_WITH_SYSFS),Yes)
130 EXTRA_CFLAGS += -DREGISTER_TTYS_WITH_SYSFS
131endif
132
133# Conform to correct kbuild conventions...
diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c
new file mode 100644
index 000000000000..83ded18e4ae2
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_cls.c
@@ -0,0 +1,1412 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 *
31 * $Id: dgnc_cls.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
32 */
33
34#include <linux/kernel.h>
35#include <linux/version.h>
36#include <linux/sched.h> /* For jiffies, task states */
37#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
38#include <linux/delay.h> /* For udelay */
39#include <asm/io.h> /* For read[bwl]/write[bwl] */
40#include <linux/serial.h> /* For struct async_serial */
41#include <linux/serial_reg.h> /* For the various UART offsets */
42#include <linux/pci.h>
43
44#include "dgnc_driver.h" /* Driver main header file */
45#include "dgnc_cls.h"
46#include "dgnc_tty.h"
47#include "dgnc_trace.h"
48
49static inline void cls_parse_isr(struct board_t *brd, uint port);
50static inline void cls_clear_break(struct channel_t *ch, int force);
51static inline void cls_set_cts_flow_control(struct channel_t *ch);
52static inline void cls_set_rts_flow_control(struct channel_t *ch);
53static inline void cls_set_ixon_flow_control(struct channel_t *ch);
54static inline void cls_set_ixoff_flow_control(struct channel_t *ch);
55static inline void cls_set_no_output_flow_control(struct channel_t *ch);
56static inline void cls_set_no_input_flow_control(struct channel_t *ch);
57static void cls_parse_modem(struct channel_t *ch, uchar signals);
58static void cls_tasklet(unsigned long data);
59static void cls_vpd(struct board_t *brd);
60static void cls_uart_init(struct channel_t *ch);
61static void cls_uart_off(struct channel_t *ch);
62static int cls_drain(struct tty_struct *tty, uint seconds);
63static void cls_param(struct tty_struct *tty);
64static void cls_assert_modem_signals(struct channel_t *ch);
65static void cls_flush_uart_write(struct channel_t *ch);
66static void cls_flush_uart_read(struct channel_t *ch);
67static void cls_disable_receiver(struct channel_t *ch);
68static void cls_enable_receiver(struct channel_t *ch);
69static void cls_send_break(struct channel_t *ch, int msecs);
70static void cls_send_start_character(struct channel_t *ch);
71static void cls_send_stop_character(struct channel_t *ch);
72static void cls_copy_data_from_uart_to_queue(struct channel_t *ch);
73static void cls_copy_data_from_queue_to_uart(struct channel_t *ch);
74static uint cls_get_uart_bytes_left(struct channel_t *ch);
75static void cls_send_immediate_char(struct channel_t *ch, unsigned char);
76static irqreturn_t cls_intr(int irq, void *voidbrd);
77
78struct board_ops dgnc_cls_ops = {
79 .tasklet = cls_tasklet,
80 .intr = cls_intr,
81 .uart_init = cls_uart_init,
82 .uart_off = cls_uart_off,
83 .drain = cls_drain,
84 .param = cls_param,
85 .vpd = cls_vpd,
86 .assert_modem_signals = cls_assert_modem_signals,
87 .flush_uart_write = cls_flush_uart_write,
88 .flush_uart_read = cls_flush_uart_read,
89 .disable_receiver = cls_disable_receiver,
90 .enable_receiver = cls_enable_receiver,
91 .send_break = cls_send_break,
92 .send_start_character = cls_send_start_character,
93 .send_stop_character = cls_send_stop_character,
94 .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart,
95 .get_uart_bytes_left = cls_get_uart_bytes_left,
96 .send_immediate_char = cls_send_immediate_char
97};
98
99
100static inline void cls_set_cts_flow_control(struct channel_t *ch)
101{
102 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
103 uchar ier = readb(&ch->ch_cls_uart->ier);
104 uchar isr_fcr = 0;
105
106 DPR_PARAM(("Setting CTSFLOW\n"));
107
108 /*
109 * The Enhanced Register Set may only be accessed when
110 * the Line Control Register is set to 0xBFh.
111 */
112 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
113
114 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
115
116 /* Turn on CTS flow control, turn off IXON flow control */
117 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_CTSDSR);
118 isr_fcr &= ~(UART_EXAR654_EFR_IXON);
119
120 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
121
122 /* Write old LCR value back out, which turns enhanced access off */
123 writeb(lcrb, &ch->ch_cls_uart->lcr);
124
125 /* Enable interrupts for CTS flow, turn off interrupts for received XOFF chars */
126 ier |= (UART_EXAR654_IER_CTSDSR);
127 ier &= ~(UART_EXAR654_IER_XOFF);
128 writeb(ier, &ch->ch_cls_uart->ier);
129
130 /* Set the usual FIFO values */
131 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
132
133 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
134 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
135 &ch->ch_cls_uart->isr_fcr);
136
137 ch->ch_t_tlevel = 16;
138
139}
140
141
142static inline void cls_set_ixon_flow_control(struct channel_t *ch)
143{
144 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
145 uchar ier = readb(&ch->ch_cls_uart->ier);
146 uchar isr_fcr = 0;
147
148 DPR_PARAM(("Setting IXON FLOW\n"));
149
150 /*
151 * The Enhanced Register Set may only be accessed when
152 * the Line Control Register is set to 0xBFh.
153 */
154 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
155
156 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
157
158 /* Turn on IXON flow control, turn off CTS flow control */
159 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXON);
160 isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR);
161
162 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
163
164 /* Now set our current start/stop chars while in enhanced mode */
165 writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
166 writeb(0, &ch->ch_cls_uart->lsr);
167 writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
168 writeb(0, &ch->ch_cls_uart->spr);
169
170 /* Write old LCR value back out, which turns enhanced access off */
171 writeb(lcrb, &ch->ch_cls_uart->lcr);
172
173 /* Disable interrupts for CTS flow, turn on interrupts for received XOFF chars */
174 ier &= ~(UART_EXAR654_IER_CTSDSR);
175 ier |= (UART_EXAR654_IER_XOFF);
176 writeb(ier, &ch->ch_cls_uart->ier);
177
178 /* Set the usual FIFO values */
179 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
180
181 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
182 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
183 &ch->ch_cls_uart->isr_fcr);
184
185}
186
187
188static inline void cls_set_no_output_flow_control(struct channel_t *ch)
189{
190 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
191 uchar ier = readb(&ch->ch_cls_uart->ier);
192 uchar isr_fcr = 0;
193
194 DPR_PARAM(("Unsetting Output FLOW\n"));
195
196 /*
197 * The Enhanced Register Set may only be accessed when
198 * the Line Control Register is set to 0xBFh.
199 */
200 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
201
202 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
203
204 /* Turn off IXON flow control, turn off CTS flow control */
205 isr_fcr |= (UART_EXAR654_EFR_ECB);
206 isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR | UART_EXAR654_EFR_IXON);
207
208 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
209
210 /* Write old LCR value back out, which turns enhanced access off */
211 writeb(lcrb, &ch->ch_cls_uart->lcr);
212
213 /* Disable interrupts for CTS flow, turn off interrupts for received XOFF chars */
214 ier &= ~(UART_EXAR654_IER_CTSDSR);
215 ier &= ~(UART_EXAR654_IER_XOFF);
216 writeb(ier, &ch->ch_cls_uart->ier);
217
218 /* Set the usual FIFO values */
219 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
220
221 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
222 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
223 &ch->ch_cls_uart->isr_fcr);
224
225 ch->ch_r_watermark = 0;
226 ch->ch_t_tlevel = 16;
227 ch->ch_r_tlevel = 16;
228
229}
230
231
232static inline void cls_set_rts_flow_control(struct channel_t *ch)
233{
234 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
235 uchar ier = readb(&ch->ch_cls_uart->ier);
236 uchar isr_fcr = 0;
237
238 DPR_PARAM(("Setting RTSFLOW\n"));
239
240 /*
241 * The Enhanced Register Set may only be accessed when
242 * the Line Control Register is set to 0xBFh.
243 */
244 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
245
246 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
247
248 /* Turn on RTS flow control, turn off IXOFF flow control */
249 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_RTSDTR);
250 isr_fcr &= ~(UART_EXAR654_EFR_IXOFF);
251
252 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
253
254 /* Write old LCR value back out, which turns enhanced access off */
255 writeb(lcrb, &ch->ch_cls_uart->lcr);
256
257 /* Enable interrupts for RTS flow */
258 ier |= (UART_EXAR654_IER_RTSDTR);
259 writeb(ier, &ch->ch_cls_uart->ier);
260
261 /* Set the usual FIFO values */
262 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
263
264 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 |
265 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
266 &ch->ch_cls_uart->isr_fcr);
267
268
269 ch->ch_r_watermark = 4;
270 ch->ch_r_tlevel = 8;
271
272}
273
274
275static inline void cls_set_ixoff_flow_control(struct channel_t *ch)
276{
277 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
278 uchar ier = readb(&ch->ch_cls_uart->ier);
279 uchar isr_fcr = 0;
280
281 DPR_PARAM(("Setting IXOFF FLOW\n"));
282
283 /*
284 * The Enhanced Register Set may only be accessed when
285 * the Line Control Register is set to 0xBFh.
286 */
287 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
288
289 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
290
291 /* Turn on IXOFF flow control, turn off RTS flow control */
292 isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXOFF);
293 isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR);
294
295 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
296
297 /* Now set our current start/stop chars while in enhanced mode */
298 writeb(ch->ch_startc, &ch->ch_cls_uart->mcr);
299 writeb(0, &ch->ch_cls_uart->lsr);
300 writeb(ch->ch_stopc, &ch->ch_cls_uart->msr);
301 writeb(0, &ch->ch_cls_uart->spr);
302
303 /* Write old LCR value back out, which turns enhanced access off */
304 writeb(lcrb, &ch->ch_cls_uart->lcr);
305
306 /* Disable interrupts for RTS flow */
307 ier &= ~(UART_EXAR654_IER_RTSDTR);
308 writeb(ier, &ch->ch_cls_uart->ier);
309
310 /* Set the usual FIFO values */
311 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
312
313 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
314 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
315 &ch->ch_cls_uart->isr_fcr);
316
317}
318
319
320static inline void cls_set_no_input_flow_control(struct channel_t *ch)
321{
322 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
323 uchar ier = readb(&ch->ch_cls_uart->ier);
324 uchar isr_fcr = 0;
325
326 DPR_PARAM(("Unsetting Input FLOW\n"));
327
328 /*
329 * The Enhanced Register Set may only be accessed when
330 * the Line Control Register is set to 0xBFh.
331 */
332 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
333
334 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
335
336 /* Turn off IXOFF flow control, turn off RTS flow control */
337 isr_fcr |= (UART_EXAR654_EFR_ECB);
338 isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR | UART_EXAR654_EFR_IXOFF);
339
340 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
341
342 /* Write old LCR value back out, which turns enhanced access off */
343 writeb(lcrb, &ch->ch_cls_uart->lcr);
344
345 /* Disable interrupts for RTS flow */
346 ier &= ~(UART_EXAR654_IER_RTSDTR);
347 writeb(ier, &ch->ch_cls_uart->ier);
348
349 /* Set the usual FIFO values */
350 writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr);
351
352 writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 |
353 UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR),
354 &ch->ch_cls_uart->isr_fcr);
355
356 ch->ch_t_tlevel = 16;
357 ch->ch_r_tlevel = 16;
358
359}
360
361
362/*
363 * cls_clear_break.
364 * Determines whether its time to shut off break condition.
365 *
366 * No locks are assumed to be held when calling this function.
367 * channel lock is held and released in this function.
368 */
369static inline void cls_clear_break(struct channel_t *ch, int force)
370{
371 ulong lock_flags;
372
373 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
374 return;
375
376 DGNC_LOCK(ch->ch_lock, lock_flags);
377
378 /* Bail if we aren't currently sending a break. */
379 if (!ch->ch_stop_sending_break) {
380 DGNC_UNLOCK(ch->ch_lock, lock_flags);
381 return;
382 }
383
384 /* Turn break off, and unset some variables */
385 if (ch->ch_flags & CH_BREAK_SENDING) {
386 if ((jiffies >= ch->ch_stop_sending_break) || force) {
387 uchar temp = readb(&ch->ch_cls_uart->lcr);
388 writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);
389 ch->ch_flags &= ~(CH_BREAK_SENDING);
390 ch->ch_stop_sending_break = 0;
391 DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
392 }
393 }
394 DGNC_UNLOCK(ch->ch_lock, lock_flags);
395}
396
397
398/* Parse the ISR register for the specific port */
399static inline void cls_parse_isr(struct board_t *brd, uint port)
400{
401 struct channel_t *ch;
402 uchar isr = 0;
403 ulong lock_flags;
404
405 /*
406 * No need to verify board pointer, it was already
407 * verified in the interrupt routine.
408 */
409
410 if (port > brd->nasync)
411 return;
412
413 ch = brd->channels[port];
414 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
415 return;
416
417 /* Here we try to figure out what caused the interrupt to happen */
418 while (1) {
419
420 isr = readb(&ch->ch_cls_uart->isr_fcr);
421
422 /* Bail if no pending interrupt on port */
423 if (isr & UART_IIR_NO_INT) {
424 break;
425 }
426
427 DPR_INTR(("%s:%d port: %x isr: %x\n", __FILE__, __LINE__, port, isr));
428
429 /* Receive Interrupt pending */
430 if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) {
431 /* Read data from uart -> queue */
432 brd->intr_rx++;
433 ch->ch_intr_rx++;
434 cls_copy_data_from_uart_to_queue(ch);
435 dgnc_check_queue_flow_control(ch);
436 }
437
438 /* Transmit Hold register empty pending */
439 if (isr & UART_IIR_THRI) {
440 /* Transfer data (if any) from Write Queue -> UART. */
441 DGNC_LOCK(ch->ch_lock, lock_flags);
442 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
443 brd->intr_tx++;
444 ch->ch_intr_tx++;
445 DGNC_UNLOCK(ch->ch_lock, lock_flags);
446 cls_copy_data_from_queue_to_uart(ch);
447 }
448
449 /* Received Xoff signal/Special character */
450 if (isr & UART_IIR_XOFF) {
451 /* Empty */
452 }
453
454 /* CTS/RTS change of state */
455 if (isr & UART_IIR_CTSRTS) {
456 brd->intr_modem++;
457 ch->ch_intr_modem++;
458 /*
459 * Don't need to do anything, the cls_parse_modem
460 * below will grab the updated modem signals.
461 */
462 }
463
464 /* Parse any modem signal changes */
465 DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n"));
466 cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
467 }
468}
469
470
471/*
472 * cls_param()
473 * Send any/all changes to the line to the UART.
474 */
475static void cls_param(struct tty_struct *tty)
476{
477 uchar lcr = 0;
478 uchar uart_lcr = 0;
479 uchar ier = 0;
480 uchar uart_ier = 0;
481 uint baud = 9600;
482 int quot = 0;
483 struct board_t *bd;
484 struct channel_t *ch;
485 struct un_t *un;
486
487 if (!tty || tty->magic != TTY_MAGIC) {
488 return;
489 }
490
491 un = (struct un_t *) tty->driver_data;
492 if (!un || un->magic != DGNC_UNIT_MAGIC) {
493 return;
494 }
495
496 ch = un->un_ch;
497 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
498 return;
499 }
500
501 bd = ch->ch_bd;
502 if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
503 return;
504 }
505
506 DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
507 ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
508
509 /*
510 * If baud rate is zero, flush queues, and set mval to drop DTR.
511 */
512 if ((ch->ch_c_cflag & (CBAUD)) == 0) {
513 ch->ch_r_head = ch->ch_r_tail = 0;
514 ch->ch_e_head = ch->ch_e_tail = 0;
515 ch->ch_w_head = ch->ch_w_tail = 0;
516
517 cls_flush_uart_write(ch);
518 cls_flush_uart_read(ch);
519
520 /* The baudrate is B0 so all modem lines are to be dropped. */
521 ch->ch_flags |= (CH_BAUD0);
522 ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
523 cls_assert_modem_signals(ch);
524 ch->ch_old_baud = 0;
525 return;
526 } else if (ch->ch_custom_speed) {
527
528 baud = ch->ch_custom_speed;
529 /* Handle transition from B0 */
530 if (ch->ch_flags & CH_BAUD0) {
531 ch->ch_flags &= ~(CH_BAUD0);
532
533 /*
534 * Bring back up RTS and DTR...
535 * Also handle RTS or DTR toggle if set.
536 */
537 if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
538 ch->ch_mostat |= (UART_MCR_RTS);
539 if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
540 ch->ch_mostat |= (UART_MCR_DTR);
541 }
542
543 } else {
544 int iindex = 0;
545 int jindex = 0;
546
547 ulong bauds[4][16] = {
548 { /* slowbaud */
549 0, 50, 75, 110,
550 134, 150, 200, 300,
551 600, 1200, 1800, 2400,
552 4800, 9600, 19200, 38400 },
553 { /* slowbaud & CBAUDEX */
554 0, 57600, 115200, 230400,
555 460800, 150, 200, 921600,
556 600, 1200, 1800, 2400,
557 4800, 9600, 19200, 38400 },
558 { /* fastbaud */
559 0, 57600, 76800, 115200,
560 131657, 153600, 230400, 460800,
561 921600, 1200, 1800, 2400,
562 4800, 9600, 19200, 38400 },
563 { /* fastbaud & CBAUDEX */
564 0, 57600, 115200, 230400,
565 460800, 150, 200, 921600,
566 600, 1200, 1800, 2400,
567 4800, 9600, 19200, 38400 }
568 };
569
570 /* Only use the TXPrint baud rate if the terminal unit is NOT open */
571 if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT))
572 baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
573 else
574 baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
575
576 if (ch->ch_c_cflag & CBAUDEX)
577 iindex = 1;
578
579 if (ch->ch_digi.digi_flags & DIGI_FAST)
580 iindex += 2;
581
582 jindex = baud;
583
584 if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
585 baud = bauds[iindex][jindex];
586 } else {
587 DPR_IOCTL(("baud indices were out of range (%d)(%d)",
588 iindex, jindex));
589 baud = 0;
590 }
591
592 if (baud == 0)
593 baud = 9600;
594
595 /* Handle transition from B0 */
596 if (ch->ch_flags & CH_BAUD0) {
597 ch->ch_flags &= ~(CH_BAUD0);
598
599 /*
600 * Bring back up RTS and DTR...
601 * Also handle RTS or DTR toggle if set.
602 */
603 if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
604 ch->ch_mostat |= (UART_MCR_RTS);
605 if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
606 ch->ch_mostat |= (UART_MCR_DTR);
607 }
608 }
609
610 if (ch->ch_c_cflag & PARENB) {
611 lcr |= UART_LCR_PARITY;
612 }
613
614 if (!(ch->ch_c_cflag & PARODD)) {
615 lcr |= UART_LCR_EPAR;
616 }
617
618 /*
619 * Not all platforms support mark/space parity,
620 * so this will hide behind an ifdef.
621 */
622#ifdef CMSPAR
623 if (ch->ch_c_cflag & CMSPAR)
624 lcr |= UART_LCR_SPAR;
625#endif
626
627 if (ch->ch_c_cflag & CSTOPB)
628 lcr |= UART_LCR_STOP;
629
630 switch (ch->ch_c_cflag & CSIZE) {
631 case CS5:
632 lcr |= UART_LCR_WLEN5;
633 break;
634 case CS6:
635 lcr |= UART_LCR_WLEN6;
636 break;
637 case CS7:
638 lcr |= UART_LCR_WLEN7;
639 break;
640 case CS8:
641 default:
642 lcr |= UART_LCR_WLEN8;
643 break;
644 }
645
646 ier = uart_ier = readb(&ch->ch_cls_uart->ier);
647 uart_lcr = readb(&ch->ch_cls_uart->lcr);
648
649 if (baud == 0)
650 baud = 9600;
651
652 quot = ch->ch_bd->bd_dividend / baud;
653
654 if (quot != 0 && ch->ch_old_baud != baud) {
655 ch->ch_old_baud = baud;
656 writeb(UART_LCR_DLAB, &ch->ch_cls_uart->lcr);
657 writeb((quot & 0xff), &ch->ch_cls_uart->txrx);
658 writeb((quot >> 8), &ch->ch_cls_uart->ier);
659 writeb(lcr, &ch->ch_cls_uart->lcr);
660 }
661
662 if (uart_lcr != lcr)
663 writeb(lcr, &ch->ch_cls_uart->lcr);
664
665 if (ch->ch_c_cflag & CREAD) {
666 ier |= (UART_IER_RDI | UART_IER_RLSI);
667 }
668 else {
669 ier &= ~(UART_IER_RDI | UART_IER_RLSI);
670 }
671
672 /*
673 * Have the UART interrupt on modem signal changes ONLY when
674 * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set.
675 */
676 if ((ch->ch_digi.digi_flags & CTSPACE) || (ch->ch_digi.digi_flags & RTSPACE) ||
677 (ch->ch_c_cflag & CRTSCTS) || !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
678 !(ch->ch_c_cflag & CLOCAL))
679 {
680 ier |= UART_IER_MSI;
681 }
682 else {
683 ier &= ~UART_IER_MSI;
684 }
685
686 ier |= UART_IER_THRI;
687
688 if (ier != uart_ier)
689 writeb(ier, &ch->ch_cls_uart->ier);
690
691 if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
692 cls_set_cts_flow_control(ch);
693 }
694 else if (ch->ch_c_iflag & IXON) {
695 /* If start/stop is set to disable, then we should disable flow control */
696 if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
697 cls_set_no_output_flow_control(ch);
698 else
699 cls_set_ixon_flow_control(ch);
700 }
701 else {
702 cls_set_no_output_flow_control(ch);
703 }
704
705 if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
706 cls_set_rts_flow_control(ch);
707 }
708 else if (ch->ch_c_iflag & IXOFF) {
709 /* If start/stop is set to disable, then we should disable flow control */
710 if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
711 cls_set_no_input_flow_control(ch);
712 else
713 cls_set_ixoff_flow_control(ch);
714 }
715 else {
716 cls_set_no_input_flow_control(ch);
717 }
718
719 cls_assert_modem_signals(ch);
720
721 /* Get current status of the modem signals now */
722 cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr));
723}
724
725
726/*
727 * Our board poller function.
728 */
729static void cls_tasklet(unsigned long data)
730{
731 struct board_t *bd = (struct board_t *) data;
732 struct channel_t *ch;
733 ulong lock_flags;
734 int i;
735 int state = 0;
736 int ports = 0;
737
738 if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
739 APR(("poll_tasklet() - NULL or bad bd.\n"));
740 return;
741 }
742
743 /* Cache a couple board values */
744 DGNC_LOCK(bd->bd_lock, lock_flags);
745 state = bd->state;
746 ports = bd->nasync;
747 DGNC_UNLOCK(bd->bd_lock, lock_flags);
748
749 /*
750 * Do NOT allow the interrupt routine to read the intr registers
751 * Until we release this lock.
752 */
753 DGNC_LOCK(bd->bd_intr_lock, lock_flags);
754
755 /*
756 * If board is ready, parse deeper to see if there is anything to do.
757 */
758 if ((state == BOARD_READY) && (ports > 0)) {
759
760 /* Loop on each port */
761 for (i = 0; i < ports; i++) {
762 ch = bd->channels[i];
763 if (!ch)
764 continue;
765
766 /*
767 * NOTE: Remember you CANNOT hold any channel
768 * locks when calling input.
769 * During input processing, its possible we
770 * will call ld, which might do callbacks back
771 * into us.
772 */
773 dgnc_input(ch);
774
775 /*
776 * Channel lock is grabbed and then released
777 * inside this routine.
778 */
779 cls_copy_data_from_queue_to_uart(ch);
780 dgnc_wakeup_writes(ch);
781
782 /*
783 * Check carrier function.
784 */
785 dgnc_carrier(ch);
786
787 /*
788 * The timing check of turning off the break is done
789 * inside clear_break()
790 */
791 if (ch->ch_stop_sending_break)
792 cls_clear_break(ch, 0);
793 }
794 }
795
796 DGNC_UNLOCK(bd->bd_intr_lock, lock_flags);
797
798}
799
800
801/*
802 * cls_intr()
803 *
804 * Classic specific interrupt handler.
805 */
806static irqreturn_t cls_intr(int irq, void *voidbrd)
807{
808 struct board_t *brd = (struct board_t *) voidbrd;
809 uint i = 0;
810 uchar poll_reg;
811 unsigned long lock_flags;
812
813 if (!brd) {
814 APR(("Received interrupt (%d) with null board associated\n", irq));
815 return IRQ_NONE;
816 }
817
818 /*
819 * Check to make sure its for us.
820 */
821 if (brd->magic != DGNC_BOARD_MAGIC) {
822 APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
823 return IRQ_NONE;
824 }
825
826 DGNC_LOCK(brd->bd_intr_lock, lock_flags);
827
828 brd->intr_count++;
829
830 /*
831 * Check the board's global interrupt offset to see if we
832 * we actually do have an interrupt pending for us.
833 */
834 poll_reg = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET);
835
836 /* If 0, no interrupts pending */
837 if (!poll_reg) {
838 DPR_INTR(("Kernel interrupted to me, but no pending interrupts...\n"));
839 DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
840 return IRQ_NONE;
841 }
842
843 DPR_INTR(("%s:%d poll_reg: %x\n", __FILE__, __LINE__, poll_reg));
844
845 /* Parse each port to find out what caused the interrupt */
846 for (i = 0; i < brd->nasync; i++) {
847 cls_parse_isr(brd, i);
848 }
849
850 /*
851 * Schedule tasklet to more in-depth servicing at a better time.
852 */
853 tasklet_schedule(&brd->helper_tasklet);
854
855 DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
856
857 DPR_INTR(("dgnc_intr finish.\n"));
858 return IRQ_HANDLED;
859}
860
861
862static void cls_disable_receiver(struct channel_t *ch)
863{
864 uchar tmp = readb(&ch->ch_cls_uart->ier);
865 tmp &= ~(UART_IER_RDI);
866 writeb(tmp, &ch->ch_cls_uart->ier);
867}
868
869
870static void cls_enable_receiver(struct channel_t *ch)
871{
872 uchar tmp = readb(&ch->ch_cls_uart->ier);
873 tmp |= (UART_IER_RDI);
874 writeb(tmp, &ch->ch_cls_uart->ier);
875}
876
877
878static void cls_copy_data_from_uart_to_queue(struct channel_t *ch)
879{
880 int qleft = 0;
881 uchar linestatus = 0;
882 uchar error_mask = 0;
883 ushort head;
884 ushort tail;
885 ulong lock_flags;
886
887 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
888 return;
889
890 DGNC_LOCK(ch->ch_lock, lock_flags);
891
892 /* cache head and tail of queue */
893 head = ch->ch_r_head;
894 tail = ch->ch_r_tail;
895
896 /* Store how much space we have left in the queue */
897 if ((qleft = tail - head - 1) < 0)
898 qleft += RQUEUEMASK + 1;
899
900 /*
901 * Create a mask to determine whether we should
902 * insert the character (if any) into our queue.
903 */
904 if (ch->ch_c_iflag & IGNBRK)
905 error_mask |= UART_LSR_BI;
906
907 while (1) {
908 linestatus = readb(&ch->ch_cls_uart->lsr);
909
910 if (!(linestatus & (UART_LSR_DR)))
911 break;
912
913 /*
914 * Discard character if we are ignoring the error mask.
915 */
916 if (linestatus & error_mask) {
917 uchar discard;
918 linestatus = 0;
919 discard = readb(&ch->ch_cls_uart->txrx);
920 continue;
921 }
922
923 /*
924 * If our queue is full, we have no choice but to drop some data.
925 * The assumption is that HWFLOW or SWFLOW should have stopped
926 * things way way before we got to this point.
927 *
928 * I decided that I wanted to ditch the oldest data first,
929 * I hope thats okay with everyone? Yes? Good.
930 */
931 while (qleft < 1) {
932 DPR_READ(("Queue full, dropping DATA:%x LSR:%x\n",
933 ch->ch_rqueue[tail], ch->ch_equeue[tail]));
934
935 ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
936 ch->ch_err_overrun++;
937 qleft++;
938 }
939
940 ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE);
941 ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx);
942 dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, 1);
943
944 qleft--;
945
946 DPR_READ(("DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]));
947
948 if (ch->ch_equeue[head] & UART_LSR_PE)
949 ch->ch_err_parity++;
950 if (ch->ch_equeue[head] & UART_LSR_BI)
951 ch->ch_err_break++;
952 if (ch->ch_equeue[head] & UART_LSR_FE)
953 ch->ch_err_frame++;
954
955 /* Add to, and flip head if needed */
956 head = (head + 1) & RQUEUEMASK;
957 ch->ch_rxcount++;
958 }
959
960 /*
961 * Write new final heads to channel structure.
962 */
963 ch->ch_r_head = head & RQUEUEMASK;
964 ch->ch_e_head = head & EQUEUEMASK;
965
966 DGNC_UNLOCK(ch->ch_lock, lock_flags);
967}
968
969
970/*
971 * This function basically goes to sleep for secs, or until
972 * it gets signalled that the port has fully drained.
973 */
974static int cls_drain(struct tty_struct *tty, uint seconds)
975{
976 ulong lock_flags;
977 struct channel_t *ch;
978 struct un_t *un;
979 int rc = 0;
980
981 if (!tty || tty->magic != TTY_MAGIC) {
982 return (-ENXIO);
983 }
984
985 un = (struct un_t *) tty->driver_data;
986 if (!un || un->magic != DGNC_UNIT_MAGIC) {
987 return (-ENXIO);
988 }
989
990 ch = un->un_ch;
991 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
992 return (-ENXIO);
993 }
994
995 DGNC_LOCK(ch->ch_lock, lock_flags);
996 un->un_flags |= UN_EMPTY;
997 DGNC_UNLOCK(ch->ch_lock, lock_flags);
998
999 /*
1000 * NOTE: Do something with time passed in.
1001 */
1002 rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
1003
1004 /* If ret is non-zero, user ctrl-c'ed us */
1005 if (rc)
1006 DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__));
1007
1008 return (rc);
1009}
1010
1011
1012/* Channel lock MUST be held before calling this function! */
1013static void cls_flush_uart_write(struct channel_t *ch)
1014{
1015 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
1016 return;
1017 }
1018
1019 writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr);
1020 udelay(10);
1021
1022 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1023}
1024
1025
1026/* Channel lock MUST be held before calling this function! */
1027static void cls_flush_uart_read(struct channel_t *ch)
1028{
1029 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
1030 return;
1031 }
1032
1033 /*
1034 * For complete POSIX compatibility, we should be purging the
1035 * read FIFO in the UART here.
1036 *
1037 * However, doing the statement below also incorrectly flushes
1038 * write data as well as just basically trashing the FIFO.
1039 *
1040 * I believe this is a BUG in this UART.
1041 * So for now, we will leave the code #ifdef'ed out...
1042 */
1043#if 0
1044 writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_cls_uart->isr_fcr);
1045#endif
1046 udelay(10);
1047}
1048
1049
1050static void cls_copy_data_from_queue_to_uart(struct channel_t *ch)
1051{
1052 ushort head;
1053 ushort tail;
1054 int n;
1055 int qlen;
1056 uint len_written = 0;
1057 ulong lock_flags;
1058
1059 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1060 return;
1061
1062 DGNC_LOCK(ch->ch_lock, lock_flags);
1063
1064 /* No data to write to the UART */
1065 if (ch->ch_w_tail == ch->ch_w_head) {
1066 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1067 return;
1068 }
1069
1070 /* If port is "stopped", don't send any data to the UART */
1071 if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) {
1072 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1073 return;
1074 }
1075
1076 if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) {
1077 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1078 return;
1079 }
1080
1081 n = 32;
1082
1083 /* cache head and tail of queue */
1084 head = ch->ch_w_head & WQUEUEMASK;
1085 tail = ch->ch_w_tail & WQUEUEMASK;
1086 qlen = (head - tail) & WQUEUEMASK;
1087
1088 /* Find minimum of the FIFO space, versus queue length */
1089 n = min(n, qlen);
1090
1091 while (n > 0) {
1092
1093 /*
1094 * If RTS Toggle mode is on, turn on RTS now if not already set,
1095 * and make sure we get an event when the data transfer has completed.
1096 */
1097 if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
1098 if (!(ch->ch_mostat & UART_MCR_RTS)) {
1099 ch->ch_mostat |= (UART_MCR_RTS);
1100 cls_assert_modem_signals(ch);
1101 }
1102 ch->ch_tun.un_flags |= (UN_EMPTY);
1103 }
1104
1105 /*
1106 * If DTR Toggle mode is on, turn on DTR now if not already set,
1107 * and make sure we get an event when the data transfer has completed.
1108 */
1109 if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
1110 if (!(ch->ch_mostat & UART_MCR_DTR)) {
1111 ch->ch_mostat |= (UART_MCR_DTR);
1112 cls_assert_modem_signals(ch);
1113 }
1114 ch->ch_tun.un_flags |= (UN_EMPTY);
1115 }
1116 writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx);
1117 dgnc_sniff_nowait_nolock(ch, "UART WRITE", ch->ch_wqueue + ch->ch_w_tail, 1);
1118 DPR_WRITE(("Tx data: %x\n", ch->ch_wqueue[ch->ch_w_tail]));
1119 ch->ch_w_tail++;
1120 ch->ch_w_tail &= WQUEUEMASK;
1121 ch->ch_txcount++;
1122 len_written++;
1123 n--;
1124 }
1125
1126 if (len_written > 0)
1127 ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1128
1129 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1130
1131 return;
1132}
1133
1134
1135static void cls_parse_modem(struct channel_t *ch, uchar signals)
1136{
1137 volatile uchar msignals = signals;
1138
1139 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1140 return;
1141
1142 DPR_MSIGS(("cls_parse_modem: port: %d signals: %d\n", ch->ch_portnum, msignals));
1143
1144 /*
1145 * Do altpin switching. Altpin switches DCD and DSR.
1146 * This prolly breaks DSRPACE, so we should be more clever here.
1147 */
1148 if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
1149 uchar mswap = signals;
1150 if (mswap & UART_MSR_DDCD) {
1151 msignals &= ~UART_MSR_DDCD;
1152 msignals |= UART_MSR_DDSR;
1153 }
1154 if (mswap & UART_MSR_DDSR) {
1155 msignals &= ~UART_MSR_DDSR;
1156 msignals |= UART_MSR_DDCD;
1157 }
1158 if (mswap & UART_MSR_DCD) {
1159 msignals &= ~UART_MSR_DCD;
1160 msignals |= UART_MSR_DSR;
1161 }
1162 if (mswap & UART_MSR_DSR) {
1163 msignals &= ~UART_MSR_DSR;
1164 msignals |= UART_MSR_DCD;
1165 }
1166 }
1167
1168 /* Scrub off lower bits. They signify delta's, which I don't care about */
1169 signals &= 0xf0;
1170
1171 if (msignals & UART_MSR_DCD)
1172 ch->ch_mistat |= UART_MSR_DCD;
1173 else
1174 ch->ch_mistat &= ~UART_MSR_DCD;
1175
1176 if (msignals & UART_MSR_DSR)
1177 ch->ch_mistat |= UART_MSR_DSR;
1178 else
1179 ch->ch_mistat &= ~UART_MSR_DSR;
1180
1181 if (msignals & UART_MSR_RI)
1182 ch->ch_mistat |= UART_MSR_RI;
1183 else
1184 ch->ch_mistat &= ~UART_MSR_RI;
1185
1186 if (msignals & UART_MSR_CTS)
1187 ch->ch_mistat |= UART_MSR_CTS;
1188 else
1189 ch->ch_mistat &= ~UART_MSR_CTS;
1190
1191
1192 DPR_MSIGS(("Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
1193 ch->ch_portnum,
1194 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
1195 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
1196 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
1197 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
1198 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
1199 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD)));
1200}
1201
1202
1203/* Make the UART raise any of the output signals we want up */
1204static void cls_assert_modem_signals(struct channel_t *ch)
1205{
1206 uchar out;
1207
1208 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1209 return;
1210
1211 out = ch->ch_mostat;
1212
1213 if (ch->ch_flags & CH_LOOPBACK)
1214 out |= UART_MCR_LOOP;
1215
1216 writeb(out, &ch->ch_cls_uart->mcr);
1217
1218 /* Give time for the UART to actually drop the signals */
1219 udelay(10);
1220}
1221
1222
1223static void cls_send_start_character(struct channel_t *ch)
1224{
1225 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1226 return;
1227
1228 if (ch->ch_startc != _POSIX_VDISABLE) {
1229 ch->ch_xon_sends++;
1230 writeb(ch->ch_startc, &ch->ch_cls_uart->txrx);
1231 }
1232}
1233
1234
1235static void cls_send_stop_character(struct channel_t *ch)
1236{
1237 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1238 return;
1239
1240 if (ch->ch_stopc != _POSIX_VDISABLE) {
1241 ch->ch_xoff_sends++;
1242 writeb(ch->ch_stopc, &ch->ch_cls_uart->txrx);
1243 }
1244}
1245
1246
1247/* Inits UART */
1248static void cls_uart_init(struct channel_t *ch)
1249{
1250 uchar lcrb = readb(&ch->ch_cls_uart->lcr);
1251 uchar isr_fcr = 0;
1252
1253 writeb(0, &ch->ch_cls_uart->ier);
1254
1255 /*
1256 * The Enhanced Register Set may only be accessed when
1257 * the Line Control Register is set to 0xBFh.
1258 */
1259 writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr);
1260
1261 isr_fcr = readb(&ch->ch_cls_uart->isr_fcr);
1262
1263 /* Turn on Enhanced/Extended controls */
1264 isr_fcr |= (UART_EXAR654_EFR_ECB);
1265
1266 writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr);
1267
1268 /* Write old LCR value back out, which turns enhanced access off */
1269 writeb(lcrb, &ch->ch_cls_uart->lcr);
1270
1271 /* Clear out UART and FIFO */
1272 readb(&ch->ch_cls_uart->txrx);
1273
1274 writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr);
1275 udelay(10);
1276
1277 ch->ch_flags |= (CH_FIFO_ENABLED | CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1278
1279 readb(&ch->ch_cls_uart->lsr);
1280 readb(&ch->ch_cls_uart->msr);
1281}
1282
1283
1284/*
1285 * Turns off UART.
1286 */
1287static void cls_uart_off(struct channel_t *ch)
1288{
1289 writeb(0, &ch->ch_cls_uart->ier);
1290}
1291
1292
1293/*
1294 * cls_get_uarts_bytes_left.
1295 * Returns 0 is nothing left in the FIFO, returns 1 otherwise.
1296 *
1297 * The channel lock MUST be held by the calling function.
1298 */
1299static uint cls_get_uart_bytes_left(struct channel_t *ch)
1300{
1301 uchar left = 0;
1302 uchar lsr = 0;
1303
1304 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1305 return 0;
1306
1307 lsr = readb(&ch->ch_cls_uart->lsr);
1308
1309 /* Determine whether the Transmitter is empty or not */
1310 if (!(lsr & UART_LSR_TEMT)) {
1311 if (ch->ch_flags & CH_TX_FIFO_EMPTY) {
1312 tasklet_schedule(&ch->ch_bd->helper_tasklet);
1313 }
1314 left = 1;
1315 }
1316 else {
1317 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1318 left = 0;
1319 }
1320
1321 return left;
1322}
1323
1324
1325/*
1326 * cls_send_break.
1327 * Starts sending a break thru the UART.
1328 *
1329 * The channel lock MUST be held by the calling function.
1330 */
1331static void cls_send_break(struct channel_t *ch, int msecs)
1332{
1333 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1334 return;
1335
1336 /*
1337 * If we receive a time of 0, this means turn off the break.
1338 */
1339 if (msecs == 0) {
1340 /* Turn break off, and unset some variables */
1341 if (ch->ch_flags & CH_BREAK_SENDING) {
1342 uchar temp = readb(&ch->ch_cls_uart->lcr);
1343 writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr);
1344 ch->ch_flags &= ~(CH_BREAK_SENDING);
1345 ch->ch_stop_sending_break = 0;
1346 DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
1347 }
1348 return;
1349 }
1350
1351 /*
1352 * Set the time we should stop sending the break.
1353 * If we are already sending a break, toss away the existing
1354 * time to stop, and use this new value instead.
1355 */
1356 ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs);
1357
1358 /* Tell the UART to start sending the break */
1359 if (!(ch->ch_flags & CH_BREAK_SENDING)) {
1360 uchar temp = readb(&ch->ch_cls_uart->lcr);
1361 writeb((temp | UART_LCR_SBC), &ch->ch_cls_uart->lcr);
1362 ch->ch_flags |= (CH_BREAK_SENDING);
1363 DPR_IOCTL(("Port %d. Starting UART_LCR_SBC! start: %lx should end: %lx\n",
1364 ch->ch_portnum, jiffies, ch->ch_stop_sending_break));
1365 }
1366}
1367
1368
1369/*
1370 * cls_send_immediate_char.
1371 * Sends a specific character as soon as possible to the UART,
1372 * jumping over any bytes that might be in the write queue.
1373 *
1374 * The channel lock MUST be held by the calling function.
1375 */
1376static void cls_send_immediate_char(struct channel_t *ch, unsigned char c)
1377{
1378 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1379 return;
1380
1381 writeb(c, &ch->ch_cls_uart->txrx);
1382}
1383
1384static void cls_vpd(struct board_t *brd)
1385{
1386 ulong vpdbase; /* Start of io base of the card */
1387 uchar *re_map_vpdbase;/* Remapped memory of the card */
1388 int i = 0;
1389
1390
1391 vpdbase = pci_resource_start(brd->pdev, 3);
1392
1393 /* No VPD */
1394 if (!vpdbase)
1395 return;
1396
1397 re_map_vpdbase = ioremap(vpdbase, 0x400);
1398
1399 if (!re_map_vpdbase)
1400 return;
1401
1402 /* Store the VPD into our buffer */
1403 for (i = 0; i < 0x40; i++) {
1404 brd->vpd[i] = readb(re_map_vpdbase + i);
1405 printk("%x ", brd->vpd[i]);
1406 }
1407 printk("\n");
1408
1409 if (re_map_vpdbase)
1410 iounmap(re_map_vpdbase);
1411}
1412
diff --git a/drivers/staging/dgnc/dgnc_cls.h b/drivers/staging/dgnc/dgnc_cls.h
new file mode 100644
index 000000000000..dca5ea38cd54
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_cls.h
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 *
21 */
22
23#ifndef __DGNC_CLS_H
24#define __DGNC_CLS_H
25
26#include "dgnc_types.h"
27
28
29/************************************************************************
30 * Per channel/port Classic UART structure *
31 ************************************************************************
32 * Base Structure Entries Usage Meanings to Host *
33 * *
34 * W = read write R = read only *
35 * U = Unused. *
36 ************************************************************************/
37
38struct cls_uart_struct {
39 volatile uchar txrx; /* WR RHR/THR - Holding Reg */
40 volatile uchar ier; /* WR IER - Interrupt Enable Reg */
41 volatile uchar isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
42 volatile uchar lcr; /* WR LCR - Line Control Reg */
43 volatile uchar mcr; /* WR MCR - Modem Control Reg */
44 volatile uchar lsr; /* WR LSR - Line Status Reg */
45 volatile uchar msr; /* WR MSR - Modem Status Reg */
46 volatile uchar spr; /* WR SPR - Scratch Pad Reg */
47};
48
49/* Where to read the interrupt register (8bits) */
50#define UART_CLASSIC_POLL_ADDR_OFFSET 0x40
51
52#define UART_EXAR654_ENHANCED_REGISTER_SET 0xBF
53
54#define UART_16654_FCR_TXTRIGGER_8 0x0
55#define UART_16654_FCR_TXTRIGGER_16 0x10
56#define UART_16654_FCR_TXTRIGGER_32 0x20
57#define UART_16654_FCR_TXTRIGGER_56 0x30
58
59#define UART_16654_FCR_RXTRIGGER_8 0x0
60#define UART_16654_FCR_RXTRIGGER_16 0x40
61#define UART_16654_FCR_RXTRIGGER_56 0x80
62#define UART_16654_FCR_RXTRIGGER_60 0xC0
63
64#define UART_IIR_XOFF 0x10 /* Received Xoff signal/Special character */
65#define UART_IIR_CTSRTS 0x20 /* Received CTS/RTS change of state */
66#define UART_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */
67
68/*
69 * These are the EXTENDED definitions for the Exar 654's Interrupt
70 * Enable Register.
71 */
72#define UART_EXAR654_EFR_ECB 0x10 /* Enhanced control bit */
73#define UART_EXAR654_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */
74#define UART_EXAR654_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */
75#define UART_EXAR654_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */
76#define UART_EXAR654_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */
77
78#define UART_EXAR654_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */
79#define UART_EXAR654_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */
80
81#define UART_EXAR654_IER_XOFF 0x20 /* Xoff Interrupt Enable */
82#define UART_EXAR654_IER_RTSDTR 0x40 /* Output Interrupt Enable */
83#define UART_EXAR654_IER_CTSDSR 0x80 /* Input Interrupt Enable */
84
85/*
86 * Our Global Variables
87 */
88extern struct board_ops dgnc_cls_ops;
89
90#endif
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
new file mode 100644
index 000000000000..7c88de773745
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -0,0 +1,1028 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 * $Id: dgnc_driver.c,v 1.3 2011/06/23 12:47:35 markh Exp $
31 *
32 */
33
34
35#include <linux/kernel.h>
36#include <linux/version.h>
37#include <linux/module.h>
38#include <linux/pci.h>
39
40#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
41#include <linux/sched.h>
42#endif
43
44#include "dgnc_driver.h"
45#include "dgnc_pci.h"
46#include "dgnc_proc.h"
47#include "dpacompat.h"
48#include "dgnc_mgmt.h"
49#include "dgnc_tty.h"
50#include "dgnc_trace.h"
51#include "dgnc_cls.h"
52#include "dgnc_neo.h"
53#include "dgnc_sysfs.h"
54
55MODULE_LICENSE("GPL");
56MODULE_AUTHOR("Digi International, http://www.digi.com");
57MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
58MODULE_SUPPORTED_DEVICE("dgnc");
59
60/*
61 * insmod command line overrideable parameters
62 *
63 * NOTE: we use a set of macros to create the variables, which allows
64 * us to specify the variable type, name, initial value, and description.
65 */
66PARM_INT(debug, 0x00, 0644, "Driver debugging level");
67PARM_INT(rawreadok, 1, 0644, "Bypass flip buffers on input");
68PARM_INT(trcbuf_size, 0x100000, 0644, "Debugging trace buffer size.");
69
70/**************************************************************************
71 *
72 * protos for this file
73 *
74 */
75static int dgnc_start(void);
76static int dgnc_finalize_board_init(struct board_t *brd);
77static void dgnc_init_globals(void);
78static int dgnc_found_board(struct pci_dev *pdev, int id);
79static void dgnc_cleanup_board(struct board_t *brd);
80static void dgnc_poll_handler(ulong dummy);
81static int dgnc_init_pci(void);
82static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
83static void dgnc_remove_one(struct pci_dev *dev);
84static int dgnc_probe1(struct pci_dev *pdev, int card_type);
85static void dgnc_do_remap(struct board_t *brd);
86static void dgnc_mbuf(struct board_t *brd, const char *fmt, ...);
87
88
89/* Driver load/unload functions */
90int dgnc_init_module(void);
91void dgnc_cleanup_module(void);
92
93module_init(dgnc_init_module);
94module_exit(dgnc_cleanup_module);
95
96
97/*
98 * File operations permitted on Control/Management major.
99 */
100static struct file_operations dgnc_BoardFops =
101{
102 .owner = THIS_MODULE,
103#ifdef HAVE_UNLOCKED_IOCTL
104 .unlocked_ioctl = dgnc_mgmt_ioctl,
105#else
106 .ioctl = dgnc_mgmt_ioctl,
107#endif
108 .open = dgnc_mgmt_open,
109 .release = dgnc_mgmt_close
110};
111
112
113/*
114 * Globals
115 */
116uint dgnc_NumBoards;
117struct board_t *dgnc_Board[MAXBOARDS];
118DEFINE_SPINLOCK(dgnc_global_lock);
119int dgnc_driver_state = DRIVER_INITIALIZED;
120ulong dgnc_poll_counter;
121uint dgnc_Major;
122int dgnc_poll_tick = 20; /* Poll interval - 20 ms */
123
124/*
125 * Static vars.
126 */
127static uint dgnc_Major_Control_Registered = FALSE;
128static uint dgnc_driver_start = FALSE;
129
130static struct class *dgnc_class;
131
132/*
133 * Poller stuff
134 */
135static DEFINE_SPINLOCK(dgnc_poll_lock); /* Poll scheduling lock */
136static ulong dgnc_poll_time; /* Time of next poll */
137static uint dgnc_poll_stop; /* Used to tell poller to stop */
138static struct timer_list dgnc_poll_timer;
139
140
141static struct pci_device_id dgnc_pci_tbl[] = {
142 { DIGI_VID, PCI_DEVICE_CLASSIC_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
143 { DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
144 { DIGI_VID, PCI_DEVICE_CLASSIC_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
145 { DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
146 { DIGI_VID, PCI_DEVICE_NEO_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
147 { DIGI_VID, PCI_DEVICE_NEO_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
148 { DIGI_VID, PCI_DEVICE_NEO_2DB9_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
149 { DIGI_VID, PCI_DEVICE_NEO_2DB9PRI_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
150 { DIGI_VID, PCI_DEVICE_NEO_2RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
151 { DIGI_VID, PCI_DEVICE_NEO_2RJ45PRI_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
152 { DIGI_VID, PCI_DEVICE_NEO_1_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
153 { DIGI_VID, PCI_DEVICE_NEO_1_422_485_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
154 { DIGI_VID, PCI_DEVICE_NEO_2_422_485_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
155 { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
156 { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
157 { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_4RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
158 { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_8RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
159 {0,} /* 0 terminated list. */
160};
161MODULE_DEVICE_TABLE(pci, dgnc_pci_tbl);
162
163struct board_id {
164 uchar *name;
165 uint maxports;
166 unsigned int is_pci_express;
167};
168
169static struct board_id dgnc_Ids[] =
170{
171 { PCI_DEVICE_CLASSIC_4_PCI_NAME, 4, 0 },
172 { PCI_DEVICE_CLASSIC_4_422_PCI_NAME, 4, 0 },
173 { PCI_DEVICE_CLASSIC_8_PCI_NAME, 8, 0 },
174 { PCI_DEVICE_CLASSIC_8_422_PCI_NAME, 8, 0 },
175 { PCI_DEVICE_NEO_4_PCI_NAME, 4, 0 },
176 { PCI_DEVICE_NEO_8_PCI_NAME, 8, 0 },
177 { PCI_DEVICE_NEO_2DB9_PCI_NAME, 2, 0 },
178 { PCI_DEVICE_NEO_2DB9PRI_PCI_NAME, 2, 0 },
179 { PCI_DEVICE_NEO_2RJ45_PCI_NAME, 2, 0 },
180 { PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME, 2, 0 },
181 { PCI_DEVICE_NEO_1_422_PCI_NAME, 1, 0 },
182 { PCI_DEVICE_NEO_1_422_485_PCI_NAME, 1, 0 },
183 { PCI_DEVICE_NEO_2_422_485_PCI_NAME, 2, 0 },
184 { PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME, 8, 1 },
185 { PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME, 4, 1 },
186 { PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME, 4, 1 },
187 { PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME, 8, 1 },
188 { NULL, 0, 0 }
189};
190
191static struct pci_driver dgnc_driver = {
192 .name = "dgnc",
193 .probe = dgnc_init_one,
194 .id_table = dgnc_pci_tbl,
195 .remove = dgnc_remove_one,
196};
197
198
199char *dgnc_state_text[] = {
200 "Board Failed",
201 "Board Found",
202 "Board READY",
203};
204
205char *dgnc_driver_state_text[] = {
206 "Driver Initialized",
207 "Driver Ready."
208};
209
210
211
212/************************************************************************
213 *
214 * Driver load/unload functions
215 *
216 ************************************************************************/
217
218
219/*
220 * init_module()
221 *
222 * Module load. This is where it all starts.
223 */
224int dgnc_init_module(void)
225{
226 int rc = 0;
227
228 APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));
229
230 /*
231 * Initialize global stuff
232 */
233 rc = dgnc_start();
234
235 if (rc < 0) {
236 return(rc);
237 }
238
239 /*
240 * Find and configure all the cards
241 */
242 rc = dgnc_init_pci();
243
244 /*
245 * If something went wrong in the scan, bail out of driver.
246 */
247 if (rc < 0) {
248 /* Only unregister the pci driver if it was actually registered. */
249 if (dgnc_NumBoards)
250 pci_unregister_driver(&dgnc_driver);
251 else
252 printk("WARNING: dgnc driver load failed. No Digi Neo or Classic boards found.\n");
253
254 dgnc_cleanup_module();
255 }
256 else {
257 dgnc_create_driver_sysfiles(&dgnc_driver);
258 }
259
260 DPR_INIT(("Finished init_module. Returning %d\n", rc));
261 return (rc);
262}
263
264
265/*
266 * Start of driver.
267 */
268static int dgnc_start(void)
269{
270 int rc = 0;
271 unsigned long flags;
272
273 if (dgnc_driver_start == FALSE) {
274
275 dgnc_driver_start = TRUE;
276
277 /* make sure that the globals are init'd before we do anything else */
278 dgnc_init_globals();
279
280 dgnc_NumBoards = 0;
281
282 APR(("For the tools package or updated drivers please visit http://www.digi.com\n"));
283
284 /*
285 * Register our base character device into the kernel.
286 * This allows the download daemon to connect to the downld device
287 * before any of the boards are init'ed.
288 */
289 if (!dgnc_Major_Control_Registered) {
290 /*
291 * Register management/dpa devices
292 */
293 rc = register_chrdev(0, "dgnc", &dgnc_BoardFops);
294 if (rc <= 0) {
295 APR(("Can't register dgnc driver device (%d)\n", rc));
296 rc = -ENXIO;
297 return(rc);
298 }
299 dgnc_Major = rc;
300
301 dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt");
302#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
303 device_create_drvdata(dgnc_class, NULL,
304 MKDEV(dgnc_Major, 0),
305 NULL, "dgnc_mgmt");
306#else
307 device_create(dgnc_class, NULL,
308 MKDEV(dgnc_Major, 0),
309 NULL, "dgnc_mgmt");
310#endif
311
312 dgnc_Major_Control_Registered = TRUE;
313 }
314
315 /*
316 * Register our basic stuff in /proc/dgnc
317 */
318 dgnc_proc_register_basic_prescan();
319
320 /*
321 * Init any global tty stuff.
322 */
323 rc = dgnc_tty_preinit();
324
325 if (rc < 0) {
326 APR(("tty preinit - not enough memory (%d)\n", rc));
327 return(rc);
328 }
329
330 /* Start the poller */
331 DGNC_LOCK(dgnc_poll_lock, flags);
332 init_timer(&dgnc_poll_timer);
333 dgnc_poll_timer.function = dgnc_poll_handler;
334 dgnc_poll_timer.data = 0;
335 dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick);
336 dgnc_poll_timer.expires = dgnc_poll_time;
337 DGNC_UNLOCK(dgnc_poll_lock, flags);
338
339 add_timer(&dgnc_poll_timer);
340
341 dgnc_driver_state = DRIVER_READY;
342 }
343
344 return(rc);
345}
346
347/*
348 * Register pci driver, and return how many boards we have.
349 */
350static int dgnc_init_pci(void)
351{
352 return pci_register_driver(&dgnc_driver);
353}
354
355
356/* returns count (>= 0), or negative on error */
357static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
358{
359 int rc;
360
361 /* wake up and enable device */
362 rc = pci_enable_device(pdev);
363
364 if (rc < 0) {
365 rc = -EIO;
366 } else {
367 rc = dgnc_probe1(pdev, ent->driver_data);
368 if (rc == 0) {
369 dgnc_NumBoards++;
370 DPR_INIT(("Incrementing numboards to %d\n", dgnc_NumBoards));
371 }
372 }
373 return rc;
374}
375
376static int dgnc_probe1(struct pci_dev *pdev, int card_type)
377{
378 return dgnc_found_board(pdev, card_type);
379}
380
381
382static void dgnc_remove_one(struct pci_dev *dev)
383{
384 /* Do Nothing */
385}
386
387/*
388 * dgnc_cleanup_module()
389 *
390 * Module unload. This is where it all ends.
391 */
392void dgnc_cleanup_module(void)
393{
394 int i;
395 ulong lock_flags;
396
397 DGNC_LOCK(dgnc_poll_lock, lock_flags);
398 dgnc_poll_stop = 1;
399 DGNC_UNLOCK(dgnc_poll_lock, lock_flags);
400
401 /* Turn off poller right away. */
402 del_timer_sync(&dgnc_poll_timer);
403
404 dgnc_proc_unregister_all();
405
406 dgnc_remove_driver_sysfiles(&dgnc_driver);
407
408 if (dgnc_Major_Control_Registered) {
409 device_destroy(dgnc_class, MKDEV(dgnc_Major, 0));
410 class_destroy(dgnc_class);
411 unregister_chrdev(dgnc_Major, "dgnc");
412 }
413
414 for (i = 0; i < dgnc_NumBoards; ++i) {
415 dgnc_remove_ports_sysfiles(dgnc_Board[i]);
416 dgnc_tty_uninit(dgnc_Board[i]);
417 dgnc_cleanup_board(dgnc_Board[i]);
418 }
419
420 dgnc_tty_post_uninit();
421
422#if defined(DGNC_TRACER)
423 /* last thing, make sure we release the tracebuffer */
424 dgnc_tracer_free();
425#endif
426 if (dgnc_NumBoards)
427 pci_unregister_driver(&dgnc_driver);
428}
429
430
431/*
432 * dgnc_cleanup_board()
433 *
434 * Free all the memory associated with a board
435 */
436static void dgnc_cleanup_board(struct board_t *brd)
437{
438 int i = 0;
439
440 if(!brd || brd->magic != DGNC_BOARD_MAGIC)
441 return;
442
443 switch (brd->device) {
444 case PCI_DEVICE_CLASSIC_4_DID:
445 case PCI_DEVICE_CLASSIC_8_DID:
446 case PCI_DEVICE_CLASSIC_4_422_DID:
447 case PCI_DEVICE_CLASSIC_8_422_DID:
448
449 /* Tell card not to interrupt anymore. */
450 outb(0, brd->iobase + 0x4c);
451 break;
452
453 default:
454 break;
455 }
456
457 if (brd->irq)
458 free_irq(brd->irq, brd);
459
460 tasklet_kill(&brd->helper_tasklet);
461
462 if (brd->re_map_membase) {
463 iounmap(brd->re_map_membase);
464 brd->re_map_membase = NULL;
465 }
466
467 if (brd->msgbuf_head) {
468 unsigned long flags;
469
470 DGNC_LOCK(dgnc_global_lock, flags);
471 brd->msgbuf = NULL;
472 printk(brd->msgbuf_head);
473 kfree(brd->msgbuf_head);
474 brd->msgbuf_head = NULL;
475 DGNC_UNLOCK(dgnc_global_lock, flags);
476 }
477
478 /* Free all allocated channels structs */
479 for (i = 0; i < MAXPORTS ; i++) {
480 if (brd->channels[i]) {
481 if (brd->channels[i]->ch_rqueue)
482 kfree(brd->channels[i]->ch_rqueue);
483 if (brd->channels[i]->ch_equeue)
484 kfree(brd->channels[i]->ch_equeue);
485 if (brd->channels[i]->ch_wqueue)
486 kfree(brd->channels[i]->ch_wqueue);
487
488 kfree(brd->channels[i]);
489 brd->channels[i] = NULL;
490 }
491 }
492
493 if (brd->flipbuf)
494 kfree(brd->flipbuf);
495
496 dgnc_Board[brd->boardnum] = NULL;
497
498 kfree(brd);
499}
500
501
502/*
503 * dgnc_found_board()
504 *
505 * A board has been found, init it.
506 */
507static int dgnc_found_board(struct pci_dev *pdev, int id)
508{
509 struct board_t *brd;
510 unsigned int pci_irq;
511 int i = 0;
512 int rc = 0;
513 unsigned long flags;
514
515 /* get the board structure and prep it */
516 brd = dgnc_Board[dgnc_NumBoards] =
517 (struct board_t *) dgnc_driver_kzmalloc(sizeof(struct board_t), GFP_KERNEL);
518 if (!brd) {
519 APR(("memory allocation for board structure failed\n"));
520 return(-ENOMEM);
521 }
522
523 /* make a temporary message buffer for the boot messages */
524 brd->msgbuf = brd->msgbuf_head =
525 (char *) dgnc_driver_kzmalloc(sizeof(char) * 8192, GFP_KERNEL);
526 if (!brd->msgbuf) {
527 kfree(brd);
528 APR(("memory allocation for board msgbuf failed\n"));
529 return(-ENOMEM);
530 }
531
532 /* store the info for the board we've found */
533 brd->magic = DGNC_BOARD_MAGIC;
534 brd->boardnum = dgnc_NumBoards;
535 brd->vendor = dgnc_pci_tbl[id].vendor;
536 brd->device = dgnc_pci_tbl[id].device;
537 brd->pdev = pdev;
538 brd->pci_bus = pdev->bus->number;
539 brd->pci_slot = PCI_SLOT(pdev->devfn);
540 brd->name = dgnc_Ids[id].name;
541 brd->maxports = dgnc_Ids[id].maxports;
542 if (dgnc_Ids[i].is_pci_express)
543 brd->bd_flags |= BD_IS_PCI_EXPRESS;
544 brd->dpastatus = BD_NOFEP;
545 init_waitqueue_head(&brd->state_wait);
546
547 DGNC_SPINLOCK_INIT(brd->bd_lock);
548 DGNC_SPINLOCK_INIT(brd->bd_intr_lock);
549
550 brd->state = BOARD_FOUND;
551
552 for (i = 0; i < MAXPORTS; i++) {
553 brd->channels[i] = NULL;
554 }
555
556 /* store which card & revision we have */
557 pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
558 pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
559 pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
560
561 pci_irq = pdev->irq;
562 brd->irq = pci_irq;
563
564
565 switch(brd->device) {
566
567 case PCI_DEVICE_CLASSIC_4_DID:
568 case PCI_DEVICE_CLASSIC_8_DID:
569 case PCI_DEVICE_CLASSIC_4_422_DID:
570 case PCI_DEVICE_CLASSIC_8_422_DID:
571
572 brd->dpatype = T_CLASSIC | T_PCIBUS;
573
574 DPR_INIT(("dgnc_found_board - Classic.\n"));
575
576 /*
577 * For PCI ClassicBoards
578 * PCI Local Address (i.e. "resource" number) space
579 * 0 PLX Memory Mapped Config
580 * 1 PLX I/O Mapped Config
581 * 2 I/O Mapped UARTs and Status
582 * 3 Memory Mapped VPD
583 * 4 Memory Mapped UARTs and Status
584 */
585
586
587 /* get the PCI Base Address Registers */
588 brd->membase = pci_resource_start(pdev, 4);
589
590 if (!brd->membase) {
591 APR(("card has no PCI IO resources, failing board.\n"));
592 return -ENODEV;
593 }
594
595 brd->membase_end = pci_resource_end(pdev, 4);
596
597 if (brd->membase & 1)
598 brd->membase &= ~3;
599 else
600 brd->membase &= ~15;
601
602 brd->iobase = pci_resource_start(pdev, 1);
603 brd->iobase_end = pci_resource_end(pdev, 1);
604 brd->iobase = ((unsigned int) (brd->iobase)) & 0xFFFE;
605
606 /* Assign the board_ops struct */
607 brd->bd_ops = &dgnc_cls_ops;
608
609 brd->bd_uart_offset = 0x8;
610 brd->bd_dividend = 921600;
611
612 dgnc_do_remap(brd);
613
614 /* Get and store the board VPD, if it exists */
615 brd->bd_ops->vpd(brd);
616
617 /*
618 * Enable Local Interrupt 1 (0x1),
619 * Local Interrupt 1 Polarity Active high (0x2),
620 * Enable PCI interrupt (0x40)
621 */
622 outb(0x43, brd->iobase + 0x4c);
623
624 break;
625
626
627 case PCI_DEVICE_NEO_4_DID:
628 case PCI_DEVICE_NEO_8_DID:
629 case PCI_DEVICE_NEO_2DB9_DID:
630 case PCI_DEVICE_NEO_2DB9PRI_DID:
631 case PCI_DEVICE_NEO_2RJ45_DID:
632 case PCI_DEVICE_NEO_2RJ45PRI_DID:
633 case PCI_DEVICE_NEO_1_422_DID:
634 case PCI_DEVICE_NEO_1_422_485_DID:
635 case PCI_DEVICE_NEO_2_422_485_DID:
636 case PCI_DEVICE_NEO_EXPRESS_8_DID:
637 case PCI_DEVICE_NEO_EXPRESS_4_DID:
638 case PCI_DEVICE_NEO_EXPRESS_4RJ45_DID:
639 case PCI_DEVICE_NEO_EXPRESS_8RJ45_DID:
640
641 /*
642 * This chip is set up 100% when we get to it.
643 * No need to enable global interrupts or anything.
644 */
645 if (brd->bd_flags & BD_IS_PCI_EXPRESS)
646 brd->dpatype = T_NEO_EXPRESS | T_PCIBUS;
647 else
648 brd->dpatype = T_NEO | T_PCIBUS;
649
650 DPR_INIT(("dgnc_found_board - NEO.\n"));
651
652 /* get the PCI Base Address Registers */
653 brd->membase = pci_resource_start(pdev, 0);
654 brd->membase_end = pci_resource_end(pdev, 0);
655
656 if (brd->membase & 1)
657 brd->membase &= ~3;
658 else
659 brd->membase &= ~15;
660
661 /* Assign the board_ops struct */
662 brd->bd_ops = &dgnc_neo_ops;
663
664 brd->bd_uart_offset = 0x200;
665 brd->bd_dividend = 921600;
666
667 dgnc_do_remap(brd);
668
669 if (brd->re_map_membase) {
670
671 /* After remap is complete, we need to read and store the dvid */
672 brd->dvid = readb(brd->re_map_membase + 0x8D);
673
674 /* Get and store the board VPD, if it exists */
675 brd->bd_ops->vpd(brd);
676 }
677 break;
678
679 default:
680 APR(("Did not find any compatible Neo or Classic PCI boards in system.\n"));
681 return (-ENXIO);
682
683 }
684
685 /*
686 * Do tty device initialization.
687 */
688
689 rc = dgnc_tty_register(brd);
690 if (rc < 0) {
691 dgnc_tty_uninit(brd);
692 APR(("Can't register tty devices (%d)\n", rc));
693 brd->state = BOARD_FAILED;
694 brd->dpastatus = BD_NOFEP;
695 goto failed;
696 }
697
698 rc = dgnc_finalize_board_init(brd);
699 if (rc < 0) {
700 APR(("Can't finalize board init (%d)\n", rc));
701 brd->state = BOARD_FAILED;
702 brd->dpastatus = BD_NOFEP;
703
704 goto failed;
705 }
706
707 rc = dgnc_tty_init(brd);
708 if (rc < 0) {
709 dgnc_tty_uninit(brd);
710 APR(("Can't init tty devices (%d)\n", rc));
711 brd->state = BOARD_FAILED;
712 brd->dpastatus = BD_NOFEP;
713
714 goto failed;
715 }
716
717 brd->state = BOARD_READY;
718 brd->dpastatus = BD_RUNNING;
719
720 dgnc_create_ports_sysfiles(brd);
721
722 /* init our poll helper tasklet */
723 tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, (unsigned long) brd);
724
725 /* Log the information about the board */
726 dgnc_mbuf(brd, DRVSTR": board %d: %s (rev %d), irq %d\n",
727 dgnc_NumBoards, brd->name, brd->rev, brd->irq);
728
729 DPR_INIT(("dgnc_scan(%d) - printing out the msgbuf\n", i));
730 DGNC_LOCK(dgnc_global_lock, flags);
731 brd->msgbuf = NULL;
732 printk(brd->msgbuf_head);
733 kfree(brd->msgbuf_head);
734 brd->msgbuf_head = NULL;
735 DGNC_UNLOCK(dgnc_global_lock, flags);
736
737 /*
738 * allocate flip buffer for board.
739 *
740 * Okay to malloc with GFP_KERNEL, we are not at interrupt
741 * context, and there are no locks held.
742 */
743 brd->flipbuf = dgnc_driver_kzmalloc(MYFLIPLEN, GFP_KERNEL);
744
745 dgnc_proc_register_basic_postscan(dgnc_NumBoards);
746
747 wake_up_interruptible(&brd->state_wait);
748
749 return(0);
750
751failed:
752
753 return (-ENXIO);
754
755}
756
757
758static int dgnc_finalize_board_init(struct board_t *brd) {
759 int rc = 0;
760
761 DPR_INIT(("dgnc_finalize_board_init() - start\n"));
762
763 if (!brd || brd->magic != DGNC_BOARD_MAGIC)
764 return(-ENODEV);
765
766 DPR_INIT(("dgnc_finalize_board_init() - start #2\n"));
767
768 if (brd->irq) {
769 rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "DGNC", brd);
770
771 if (rc) {
772 printk("Failed to hook IRQ %d\n",brd->irq);
773 brd->state = BOARD_FAILED;
774 brd->dpastatus = BD_NOFEP;
775 rc = -ENODEV;
776 } else {
777 DPR_INIT(("Requested and received usage of IRQ %d\n", brd->irq));
778 }
779 }
780 return(rc);
781}
782
783/*
784 * Remap PCI memory.
785 */
786static void dgnc_do_remap(struct board_t *brd)
787{
788
789 if (!brd || brd->magic != DGNC_BOARD_MAGIC)
790 return;
791
792 brd->re_map_membase = ioremap(brd->membase, 0x1000);
793
794 DPR_INIT(("remapped mem: 0x%p\n", brd->re_map_membase));
795}
796
797
798/*****************************************************************************
799*
800* Function:
801*
802* dgnc_poll_handler
803*
804* Author:
805*
806* Scott H Kilau
807*
808* Parameters:
809*
810* dummy -- ignored
811*
812* Return Values:
813*
814* none
815*
816* Description:
817*
818* As each timer expires, it determines (a) whether the "transmit"
819* waiter needs to be woken up, and (b) whether the poller needs to
820* be rescheduled.
821*
822******************************************************************************/
823
824static void dgnc_poll_handler(ulong dummy)
825{
826 struct board_t *brd;
827 unsigned long lock_flags;
828 int i;
829 unsigned long new_time;
830
831 dgnc_poll_counter++;
832
833 /*
834 * Do not start the board state machine until
835 * driver tells us its up and running, and has
836 * everything it needs.
837 */
838 if (dgnc_driver_state != DRIVER_READY) {
839 goto schedule_poller;
840 }
841
842 /* Go thru each board, kicking off a tasklet for each if needed */
843 for (i = 0; i < dgnc_NumBoards; i++) {
844 brd = dgnc_Board[i];
845
846 DGNC_LOCK(brd->bd_lock, lock_flags);
847
848 /* If board is in a failed state, don't bother scheduling a tasklet */
849 if (brd->state == BOARD_FAILED) {
850 DGNC_UNLOCK(brd->bd_lock, lock_flags);
851 continue;
852 }
853
854 /* Schedule a poll helper task */
855 tasklet_schedule(&brd->helper_tasklet);
856
857 DGNC_UNLOCK(brd->bd_lock, lock_flags);
858 }
859
860schedule_poller:
861
862 /*
863 * Schedule ourself back at the nominal wakeup interval.
864 */
865 DGNC_LOCK(dgnc_poll_lock, lock_flags);
866 dgnc_poll_time += dgnc_jiffies_from_ms(dgnc_poll_tick);
867
868 new_time = dgnc_poll_time - jiffies;
869
870 if ((ulong) new_time >= 2 * dgnc_poll_tick) {
871 dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick);
872 }
873
874 init_timer(&dgnc_poll_timer);
875 dgnc_poll_timer.function = dgnc_poll_handler;
876 dgnc_poll_timer.data = 0;
877 dgnc_poll_timer.expires = dgnc_poll_time;
878 DGNC_UNLOCK(dgnc_poll_lock, lock_flags);
879
880 if (!dgnc_poll_stop)
881 add_timer(&dgnc_poll_timer);
882}
883
884/*
885 * dgnc_init_globals()
886 *
887 * This is where we initialize the globals from the static insmod
888 * configuration variables. These are declared near the head of
889 * this file.
890 */
891static void dgnc_init_globals(void)
892{
893 int i = 0;
894
895 dgnc_rawreadok = rawreadok;
896 dgnc_trcbuf_size = trcbuf_size;
897 dgnc_debug = debug;
898
899 for (i = 0; i < MAXBOARDS; i++) {
900 dgnc_Board[i] = NULL;
901 }
902
903 init_timer(&dgnc_poll_timer);
904}
905
906
907/************************************************************************
908 *
909 * Utility functions
910 *
911 ************************************************************************/
912
913
914/*
915 * dgnc_driver_kzmalloc()
916 *
917 * Malloc and clear memory,
918 */
919void *dgnc_driver_kzmalloc(size_t size, int priority)
920{
921 void *p = kmalloc(size, priority);
922 if(p)
923 memset(p, 0, size);
924 return(p);
925}
926
927
928/*
929 * dgnc_mbuf()
930 *
931 * Used to print to the message buffer during board init.
932 */
933static void dgnc_mbuf(struct board_t *brd, const char *fmt, ...) {
934 va_list ap;
935 char buf[1024];
936 int i;
937 unsigned long flags;
938
939 DGNC_LOCK(dgnc_global_lock, flags);
940
941 /* Format buf using fmt and arguments contained in ap. */
942 va_start(ap, fmt);
943 i = vsprintf(buf, fmt, ap);
944 va_end(ap);
945
946 DPR((buf));
947
948 if (!brd || !brd->msgbuf) {
949 printk(buf);
950 DGNC_UNLOCK(dgnc_global_lock, flags);
951 return;
952 }
953
954 memcpy(brd->msgbuf, buf, strlen(buf));
955 brd->msgbuf += strlen(buf);
956 *brd->msgbuf = (char) NULL;
957
958 DGNC_UNLOCK(dgnc_global_lock, flags);
959}
960
961
962/*
963 * dgnc_ms_sleep()
964 *
965 * Put the driver to sleep for x ms's
966 *
967 * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal.
968 */
969int dgnc_ms_sleep(ulong ms)
970{
971 current->state = TASK_INTERRUPTIBLE;
972 schedule_timeout((ms * HZ) / 1000);
973 return (signal_pending(current));
974}
975
976
977
978/*
979 * dgnc_ioctl_name() : Returns a text version of each ioctl value.
980 */
981char *dgnc_ioctl_name(int cmd)
982{
983 switch(cmd) {
984
985 case TCGETA: return("TCGETA");
986 case TCGETS: return("TCGETS");
987 case TCSETA: return("TCSETA");
988 case TCSETS: return("TCSETS");
989 case TCSETAW: return("TCSETAW");
990 case TCSETSW: return("TCSETSW");
991 case TCSETAF: return("TCSETAF");
992 case TCSETSF: return("TCSETSF");
993 case TCSBRK: return("TCSBRK");
994 case TCXONC: return("TCXONC");
995 case TCFLSH: return("TCFLSH");
996 case TIOCGSID: return("TIOCGSID");
997
998 case TIOCGETD: return("TIOCGETD");
999 case TIOCSETD: return("TIOCSETD");
1000 case TIOCGWINSZ: return("TIOCGWINSZ");
1001 case TIOCSWINSZ: return("TIOCSWINSZ");
1002
1003 case TIOCMGET: return("TIOCMGET");
1004 case TIOCMSET: return("TIOCMSET");
1005 case TIOCMBIS: return("TIOCMBIS");
1006 case TIOCMBIC: return("TIOCMBIC");
1007
1008 /* from digi.h */
1009 case DIGI_SETA: return("DIGI_SETA");
1010 case DIGI_SETAW: return("DIGI_SETAW");
1011 case DIGI_SETAF: return("DIGI_SETAF");
1012 case DIGI_SETFLOW: return("DIGI_SETFLOW");
1013 case DIGI_SETAFLOW: return("DIGI_SETAFLOW");
1014 case DIGI_GETFLOW: return("DIGI_GETFLOW");
1015 case DIGI_GETAFLOW: return("DIGI_GETAFLOW");
1016 case DIGI_GETA: return("DIGI_GETA");
1017 case DIGI_GEDELAY: return("DIGI_GEDELAY");
1018 case DIGI_SEDELAY: return("DIGI_SEDELAY");
1019 case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
1020 case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
1021 case TIOCMODG: return("TIOCMODG");
1022 case TIOCMODS: return("TIOCMODS");
1023 case TIOCSDTR: return("TIOCSDTR");
1024 case TIOCCDTR: return("TIOCCDTR");
1025
1026 default: return("unknown");
1027 }
1028}
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
new file mode 100644
index 000000000000..43177f47209b
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -0,0 +1,566 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 *
21 *************************************************************************
22 *
23 * Driver includes
24 *
25 *************************************************************************/
26
27#ifndef __DGNC_DRIVER_H
28#define __DGNC_DRIVER_H
29
30#include <linux/version.h> /* To get the current Linux version */
31#include <linux/types.h> /* To pick up the varions Linux types */
32#include <linux/tty.h> /* To pick up the various tty structs/defines */
33#include <linux/interrupt.h> /* For irqreturn_t type */
34
35#include "dgnc_types.h" /* Additional types needed by the Digi header files */
36#include "digi.h" /* Digi specific ioctl header */
37#include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */
38#include "dgnc_sysfs.h" /* Support for SYSFS */
39
40/*************************************************************************
41 *
42 * Driver defines
43 *
44 *************************************************************************/
45
46/*
47 * Driver identification, error and debugging statments
48 *
49 * In theory, you can change all occurances of "digi" in the next
50 * three lines, and the driver printk's will all automagically change.
51 *
52 * APR((fmt, args, ...)); Always prints message
53 * DPR((fmt, args, ...)); Only prints if DGNC_TRACER is defined at
54 * compile time and dgnc_debug!=0
55 */
56#define PROCSTR "dgnc" /* /proc entries */
57#define DEVSTR "/dev/dg/dgnc" /* /dev entries */
58#define DRVSTR "dgnc" /* Driver name string
59 * displayed by APR */
60#define APR(args) do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \
61 } while (0)
62#define RAPR(args) do { PRINTF_TO_KMEM(args); printk args; } while (0)
63
64#define TRC_TO_CONSOLE 1
65
66/*
67 * Debugging levels can be set using debug insmod variable
68 * They can also be compiled out completely.
69 */
70
71#define DBG_INIT (dgnc_debug & 0x01)
72#define DBG_BASIC (dgnc_debug & 0x02)
73#define DBG_CORE (dgnc_debug & 0x04)
74
75#define DBG_OPEN (dgnc_debug & 0x08)
76#define DBG_CLOSE (dgnc_debug & 0x10)
77#define DBG_READ (dgnc_debug & 0x20)
78#define DBG_WRITE (dgnc_debug & 0x40)
79
80#define DBG_IOCTL (dgnc_debug & 0x80)
81
82#define DBG_PROC (dgnc_debug & 0x100)
83#define DBG_PARAM (dgnc_debug & 0x200)
84#define DBG_PSCAN (dgnc_debug & 0x400)
85#define DBG_EVENT (dgnc_debug & 0x800)
86
87#define DBG_DRAIN (dgnc_debug & 0x1000)
88#define DBG_MSIGS (dgnc_debug & 0x2000)
89
90#define DBG_MGMT (dgnc_debug & 0x4000)
91#define DBG_INTR (dgnc_debug & 0x8000)
92
93#define DBG_CARR (dgnc_debug & 0x10000)
94
95
96#if defined(DGNC_TRACER)
97
98# if defined(TRC_TO_KMEM)
99/* Choose one: */
100# define TRC_ON_OVERFLOW_WRAP_AROUND
101# undef TRC_ON_OVERFLOW_SHIFT_BUFFER
102# endif //TRC_TO_KMEM
103
104# define TRC_MAXMSG 1024
105# define TRC_OVERFLOW "(OVERFLOW)"
106# define TRC_DTRC "/usr/bin/dtrc"
107
108#if defined TRC_TO_CONSOLE
109#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; }
110#else //!defined TRACE_TO_CONSOLE
111#define PRINTF_TO_CONSOLE(args)
112#endif
113
114#if defined TRC_TO_KMEM
115#define PRINTF_TO_KMEM(args) dgnc_tracef args
116#else //!defined TRC_TO_KMEM
117#define PRINTF_TO_KMEM(args)
118#endif
119
120#define TRC(args) { PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) }
121
122# define DPR_INIT(ARGS) if (DBG_INIT) TRC(ARGS)
123# define DPR_BASIC(ARGS) if (DBG_BASIC) TRC(ARGS)
124# define DPR_CORE(ARGS) if (DBG_CORE) TRC(ARGS)
125# define DPR_OPEN(ARGS) if (DBG_OPEN) TRC(ARGS)
126# define DPR_CLOSE(ARGS) if (DBG_CLOSE) TRC(ARGS)
127# define DPR_READ(ARGS) if (DBG_READ) TRC(ARGS)
128# define DPR_WRITE(ARGS) if (DBG_WRITE) TRC(ARGS)
129# define DPR_IOCTL(ARGS) if (DBG_IOCTL) TRC(ARGS)
130# define DPR_PROC(ARGS) if (DBG_PROC) TRC(ARGS)
131# define DPR_PARAM(ARGS) if (DBG_PARAM) TRC(ARGS)
132# define DPR_PSCAN(ARGS) if (DBG_PSCAN) TRC(ARGS)
133# define DPR_EVENT(ARGS) if (DBG_EVENT) TRC(ARGS)
134# define DPR_DRAIN(ARGS) if (DBG_DRAIN) TRC(ARGS)
135# define DPR_CARR(ARGS) if (DBG_CARR) TRC(ARGS)
136# define DPR_MGMT(ARGS) if (DBG_MGMT) TRC(ARGS)
137# define DPR_INTR(ARGS) if (DBG_INTR) TRC(ARGS)
138# define DPR_MSIGS(ARGS) if (DBG_MSIGS) TRC(ARGS)
139
140# define DPR(ARGS) if (dgnc_debug) TRC(ARGS)
141# define P(X) dgnc_tracef(#X "=%p\n", X)
142# define X(X) dgnc_tracef(#X "=%x\n", X)
143
144#else//!defined DGNC_TRACER
145
146#define PRINTF_TO_KMEM(args)
147# define TRC(ARGS)
148# define DPR_INIT(ARGS)
149# define DPR_BASIC(ARGS)
150# define DPR_CORE(ARGS)
151# define DPR_OPEN(ARGS)
152# define DPR_CLOSE(ARGS)
153# define DPR_READ(ARGS)
154# define DPR_WRITE(ARGS)
155# define DPR_IOCTL(ARGS)
156# define DPR_PROC(ARGS)
157# define DPR_PARAM(ARGS)
158# define DPR_PSCAN(ARGS)
159# define DPR_EVENT(ARGS)
160# define DPR_DRAIN(ARGS)
161# define DPR_CARR(ARGS)
162# define DPR_MGMT(ARGS)
163# define DPR_INTR(ARGS)
164# define DPR_MSIGS(ARGS)
165
166# define DPR(args)
167
168#endif//DGNC_TRACER
169
170/* Number of boards we support at once. */
171#define MAXBOARDS 20
172#define MAXPORTS 8
173#define MAXTTYNAMELEN 200
174
175/* Our 3 magic numbers for our board, channel and unit structs */
176#define DGNC_BOARD_MAGIC 0x5c6df104
177#define DGNC_CHANNEL_MAGIC 0x6c6df104
178#define DGNC_UNIT_MAGIC 0x7c6df104
179
180/* Serial port types */
181#define DGNC_SERIAL 0
182#define DGNC_PRINT 1
183
184#define SERIAL_TYPE_NORMAL 1
185
186#define PORT_NUM(dev) ((dev) & 0x7f)
187#define IS_PRINT(dev) (((dev) & 0xff) >= 0x80)
188
189/* MAX number of stop characters we will send when our read queue is getting full */
190#define MAX_STOPS_SENT 5
191
192/* 4 extra for alignment play space */
193#define WRITEBUFLEN ((4096) + 4)
194#define MYFLIPLEN N_TTY_BUF_SIZE
195
196#define dgnc_jiffies_from_ms(a) (((a) * HZ) / 1000)
197
198/*
199 * Define a local default termios struct. All ports will be created
200 * with this termios initially. This is the same structure that is defined
201 * as the default in tty_io.c with the same settings overriden as in serial.c
202 *
203 * In short, this should match the internal serial ports' defaults.
204 */
205#define DEFAULT_IFLAGS (ICRNL | IXON)
206#define DEFAULT_OFLAGS (OPOST | ONLCR)
207#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL)
208#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \
209 ECHOCTL | ECHOKE | IEXTEN)
210
211#ifndef _POSIX_VDISABLE
212#define _POSIX_VDISABLE '\0'
213#endif
214
215#define SNIFF_MAX 65536 /* Sniff buffer size (2^n) */
216#define SNIFF_MASK (SNIFF_MAX - 1) /* Sniff wrap mask */
217
218/*
219 * Lock function/defines.
220 * Makes spotting lock/unlock locations easier.
221 */
222# define DGNC_SPINLOCK_INIT(x) spin_lock_init(&(x))
223# define DGNC_LOCK(x,y) spin_lock_irqsave(&(x), y)
224# define DGNC_UNLOCK(x,y) spin_unlock_irqrestore(&(x), y)
225
226/*
227 * All the possible states the driver can be while being loaded.
228 */
229enum {
230 DRIVER_INITIALIZED = 0,
231 DRIVER_READY
232};
233
234/*
235 * All the possible states the board can be while booting up.
236 */
237enum {
238 BOARD_FAILED = 0,
239 BOARD_FOUND,
240 BOARD_READY
241};
242
243
244/*************************************************************************
245 *
246 * Structures and closely related defines.
247 *
248 *************************************************************************/
249
250struct board_t;
251struct channel_t;
252
253/************************************************************************
254 * Per board operations structure *
255 ************************************************************************/
256struct board_ops {
257 void (*tasklet) (unsigned long data);
258 irqreturn_t (*intr) (int irq, void *voidbrd);
259 void (*uart_init) (struct channel_t *ch);
260 void (*uart_off) (struct channel_t *ch);
261 int (*drain) (struct tty_struct *tty, uint seconds);
262 void (*param) (struct tty_struct *tty);
263 void (*vpd) (struct board_t *brd);
264 void (*assert_modem_signals) (struct channel_t *ch);
265 void (*flush_uart_write) (struct channel_t *ch);
266 void (*flush_uart_read) (struct channel_t *ch);
267 void (*disable_receiver) (struct channel_t *ch);
268 void (*enable_receiver) (struct channel_t *ch);
269 void (*send_break) (struct channel_t *ch, int);
270 void (*send_start_character) (struct channel_t *ch);
271 void (*send_stop_character) (struct channel_t *ch);
272 void (*copy_data_from_queue_to_uart) (struct channel_t *ch);
273 uint (*get_uart_bytes_left) (struct channel_t *ch);
274 void (*send_immediate_char) (struct channel_t *ch, unsigned char);
275};
276
277/************************************************************************
278 * Device flag definitions for bd_flags.
279 ************************************************************************/
280#define BD_IS_PCI_EXPRESS 0x0001 /* Is a PCI Express board */
281
282
283/*
284 * Per-board information
285 */
286struct board_t
287{
288 int magic; /* Board Magic number. */
289 int boardnum; /* Board number: 0-32 */
290
291 int type; /* Type of board */
292 char *name; /* Product Name */
293 struct pci_dev *pdev; /* Pointer to the pci_dev struct */
294 unsigned long bd_flags; /* Board flags */
295 u16 vendor; /* PCI vendor ID */
296 u16 device; /* PCI device ID */
297 u16 subvendor; /* PCI subsystem vendor ID */
298 u16 subdevice; /* PCI subsystem device ID */
299 uchar rev; /* PCI revision ID */
300 uint pci_bus; /* PCI bus value */
301 uint pci_slot; /* PCI slot value */
302 uint maxports; /* MAX ports this board can handle */
303 uchar dvid; /* Board specific device id */
304 uchar vpd[128]; /* VPD of board, if found */
305 uchar serial_num[20]; /* Serial number of board, if found in VPD */
306
307 spinlock_t bd_lock; /* Used to protect board */
308
309 spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and
310 * the interrupt routine from each other.
311 */
312
313 uint state; /* State of card. */
314 wait_queue_head_t state_wait; /* Place to sleep on for state change */
315
316 struct tasklet_struct helper_tasklet; /* Poll helper tasklet */
317
318 uint nasync; /* Number of ports on card */
319
320 uint irq; /* Interrupt request number */
321 ulong intr_count; /* Count of interrupts */
322 ulong intr_modem; /* Count of interrupts */
323 ulong intr_tx; /* Count of interrupts */
324 ulong intr_rx; /* Count of interrupts */
325
326 ulong membase; /* Start of base memory of the card */
327 ulong membase_end; /* End of base memory of the card */
328
329 uchar *re_map_membase;/* Remapped memory of the card */
330
331 ulong iobase; /* Start of io base of the card */
332 ulong iobase_end; /* End of io base of the card */
333
334 uint bd_uart_offset; /* Space between each UART */
335
336 struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */
337
338 struct tty_driver SerialDriver;
339 char SerialName[200];
340 struct tty_driver PrintDriver;
341 char PrintName[200];
342
343 uint dgnc_Major_Serial_Registered;
344 uint dgnc_Major_TransparentPrint_Registered;
345
346 uint dgnc_Serial_Major;
347 uint dgnc_TransparentPrint_Major;
348
349 uint TtyRefCnt;
350
351 char *flipbuf; /* Our flip buffer, alloced if board is found */
352
353 u16 dpatype; /* The board "type", as defined by DPA */
354 u16 dpastatus; /* The board "status", as defined by DPA */
355
356 /*
357 * Mgmt data.
358 */
359 char *msgbuf_head;
360 char *msgbuf;
361
362 uint bd_dividend; /* Board/UARTs specific dividend */
363
364 struct board_ops *bd_ops;
365
366 /* /proc/<board> entries */
367 struct proc_dir_entry *proc_entry_pointer;
368 struct dgnc_proc_entry *dgnc_board_table;
369
370};
371
372
373/************************************************************************
374 * Unit flag definitions for un_flags.
375 ************************************************************************/
376#define UN_ISOPEN 0x0001 /* Device is open */
377#define UN_CLOSING 0x0002 /* Line is being closed */
378#define UN_IMM 0x0004 /* Service immediately */
379#define UN_BUSY 0x0008 /* Some work this channel */
380#define UN_BREAKI 0x0010 /* Input break received */
381#define UN_PWAIT 0x0020 /* Printer waiting for terminal */
382#define UN_TIME 0x0040 /* Waiting on time */
383#define UN_EMPTY 0x0080 /* Waiting output queue empty */
384#define UN_LOW 0x0100 /* Waiting output low water mark*/
385#define UN_EXCL_OPEN 0x0200 /* Open for exclusive use */
386#define UN_WOPEN 0x0400 /* Device waiting for open */
387#define UN_WIOCTL 0x0800 /* Device waiting for open */
388#define UN_HANGUP 0x8000 /* Carrier lost */
389
390struct device;
391
392/************************************************************************
393 * Structure for terminal or printer unit.
394 ************************************************************************/
395struct un_t {
396 int magic; /* Unit Magic Number. */
397 struct channel_t *un_ch;
398 ulong un_time;
399 uint un_type;
400 uint un_open_count; /* Counter of opens to port */
401 struct tty_struct *un_tty;/* Pointer to unit tty structure */
402 uint un_flags; /* Unit flags */
403 wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
404 uint un_dev; /* Minor device number */
405 struct device *un_sysfs;
406};
407
408
409/************************************************************************
410 * Device flag definitions for ch_flags.
411 ************************************************************************/
412#define CH_PRON 0x0001 /* Printer on string */
413#define CH_STOP 0x0002 /* Output is stopped */
414#define CH_STOPI 0x0004 /* Input is stopped */
415#define CH_CD 0x0008 /* Carrier is present */
416#define CH_FCAR 0x0010 /* Carrier forced on */
417#define CH_HANGUP 0x0020 /* Hangup received */
418
419#define CH_RECEIVER_OFF 0x0040 /* Receiver is off */
420#define CH_OPENING 0x0080 /* Port in fragile open state */
421#define CH_CLOSING 0x0100 /* Port in fragile close state */
422#define CH_FIFO_ENABLED 0x0200 /* Port has FIFOs enabled */
423#define CH_TX_FIFO_EMPTY 0x0400 /* TX Fifo is completely empty */
424#define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */
425#define CH_BREAK_SENDING 0x1000 /* Break is being sent */
426#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */
427#define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */
428#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */
429#define CH_FORCED_STOP 0x20000 /* Output is forcibly stopped */
430#define CH_FORCED_STOPI 0x40000 /* Input is forcibly stopped */
431
432/*
433 * Definitions for ch_sniff_flags
434 */
435#define SNIFF_OPEN 0x1
436#define SNIFF_WAIT_DATA 0x2
437#define SNIFF_WAIT_SPACE 0x4
438
439
440/* Our Read/Error/Write queue sizes */
441#define RQUEUEMASK 0x1FFF /* 8 K - 1 */
442#define EQUEUEMASK 0x1FFF /* 8 K - 1 */
443#define WQUEUEMASK 0x0FFF /* 4 K - 1 */
444#define RQUEUESIZE (RQUEUEMASK + 1)
445#define EQUEUESIZE RQUEUESIZE
446#define WQUEUESIZE (WQUEUEMASK + 1)
447
448
449/************************************************************************
450 * Channel information structure.
451 ************************************************************************/
452struct channel_t {
453 int magic; /* Channel Magic Number */
454 struct board_t *ch_bd; /* Board structure pointer */
455 struct digi_t ch_digi; /* Transparent Print structure */
456 struct un_t ch_tun; /* Terminal unit info */
457 struct un_t ch_pun; /* Printer unit info */
458
459 spinlock_t ch_lock; /* provide for serialization */
460 wait_queue_head_t ch_flags_wait;
461
462 uint ch_portnum; /* Port number, 0 offset. */
463 uint ch_open_count; /* open count */
464 uint ch_flags; /* Channel flags */
465
466 ulong ch_close_delay; /* How long we should drop RTS/DTR for */
467
468 ulong ch_cpstime; /* Time for CPS calculations */
469
470 tcflag_t ch_c_iflag; /* channel iflags */
471 tcflag_t ch_c_cflag; /* channel cflags */
472 tcflag_t ch_c_oflag; /* channel oflags */
473 tcflag_t ch_c_lflag; /* channel lflags */
474 uchar ch_stopc; /* Stop character */
475 uchar ch_startc; /* Start character */
476
477 uint ch_old_baud; /* Cache of the current baud */
478 uint ch_custom_speed;/* Custom baud, if set */
479
480 uint ch_wopen; /* Waiting for open process cnt */
481
482 uchar ch_mostat; /* FEP output modem status */
483 uchar ch_mistat; /* FEP input modem status */
484
485 struct neo_uart_struct *ch_neo_uart; /* Pointer to the "mapped" UART struct */
486 struct cls_uart_struct *ch_cls_uart; /* Pointer to the "mapped" UART struct */
487
488 uchar ch_cached_lsr; /* Cached value of the LSR register */
489
490 uchar *ch_rqueue; /* Our read queue buffer - malloc'ed */
491 ushort ch_r_head; /* Head location of the read queue */
492 ushort ch_r_tail; /* Tail location of the read queue */
493
494 uchar *ch_equeue; /* Our error queue buffer - malloc'ed */
495 ushort ch_e_head; /* Head location of the error queue */
496 ushort ch_e_tail; /* Tail location of the error queue */
497
498 uchar *ch_wqueue; /* Our write queue buffer - malloc'ed */
499 ushort ch_w_head; /* Head location of the write queue */
500 ushort ch_w_tail; /* Tail location of the write queue */
501
502 ulong ch_rxcount; /* total of data received so far */
503 ulong ch_txcount; /* total of data transmitted so far */
504
505 uchar ch_r_tlevel; /* Receive Trigger level */
506 uchar ch_t_tlevel; /* Transmit Trigger level */
507
508 uchar ch_r_watermark; /* Receive Watermark */
509
510 ulong ch_stop_sending_break; /* Time we should STOP sending a break */
511
512 uint ch_stops_sent; /* How many times I have sent a stop character
513 * to try to stop the other guy sending.
514 */
515 ulong ch_err_parity; /* Count of parity errors on channel */
516 ulong ch_err_frame; /* Count of framing errors on channel */
517 ulong ch_err_break; /* Count of breaks on channel */
518 ulong ch_err_overrun; /* Count of overruns on channel */
519
520 ulong ch_xon_sends; /* Count of xons transmitted */
521 ulong ch_xoff_sends; /* Count of xoffs transmitted */
522
523 ulong ch_intr_modem; /* Count of interrupts */
524 ulong ch_intr_tx; /* Count of interrupts */
525 ulong ch_intr_rx; /* Count of interrupts */
526
527
528 /* /proc/<board>/<channel> entries */
529 struct proc_dir_entry *proc_entry_pointer;
530 struct dgnc_proc_entry *dgnc_channel_table;
531
532 uint ch_sniff_in;
533 uint ch_sniff_out;
534 char *ch_sniff_buf; /* Sniff buffer for proc */
535 ulong ch_sniff_flags; /* Channel flags */
536 wait_queue_head_t ch_sniff_wait;
537};
538
539
540/*************************************************************************
541 *
542 * Prototypes for non-static functions used in more than one module
543 *
544 *************************************************************************/
545
546extern int dgnc_ms_sleep(ulong ms);
547extern void *dgnc_driver_kzmalloc(size_t size, int priority);
548extern char *dgnc_ioctl_name(int cmd);
549
550/*
551 * Our Global Variables.
552 */
553extern int dgnc_driver_state; /* The state of the driver */
554extern uint dgnc_Major; /* Our driver/mgmt major */
555extern int dgnc_debug; /* Debug variable */
556extern int dgnc_rawreadok; /* Set if user wants rawreads */
557extern int dgnc_poll_tick; /* Poll interval - 20 ms */
558extern int dgnc_trcbuf_size; /* Size of the ringbuffer */
559extern spinlock_t dgnc_global_lock; /* Driver global spinlock */
560extern uint dgnc_NumBoards; /* Total number of boards */
561extern struct board_t *dgnc_Board[MAXBOARDS]; /* Array of board structs */
562extern ulong dgnc_poll_counter; /* Times the poller has run */
563extern char *dgnc_state_text[]; /* Array of state text */
564extern char *dgnc_driver_state_text[];/* Array of driver state text */
565
566#endif
diff --git a/drivers/staging/dgnc/dgnc_kcompat.h b/drivers/staging/dgnc/dgnc_kcompat.h
new file mode 100644
index 000000000000..3f69e1dddcaf
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_kcompat.h
@@ -0,0 +1,91 @@
1/*
2 * Copyright 2004 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 *
21 *************************************************************************
22 *
23 * This file is intended to contain all the kernel "differences" between the
24 * various kernels that we support.
25 *
26 *************************************************************************/
27
28#ifndef __DGNC_KCOMPAT_H
29#define __DGNC_KCOMPAT_H
30
31# ifndef KERNEL_VERSION
32# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
33# endif
34
35
36#if !defined(TTY_FLIPBUF_SIZE)
37# define TTY_FLIPBUF_SIZE 512
38#endif
39
40
41/* Sparse stuff */
42# ifndef __user
43# define __user
44# define __kernel
45# define __safe
46# define __force
47# define __chk_user_ptr(x) (void)0
48# endif
49
50
51# define PARM_STR(VAR, INIT, PERM, DESC) \
52 static char *VAR = INIT; \
53 char *dgnc_##VAR; \
54 module_param(VAR, charp, PERM); \
55 MODULE_PARM_DESC(VAR, DESC);
56
57# define PARM_INT(VAR, INIT, PERM, DESC) \
58 static int VAR = INIT; \
59 int dgnc_##VAR; \
60 module_param(VAR, int, PERM); \
61 MODULE_PARM_DESC(VAR, DESC);
62
63# define PARM_ULONG(VAR, INIT, PERM, DESC) \
64 static ulong VAR = INIT; \
65 ulong dgnc_##VAR; \
66 module_param(VAR, long, PERM); \
67 MODULE_PARM_DESC(VAR, DESC);
68
69
70
71
72
73#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
74
75
76
77/* NOTHING YET */
78
79
80
81# else
82
83
84
85# error "this driver does not support anything below the 2.6.27 kernel series."
86
87
88
89# endif
90
91#endif /* ! __DGNC_KCOMPAT_H */
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c
new file mode 100644
index 000000000000..b8e47920111d
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_mgmt.c
@@ -0,0 +1,313 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 */
31
32/************************************************************************
33 *
34 * This file implements the mgmt functionality for the
35 * Neo and ClassicBoard based product lines.
36 *
37 ************************************************************************
38 * $Id: dgnc_mgmt.c,v 1.2 2010/12/14 20:08:29 markh Exp $
39 */
40#include <linux/kernel.h>
41#include <linux/version.h>
42#include <linux/ctype.h>
43#include <linux/sched.h> /* For jiffies, task states */
44#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
45#include <linux/serial_reg.h>
46#include <linux/termios.h>
47#include <asm/uaccess.h> /* For copy_from_user/copy_to_user */
48
49#include "dgnc_driver.h"
50#include "dgnc_pci.h"
51#include "dgnc_proc.h"
52#include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */
53#include "dgnc_mgmt.h"
54#include "dpacompat.h"
55
56
57/* Our "in use" variables, to enforce 1 open only */
58static int dgnc_mgmt_in_use[MAXMGMTDEVICES];
59
60
61/*
62 * dgnc_mgmt_open()
63 *
64 * Open the mgmt/downld/dpa device
65 */
66int dgnc_mgmt_open(struct inode *inode, struct file *file)
67{
68 unsigned long lock_flags;
69 unsigned int minor = iminor(inode);
70
71 DPR_MGMT(("dgnc_mgmt_open start.\n"));
72
73 DGNC_LOCK(dgnc_global_lock, lock_flags);
74
75 /* mgmt device */
76 if (minor < MAXMGMTDEVICES) {
77 /* Only allow 1 open at a time on mgmt device */
78 if (dgnc_mgmt_in_use[minor]) {
79 DGNC_UNLOCK(dgnc_global_lock, lock_flags);
80 return (-EBUSY);
81 }
82 dgnc_mgmt_in_use[minor]++;
83 }
84 else {
85 DGNC_UNLOCK(dgnc_global_lock, lock_flags);
86 return (-ENXIO);
87 }
88
89 DGNC_UNLOCK(dgnc_global_lock, lock_flags);
90
91 DPR_MGMT(("dgnc_mgmt_open finish.\n"));
92
93 return 0;
94}
95
96
97/*
98 * dgnc_mgmt_close()
99 *
100 * Open the mgmt/dpa device
101 */
102int dgnc_mgmt_close(struct inode *inode, struct file *file)
103{
104 unsigned long lock_flags;
105 unsigned int minor = iminor(inode);
106
107 DPR_MGMT(("dgnc_mgmt_close start.\n"));
108
109 DGNC_LOCK(dgnc_global_lock, lock_flags);
110
111 /* mgmt device */
112 if (minor < MAXMGMTDEVICES) {
113 if (dgnc_mgmt_in_use[minor]) {
114 dgnc_mgmt_in_use[minor] = 0;
115 }
116 }
117 DGNC_UNLOCK(dgnc_global_lock, lock_flags);
118
119 DPR_MGMT(("dgnc_mgmt_close finish.\n"));
120
121 return 0;
122}
123
124
125/*
126 * dgnc_mgmt_ioctl()
127 *
128 * ioctl the mgmt/dpa device
129 */
130#ifdef HAVE_UNLOCKED_IOCTL
131long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
132{
133 struct inode *inode = file->f_dentry->d_inode;
134#else
135int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
136{
137#endif
138 unsigned long lock_flags;
139 void __user *uarg = (void __user *) arg;
140
141 DPR_MGMT(("dgnc_mgmt_ioctl start.\n"));
142
143 switch (cmd) {
144
145 case DIGI_GETDD:
146 {
147 /*
148 * This returns the total number of boards
149 * in the system, as well as driver version
150 * and has space for a reserved entry
151 */
152 struct digi_dinfo ddi;
153
154 DGNC_LOCK(dgnc_global_lock, lock_flags);
155
156 ddi.dinfo_nboards = dgnc_NumBoards;
157 sprintf(ddi.dinfo_version, "%s", DG_PART);
158
159 DGNC_UNLOCK(dgnc_global_lock, lock_flags);
160
161 DPR_MGMT(("DIGI_GETDD returning numboards: %d version: %s\n",
162 ddi.dinfo_nboards, ddi.dinfo_version));
163
164 if (copy_to_user(uarg, &ddi, sizeof (ddi)))
165 return(-EFAULT);
166
167 break;
168 }
169
170 case DIGI_GETBD:
171 {
172 int brd;
173
174 struct digi_info di;
175
176 if (copy_from_user(&brd, uarg, sizeof(int))) {
177 return(-EFAULT);
178 }
179
180 DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd));
181
182 if ((brd < 0) || (brd > dgnc_NumBoards) || (dgnc_NumBoards == 0))
183 return (-ENODEV);
184
185 memset(&di, 0, sizeof(di));
186
187 di.info_bdnum = brd;
188
189 DGNC_LOCK(dgnc_Board[brd]->bd_lock, lock_flags);
190
191 di.info_bdtype = dgnc_Board[brd]->dpatype;
192 di.info_bdstate = dgnc_Board[brd]->dpastatus;
193 di.info_ioport = 0;
194 di.info_physaddr = (ulong) dgnc_Board[brd]->membase;
195 di.info_physsize = (ulong) dgnc_Board[brd]->membase - dgnc_Board[brd]->membase_end;
196 if (dgnc_Board[brd]->state != BOARD_FAILED)
197 di.info_nports = dgnc_Board[brd]->nasync;
198 else
199 di.info_nports = 0;
200
201 DGNC_UNLOCK(dgnc_Board[brd]->bd_lock, lock_flags);
202
203 DPR_MGMT(("DIGI_GETBD returning type: %x state: %x ports: %x size: %x\n",
204 di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize));
205
206 if (copy_to_user(uarg, &di, sizeof (di)))
207 return (-EFAULT);
208
209 break;
210 }
211
212 case DIGI_GET_NI_INFO:
213 {
214 struct channel_t *ch;
215 struct ni_info ni;
216 uchar mstat = 0;
217 uint board = 0;
218 uint channel = 0;
219
220 if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) {
221 return(-EFAULT);
222 }
223
224 DPR_MGMT(("DIGI_GETBD asking about board: %d channel: %d\n",
225 ni.board, ni.channel));
226
227 board = ni.board;
228 channel = ni.channel;
229
230 /* Verify boundaries on board */
231 if ((board < 0) || (board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
232 return (-ENODEV);
233
234 /* Verify boundaries on channel */
235 if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
236 return (-ENODEV);
237
238 ch = dgnc_Board[board]->channels[channel];
239
240 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
241 return (-ENODEV);
242
243 memset(&ni, 0, sizeof(ni));
244 ni.board = board;
245 ni.channel = channel;
246
247 DGNC_LOCK(ch->ch_lock, lock_flags);
248
249 mstat = (ch->ch_mostat | ch->ch_mistat);
250
251 if (mstat & UART_MCR_DTR) {
252 ni.mstat |= TIOCM_DTR;
253 ni.dtr = TIOCM_DTR;
254 }
255 if (mstat & UART_MCR_RTS) {
256 ni.mstat |= TIOCM_RTS;
257 ni.rts = TIOCM_RTS;
258 }
259 if (mstat & UART_MSR_CTS) {
260 ni.mstat |= TIOCM_CTS;
261 ni.cts = TIOCM_CTS;
262 }
263 if (mstat & UART_MSR_RI) {
264 ni.mstat |= TIOCM_RI;
265 ni.ri = TIOCM_RI;
266 }
267 if (mstat & UART_MSR_DCD) {
268 ni.mstat |= TIOCM_CD;
269 ni.dcd = TIOCM_CD;
270 }
271 if (mstat & UART_MSR_DSR)
272 ni.mstat |= TIOCM_DSR;
273
274 ni.iflag = ch->ch_c_iflag;
275 ni.oflag = ch->ch_c_oflag;
276 ni.cflag = ch->ch_c_cflag;
277 ni.lflag = ch->ch_c_lflag;
278
279 if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS)
280 ni.hflow = 1;
281 else
282 ni.hflow = 0;
283
284 if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI))
285 ni.recv_stopped = 1;
286 else
287 ni.recv_stopped = 0;
288
289 if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP))
290 ni.xmit_stopped = 1;
291 else
292 ni.xmit_stopped = 0;
293
294 ni.curtx = ch->ch_txcount;
295 ni.currx = ch->ch_rxcount;
296
297 ni.baud = ch->ch_old_baud;
298
299 DGNC_UNLOCK(ch->ch_lock, lock_flags);
300
301 if (copy_to_user(uarg, &ni, sizeof(ni)))
302 return (-EFAULT);
303
304 break;
305 }
306
307
308 }
309
310 DPR_MGMT(("dgnc_mgmt_ioctl finish.\n"));
311
312 return 0;
313}
diff --git a/drivers/staging/dgnc/dgnc_mgmt.h b/drivers/staging/dgnc/dgnc_mgmt.h
new file mode 100644
index 000000000000..a0d1338ee545
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_mgmt.h
@@ -0,0 +1,37 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 */
21
22#ifndef __DGNC_MGMT_H
23#define __DGNC_MGMT_H
24
25#define MAXMGMTDEVICES 8
26
27int dgnc_mgmt_open(struct inode *inode, struct file *file);
28int dgnc_mgmt_close(struct inode *inode, struct file *file);
29
30#ifdef HAVE_UNLOCKED_IOCTL
31long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
32#else
33int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
34#endif
35
36#endif
37
diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c
new file mode 100644
index 000000000000..503db8fae166
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_neo.c
@@ -0,0 +1,1977 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 *
31 * $Id: dgnc_neo.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
32 */
33
34
35#include <linux/kernel.h>
36#include <linux/version.h>
37#include <linux/sched.h> /* For jiffies, task states */
38#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
39#include <linux/delay.h> /* For udelay */
40#include <asm/io.h> /* For read[bwl]/write[bwl] */
41#include <linux/serial.h> /* For struct async_serial */
42#include <linux/serial_reg.h> /* For the various UART offsets */
43
44#include "dgnc_driver.h" /* Driver main header file */
45#include "dgnc_neo.h" /* Our header file */
46#include "dgnc_tty.h"
47#include "dgnc_trace.h"
48
49static inline void neo_parse_lsr(struct board_t *brd, uint port);
50static inline void neo_parse_isr(struct board_t *brd, uint port);
51static void neo_copy_data_from_uart_to_queue(struct channel_t *ch);
52static inline void neo_clear_break(struct channel_t *ch, int force);
53static inline void neo_set_cts_flow_control(struct channel_t *ch);
54static inline void neo_set_rts_flow_control(struct channel_t *ch);
55static inline void neo_set_ixon_flow_control(struct channel_t *ch);
56static inline void neo_set_ixoff_flow_control(struct channel_t *ch);
57static inline void neo_set_no_output_flow_control(struct channel_t *ch);
58static inline void neo_set_no_input_flow_control(struct channel_t *ch);
59static inline void neo_set_new_start_stop_chars(struct channel_t *ch);
60static void neo_parse_modem(struct channel_t *ch, uchar signals);
61static void neo_tasklet(unsigned long data);
62static void neo_vpd(struct board_t *brd);
63static void neo_uart_init(struct channel_t *ch);
64static void neo_uart_off(struct channel_t *ch);
65static int neo_drain(struct tty_struct *tty, uint seconds);
66static void neo_param(struct tty_struct *tty);
67static void neo_assert_modem_signals(struct channel_t *ch);
68static void neo_flush_uart_write(struct channel_t *ch);
69static void neo_flush_uart_read(struct channel_t *ch);
70static void neo_disable_receiver(struct channel_t *ch);
71static void neo_enable_receiver(struct channel_t *ch);
72static void neo_send_break(struct channel_t *ch, int msecs);
73static void neo_send_start_character(struct channel_t *ch);
74static void neo_send_stop_character(struct channel_t *ch);
75static void neo_copy_data_from_queue_to_uart(struct channel_t *ch);
76static uint neo_get_uart_bytes_left(struct channel_t *ch);
77static void neo_send_immediate_char(struct channel_t *ch, unsigned char c);
78static irqreturn_t neo_intr(int irq, void *voidbrd);
79
80
81struct board_ops dgnc_neo_ops = {
82 .tasklet = neo_tasklet,
83 .intr = neo_intr,
84 .uart_init = neo_uart_init,
85 .uart_off = neo_uart_off,
86 .drain = neo_drain,
87 .param = neo_param,
88 .vpd = neo_vpd,
89 .assert_modem_signals = neo_assert_modem_signals,
90 .flush_uart_write = neo_flush_uart_write,
91 .flush_uart_read = neo_flush_uart_read,
92 .disable_receiver = neo_disable_receiver,
93 .enable_receiver = neo_enable_receiver,
94 .send_break = neo_send_break,
95 .send_start_character = neo_send_start_character,
96 .send_stop_character = neo_send_stop_character,
97 .copy_data_from_queue_to_uart = neo_copy_data_from_queue_to_uart,
98 .get_uart_bytes_left = neo_get_uart_bytes_left,
99 .send_immediate_char = neo_send_immediate_char
100};
101
102static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
103
104
105/*
106 * This function allows calls to ensure that all outstanding
107 * PCI writes have been completed, by doing a PCI read against
108 * a non-destructive, read-only location on the Neo card.
109 *
110 * In this case, we are reading the DVID (Read-only Device Identification)
111 * value of the Neo card.
112 */
113static inline void neo_pci_posting_flush(struct board_t *bd)
114{
115 readb(bd->re_map_membase + 0x8D);
116}
117
118static inline void neo_set_cts_flow_control(struct channel_t *ch)
119{
120 uchar ier = readb(&ch->ch_neo_uart->ier);
121 uchar efr = readb(&ch->ch_neo_uart->efr);
122
123
124 DPR_PARAM(("Setting CTSFLOW\n"));
125
126 /* Turn on auto CTS flow control */
127#if 1
128 ier |= (UART_17158_IER_CTSDSR);
129#else
130 ier &= ~(UART_17158_IER_CTSDSR);
131#endif
132
133 efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
134
135 /* Turn off auto Xon flow control */
136 efr &= ~(UART_17158_EFR_IXON);
137
138 /* Why? Becuz Exar's spec says we have to zero it out before setting it */
139 writeb(0, &ch->ch_neo_uart->efr);
140
141 /* Turn on UART enhanced bits */
142 writeb(efr, &ch->ch_neo_uart->efr);
143
144 /* Turn on table D, with 8 char hi/low watermarks */
145 writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
146
147 /* Feed the UART our trigger levels */
148 writeb(8, &ch->ch_neo_uart->tfifo);
149 ch->ch_t_tlevel = 8;
150
151 writeb(ier, &ch->ch_neo_uart->ier);
152
153 neo_pci_posting_flush(ch->ch_bd);
154}
155
156
157static inline void neo_set_rts_flow_control(struct channel_t *ch)
158{
159 uchar ier = readb(&ch->ch_neo_uart->ier);
160 uchar efr = readb(&ch->ch_neo_uart->efr);
161
162 DPR_PARAM(("Setting RTSFLOW\n"));
163
164 /* Turn on auto RTS flow control */
165#if 1
166 ier |= (UART_17158_IER_RTSDTR);
167#else
168 ier &= ~(UART_17158_IER_RTSDTR);
169#endif
170 efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
171
172 /* Turn off auto Xoff flow control */
173 ier &= ~(UART_17158_IER_XOFF);
174 efr &= ~(UART_17158_EFR_IXOFF);
175
176 /* Why? Becuz Exar's spec says we have to zero it out before setting it */
177 writeb(0, &ch->ch_neo_uart->efr);
178
179 /* Turn on UART enhanced bits */
180 writeb(efr, &ch->ch_neo_uart->efr);
181
182 writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
183 ch->ch_r_watermark = 4;
184
185 writeb(32, &ch->ch_neo_uart->rfifo);
186 ch->ch_r_tlevel = 32;
187
188 writeb(ier, &ch->ch_neo_uart->ier);
189
190 /*
191 * From the Neo UART spec sheet:
192 * The auto RTS/DTR function must be started by asserting
193 * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
194 * it is enabled.
195 */
196 ch->ch_mostat |= (UART_MCR_RTS);
197
198 neo_pci_posting_flush(ch->ch_bd);
199}
200
201
202static inline void neo_set_ixon_flow_control(struct channel_t *ch)
203{
204 uchar ier = readb(&ch->ch_neo_uart->ier);
205 uchar efr = readb(&ch->ch_neo_uart->efr);
206
207 DPR_PARAM(("Setting IXON FLOW\n"));
208
209 /* Turn off auto CTS flow control */
210 ier &= ~(UART_17158_IER_CTSDSR);
211 efr &= ~(UART_17158_EFR_CTSDSR);
212
213 /* Turn on auto Xon flow control */
214 efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
215
216 /* Why? Becuz Exar's spec says we have to zero it out before setting it */
217 writeb(0, &ch->ch_neo_uart->efr);
218
219 /* Turn on UART enhanced bits */
220 writeb(efr, &ch->ch_neo_uart->efr);
221
222 writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
223 ch->ch_r_watermark = 4;
224
225 writeb(32, &ch->ch_neo_uart->rfifo);
226 ch->ch_r_tlevel = 32;
227
228 /* Tell UART what start/stop chars it should be looking for */
229 writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
230 writeb(0, &ch->ch_neo_uart->xonchar2);
231
232 writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
233 writeb(0, &ch->ch_neo_uart->xoffchar2);
234
235 writeb(ier, &ch->ch_neo_uart->ier);
236
237 neo_pci_posting_flush(ch->ch_bd);
238}
239
240
241static inline void neo_set_ixoff_flow_control(struct channel_t *ch)
242{
243 uchar ier = readb(&ch->ch_neo_uart->ier);
244 uchar efr = readb(&ch->ch_neo_uart->efr);
245
246 DPR_PARAM(("Setting IXOFF FLOW\n"));
247
248 /* Turn off auto RTS flow control */
249 ier &= ~(UART_17158_IER_RTSDTR);
250 efr &= ~(UART_17158_EFR_RTSDTR);
251
252 /* Turn on auto Xoff flow control */
253 ier |= (UART_17158_IER_XOFF);
254 efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
255
256 /* Why? Becuz Exar's spec says we have to zero it out before setting it */
257 writeb(0, &ch->ch_neo_uart->efr);
258
259 /* Turn on UART enhanced bits */
260 writeb(efr, &ch->ch_neo_uart->efr);
261
262 /* Turn on table D, with 8 char hi/low watermarks */
263 writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
264
265 writeb(8, &ch->ch_neo_uart->tfifo);
266 ch->ch_t_tlevel = 8;
267
268 /* Tell UART what start/stop chars it should be looking for */
269 writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
270 writeb(0, &ch->ch_neo_uart->xonchar2);
271
272 writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
273 writeb(0, &ch->ch_neo_uart->xoffchar2);
274
275 writeb(ier, &ch->ch_neo_uart->ier);
276
277 neo_pci_posting_flush(ch->ch_bd);
278}
279
280
281static inline void neo_set_no_input_flow_control(struct channel_t *ch)
282{
283 uchar ier = readb(&ch->ch_neo_uart->ier);
284 uchar efr = readb(&ch->ch_neo_uart->efr);
285
286 DPR_PARAM(("Unsetting Input FLOW\n"));
287
288 /* Turn off auto RTS flow control */
289 ier &= ~(UART_17158_IER_RTSDTR);
290 efr &= ~(UART_17158_EFR_RTSDTR);
291
292 /* Turn off auto Xoff flow control */
293 ier &= ~(UART_17158_IER_XOFF);
294 if (ch->ch_c_iflag & IXON)
295 efr &= ~(UART_17158_EFR_IXOFF);
296 else
297 efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
298
299
300 /* Why? Becuz Exar's spec says we have to zero it out before setting it */
301 writeb(0, &ch->ch_neo_uart->efr);
302
303 /* Turn on UART enhanced bits */
304 writeb(efr, &ch->ch_neo_uart->efr);
305
306 /* Turn on table D, with 8 char hi/low watermarks */
307 writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
308
309 ch->ch_r_watermark = 0;
310
311 writeb(16, &ch->ch_neo_uart->tfifo);
312 ch->ch_t_tlevel = 16;
313
314 writeb(16, &ch->ch_neo_uart->rfifo);
315 ch->ch_r_tlevel = 16;
316
317 writeb(ier, &ch->ch_neo_uart->ier);
318
319 neo_pci_posting_flush(ch->ch_bd);
320}
321
322
323static inline void neo_set_no_output_flow_control(struct channel_t *ch)
324{
325 uchar ier = readb(&ch->ch_neo_uart->ier);
326 uchar efr = readb(&ch->ch_neo_uart->efr);
327
328 DPR_PARAM(("Unsetting Output FLOW\n"));
329
330 /* Turn off auto CTS flow control */
331 ier &= ~(UART_17158_IER_CTSDSR);
332 efr &= ~(UART_17158_EFR_CTSDSR);
333
334 /* Turn off auto Xon flow control */
335 if (ch->ch_c_iflag & IXOFF)
336 efr &= ~(UART_17158_EFR_IXON);
337 else
338 efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
339
340 /* Why? Becuz Exar's spec says we have to zero it out before setting it */
341 writeb(0, &ch->ch_neo_uart->efr);
342
343 /* Turn on UART enhanced bits */
344 writeb(efr, &ch->ch_neo_uart->efr);
345
346 /* Turn on table D, with 8 char hi/low watermarks */
347 writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
348
349 ch->ch_r_watermark = 0;
350
351 writeb(16, &ch->ch_neo_uart->tfifo);
352 ch->ch_t_tlevel = 16;
353
354 writeb(16, &ch->ch_neo_uart->rfifo);
355 ch->ch_r_tlevel = 16;
356
357 writeb(ier, &ch->ch_neo_uart->ier);
358
359 neo_pci_posting_flush(ch->ch_bd);
360}
361
362
363/* change UARTs start/stop chars */
364static inline void neo_set_new_start_stop_chars(struct channel_t *ch)
365{
366
367 /* if hardware flow control is set, then skip this whole thing */
368 if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) || ch->ch_c_cflag & CRTSCTS)
369 return;
370
371 DPR_PARAM(("In new start stop chars\n"));
372
373 /* Tell UART what start/stop chars it should be looking for */
374 writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
375 writeb(0, &ch->ch_neo_uart->xonchar2);
376
377 writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
378 writeb(0, &ch->ch_neo_uart->xoffchar2);
379
380 neo_pci_posting_flush(ch->ch_bd);
381}
382
383
384/*
385 * No locks are assumed to be held when calling this function.
386 */
387static inline void neo_clear_break(struct channel_t *ch, int force)
388{
389 ulong lock_flags;
390
391 DGNC_LOCK(ch->ch_lock, lock_flags);
392
393 /* Bail if we aren't currently sending a break. */
394 if (!ch->ch_stop_sending_break) {
395 DGNC_UNLOCK(ch->ch_lock, lock_flags);
396 return;
397 }
398
399 /* Turn break off, and unset some variables */
400 if (ch->ch_flags & CH_BREAK_SENDING) {
401 if ((jiffies >= ch->ch_stop_sending_break) || force) {
402 uchar temp = readb(&ch->ch_neo_uart->lcr);
403 writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
404 neo_pci_posting_flush(ch->ch_bd);
405 ch->ch_flags &= ~(CH_BREAK_SENDING);
406 ch->ch_stop_sending_break = 0;
407 DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
408 }
409 }
410 DGNC_UNLOCK(ch->ch_lock, lock_flags);
411}
412
413
414/*
415 * Parse the ISR register.
416 */
417static inline void neo_parse_isr(struct board_t *brd, uint port)
418{
419 struct channel_t *ch;
420 uchar isr;
421 uchar cause;
422 ulong lock_flags;
423
424 if (!brd || brd->magic != DGNC_BOARD_MAGIC)
425 return;
426
427 if (port > brd->maxports)
428 return;
429
430 ch = brd->channels[port];
431 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
432 return;
433
434 /* Here we try to figure out what caused the interrupt to happen */
435 while (1) {
436
437 isr = readb(&ch->ch_neo_uart->isr_fcr);
438
439 /* Bail if no pending interrupt */
440 if (isr & UART_IIR_NO_INT) {
441 break;
442 }
443
444 /*
445 * Yank off the upper 2 bits, which just show that the FIFO's are enabled.
446 */
447 isr &= ~(UART_17158_IIR_FIFO_ENABLED);
448
449 DPR_INTR(("%s:%d isr: %x\n", __FILE__, __LINE__, isr));
450
451 if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
452 /* Read data from uart -> queue */
453 brd->intr_rx++;
454 ch->ch_intr_rx++;
455 neo_copy_data_from_uart_to_queue(ch);
456
457 /* Call our tty layer to enforce queue flow control if needed. */
458 DGNC_LOCK(ch->ch_lock, lock_flags);
459 dgnc_check_queue_flow_control(ch);
460 DGNC_UNLOCK(ch->ch_lock, lock_flags);
461 }
462
463 if (isr & UART_IIR_THRI) {
464 brd->intr_tx++;
465 ch->ch_intr_tx++;
466 /* Transfer data (if any) from Write Queue -> UART. */
467 DGNC_LOCK(ch->ch_lock, lock_flags);
468 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
469 DGNC_UNLOCK(ch->ch_lock, lock_flags);
470 neo_copy_data_from_queue_to_uart(ch);
471 }
472
473 if (isr & UART_17158_IIR_XONXOFF) {
474 cause = readb(&ch->ch_neo_uart->xoffchar1);
475
476 DPR_INTR(("Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause));
477
478 /*
479 * Since the UART detected either an XON or
480 * XOFF match, we need to figure out which
481 * one it was, so we can suspend or resume data flow.
482 */
483 if (cause == UART_17158_XON_DETECT) {
484 /* Is output stopped right now, if so, resume it */
485 if (brd->channels[port]->ch_flags & CH_STOP) {
486 DGNC_LOCK(ch->ch_lock, lock_flags);
487 ch->ch_flags &= ~(CH_STOP);
488 DGNC_UNLOCK(ch->ch_lock, lock_flags);
489 }
490 DPR_INTR(("Port %d. XON detected in incoming data\n", port));
491 }
492 else if (cause == UART_17158_XOFF_DETECT) {
493 if (!(brd->channels[port]->ch_flags & CH_STOP)) {
494 DGNC_LOCK(ch->ch_lock, lock_flags);
495 ch->ch_flags |= CH_STOP;
496 DGNC_UNLOCK(ch->ch_lock, lock_flags);
497 DPR_INTR(("Setting CH_STOP\n"));
498 }
499 DPR_INTR(("Port: %d. XOFF detected in incoming data\n", port));
500 }
501 }
502
503 if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
504 /*
505 * If we get here, this means the hardware is doing auto flow control.
506 * Check to see whether RTS/DTR or CTS/DSR caused this interrupt.
507 */
508 brd->intr_modem++;
509 ch->ch_intr_modem++;
510 cause = readb(&ch->ch_neo_uart->mcr);
511 /* Which pin is doing auto flow? RTS or DTR? */
512 if ((cause & 0x4) == 0) {
513 if (cause & UART_MCR_RTS) {
514 DGNC_LOCK(ch->ch_lock, lock_flags);
515 ch->ch_mostat |= UART_MCR_RTS;
516 DGNC_UNLOCK(ch->ch_lock, lock_flags);
517 }
518 else {
519 DGNC_LOCK(ch->ch_lock, lock_flags);
520 ch->ch_mostat &= ~(UART_MCR_RTS);
521 DGNC_UNLOCK(ch->ch_lock, lock_flags);
522 }
523 } else {
524 if (cause & UART_MCR_DTR) {
525 DGNC_LOCK(ch->ch_lock, lock_flags);
526 ch->ch_mostat |= UART_MCR_DTR;
527 DGNC_UNLOCK(ch->ch_lock, lock_flags);
528 }
529 else {
530 DGNC_LOCK(ch->ch_lock, lock_flags);
531 ch->ch_mostat &= ~(UART_MCR_DTR);
532 DGNC_UNLOCK(ch->ch_lock, lock_flags);
533 }
534 }
535 }
536
537 /* Parse any modem signal changes */
538 DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n"));
539 neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
540 }
541}
542
543
544static inline void neo_parse_lsr(struct board_t *brd, uint port)
545{
546 struct channel_t *ch;
547 int linestatus;
548 ulong lock_flags;
549
550 if (!brd)
551 return;
552
553 if (brd->magic != DGNC_BOARD_MAGIC)
554 return;
555
556 if (port > brd->maxports)
557 return;
558
559 ch = brd->channels[port];
560 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
561 return;
562
563 linestatus = readb(&ch->ch_neo_uart->lsr);
564
565 DPR_INTR(("%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus));
566
567 ch->ch_cached_lsr |= linestatus;
568
569 if (ch->ch_cached_lsr & UART_LSR_DR) {
570 brd->intr_rx++;
571 ch->ch_intr_rx++;
572 /* Read data from uart -> queue */
573 neo_copy_data_from_uart_to_queue(ch);
574 DGNC_LOCK(ch->ch_lock, lock_flags);
575 dgnc_check_queue_flow_control(ch);
576 DGNC_UNLOCK(ch->ch_lock, lock_flags);
577 }
578
579 /*
580 * This is a special flag. It indicates that at least 1
581 * RX error (parity, framing, or break) has happened.
582 * Mark this in our struct, which will tell me that I have
583 *to do the special RX+LSR read for this FIFO load.
584 */
585 if (linestatus & UART_17158_RX_FIFO_DATA_ERROR) {
586 DPR_INTR(("%s:%d Port: %d Got an RX error, need to parse LSR\n",
587 __FILE__, __LINE__, port));
588 }
589
590 /*
591 * The next 3 tests should *NOT* happen, as the above test
592 * should encapsulate all 3... At least, thats what Exar says.
593 */
594
595 if (linestatus & UART_LSR_PE) {
596 ch->ch_err_parity++;
597 DPR_INTR(("%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port));
598 }
599
600 if (linestatus & UART_LSR_FE) {
601 ch->ch_err_frame++;
602 DPR_INTR(("%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port));
603 }
604
605 if (linestatus & UART_LSR_BI) {
606 ch->ch_err_break++;
607 DPR_INTR(("%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port));
608 }
609
610 if (linestatus & UART_LSR_OE) {
611 /*
612 * Rx Oruns. Exar says that an orun will NOT corrupt
613 * the FIFO. It will just replace the holding register
614 * with this new data byte. So basically just ignore this.
615 * Probably we should eventually have an orun stat in our driver...
616 */
617 ch->ch_err_overrun++;
618 DPR_INTR(("%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port));
619 }
620
621 if (linestatus & UART_LSR_THRE) {
622 brd->intr_tx++;
623 ch->ch_intr_tx++;
624 DGNC_LOCK(ch->ch_lock, lock_flags);
625 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
626 DGNC_UNLOCK(ch->ch_lock, lock_flags);
627
628 /* Transfer data (if any) from Write Queue -> UART. */
629 neo_copy_data_from_queue_to_uart(ch);
630 }
631 else if (linestatus & UART_17158_TX_AND_FIFO_CLR) {
632 brd->intr_tx++;
633 ch->ch_intr_tx++;
634 DGNC_LOCK(ch->ch_lock, lock_flags);
635 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
636 DGNC_UNLOCK(ch->ch_lock, lock_flags);
637
638 /* Transfer data (if any) from Write Queue -> UART. */
639 neo_copy_data_from_queue_to_uart(ch);
640 }
641}
642
643
644/*
645 * neo_param()
646 * Send any/all changes to the line to the UART.
647 */
648static void neo_param(struct tty_struct *tty)
649{
650 uchar lcr = 0;
651 uchar uart_lcr = 0;
652 uchar ier = 0;
653 uchar uart_ier = 0;
654 uint baud = 9600;
655 int quot = 0;
656 struct board_t *bd;
657 struct channel_t *ch;
658 struct un_t *un;
659
660 if (!tty || tty->magic != TTY_MAGIC) {
661 return;
662 }
663
664 un = (struct un_t *) tty->driver_data;
665 if (!un || un->magic != DGNC_UNIT_MAGIC) {
666 return;
667 }
668
669 ch = un->un_ch;
670 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
671 return;
672 }
673
674 bd = ch->ch_bd;
675 if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
676 return;
677 }
678
679 DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
680 ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
681
682 /*
683 * If baud rate is zero, flush queues, and set mval to drop DTR.
684 */
685 if ((ch->ch_c_cflag & (CBAUD)) == 0) {
686 ch->ch_r_head = ch->ch_r_tail = 0;
687 ch->ch_e_head = ch->ch_e_tail = 0;
688 ch->ch_w_head = ch->ch_w_tail = 0;
689
690 neo_flush_uart_write(ch);
691 neo_flush_uart_read(ch);
692
693 /* The baudrate is B0 so all modem lines are to be dropped. */
694 ch->ch_flags |= (CH_BAUD0);
695 ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
696 neo_assert_modem_signals(ch);
697 ch->ch_old_baud = 0;
698 return;
699
700 } else if (ch->ch_custom_speed) {
701
702 baud = ch->ch_custom_speed;
703 /* Handle transition from B0 */
704 if (ch->ch_flags & CH_BAUD0) {
705 ch->ch_flags &= ~(CH_BAUD0);
706
707 /*
708 * Bring back up RTS and DTR...
709 * Also handle RTS or DTR toggle if set.
710 */
711 if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
712 ch->ch_mostat |= (UART_MCR_RTS);
713 if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
714 ch->ch_mostat |= (UART_MCR_DTR);
715 }
716 } else {
717 int iindex = 0;
718 int jindex = 0;
719
720 ulong bauds[4][16] = {
721 { /* slowbaud */
722 0, 50, 75, 110,
723 134, 150, 200, 300,
724 600, 1200, 1800, 2400,
725 4800, 9600, 19200, 38400 },
726 { /* slowbaud & CBAUDEX */
727 0, 57600, 115200, 230400,
728 460800, 150, 200, 921600,
729 600, 1200, 1800, 2400,
730 4800, 9600, 19200, 38400 },
731 { /* fastbaud */
732 0, 57600, 76800, 115200,
733 131657, 153600, 230400, 460800,
734 921600, 1200, 1800, 2400,
735 4800, 9600, 19200, 38400 },
736 { /* fastbaud & CBAUDEX */
737 0, 57600, 115200, 230400,
738 460800, 150, 200, 921600,
739 600, 1200, 1800, 2400,
740 4800, 9600, 19200, 38400 }
741 };
742
743 /* Only use the TXPrint baud rate if the terminal unit is NOT open */
744 if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT))
745 baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
746 else
747 baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
748
749 if (ch->ch_c_cflag & CBAUDEX)
750 iindex = 1;
751
752 if (ch->ch_digi.digi_flags & DIGI_FAST)
753 iindex += 2;
754
755 jindex = baud;
756
757 if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) {
758 baud = bauds[iindex][jindex];
759 } else {
760 DPR_IOCTL(("baud indices were out of range (%d)(%d)",
761 iindex, jindex));
762 baud = 0;
763 }
764
765 if (baud == 0)
766 baud = 9600;
767
768 /* Handle transition from B0 */
769 if (ch->ch_flags & CH_BAUD0) {
770 ch->ch_flags &= ~(CH_BAUD0);
771
772 /*
773 * Bring back up RTS and DTR...
774 * Also handle RTS or DTR toggle if set.
775 */
776 if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
777 ch->ch_mostat |= (UART_MCR_RTS);
778 if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
779 ch->ch_mostat |= (UART_MCR_DTR);
780 }
781 }
782
783 if (ch->ch_c_cflag & PARENB) {
784 lcr |= UART_LCR_PARITY;
785 }
786
787 if (!(ch->ch_c_cflag & PARODD)) {
788 lcr |= UART_LCR_EPAR;
789 }
790
791 /*
792 * Not all platforms support mark/space parity,
793 * so this will hide behind an ifdef.
794 */
795#ifdef CMSPAR
796 if (ch->ch_c_cflag & CMSPAR)
797 lcr |= UART_LCR_SPAR;
798#endif
799
800 if (ch->ch_c_cflag & CSTOPB)
801 lcr |= UART_LCR_STOP;
802
803 switch (ch->ch_c_cflag & CSIZE) {
804 case CS5:
805 lcr |= UART_LCR_WLEN5;
806 break;
807 case CS6:
808 lcr |= UART_LCR_WLEN6;
809 break;
810 case CS7:
811 lcr |= UART_LCR_WLEN7;
812 break;
813 case CS8:
814 default:
815 lcr |= UART_LCR_WLEN8;
816 break;
817 }
818
819 ier = uart_ier = readb(&ch->ch_neo_uart->ier);
820 uart_lcr = readb(&ch->ch_neo_uart->lcr);
821
822 if (baud == 0)
823 baud = 9600;
824
825 quot = ch->ch_bd->bd_dividend / baud;
826
827 if (quot != 0 && ch->ch_old_baud != baud) {
828 ch->ch_old_baud = baud;
829 writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
830 writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
831 writeb((quot >> 8), &ch->ch_neo_uart->ier);
832 writeb(lcr, &ch->ch_neo_uart->lcr);
833 }
834
835 if (uart_lcr != lcr)
836 writeb(lcr, &ch->ch_neo_uart->lcr);
837
838 if (ch->ch_c_cflag & CREAD) {
839 ier |= (UART_IER_RDI | UART_IER_RLSI);
840 }
841 else {
842 ier &= ~(UART_IER_RDI | UART_IER_RLSI);
843 }
844
845 /*
846 * Have the UART interrupt on modem signal changes ONLY when
847 * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set.
848 */
849 if ((ch->ch_digi.digi_flags & CTSPACE) || (ch->ch_digi.digi_flags & RTSPACE) ||
850 (ch->ch_c_cflag & CRTSCTS) || !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) ||
851 !(ch->ch_c_cflag & CLOCAL))
852 {
853 ier |= UART_IER_MSI;
854 }
855 else {
856 ier &= ~UART_IER_MSI;
857 }
858
859 ier |= UART_IER_THRI;
860
861 if (ier != uart_ier)
862 writeb(ier, &ch->ch_neo_uart->ier);
863
864 /* Set new start/stop chars */
865 neo_set_new_start_stop_chars(ch);
866
867 if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
868 neo_set_cts_flow_control(ch);
869 }
870 else if (ch->ch_c_iflag & IXON) {
871 /* If start/stop is set to disable, then we should disable flow control */
872 if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
873 neo_set_no_output_flow_control(ch);
874 else
875 neo_set_ixon_flow_control(ch);
876 }
877 else {
878 neo_set_no_output_flow_control(ch);
879 }
880
881 if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
882 neo_set_rts_flow_control(ch);
883 }
884 else if (ch->ch_c_iflag & IXOFF) {
885 /* If start/stop is set to disable, then we should disable flow control */
886 if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE))
887 neo_set_no_input_flow_control(ch);
888 else
889 neo_set_ixoff_flow_control(ch);
890 }
891 else {
892 neo_set_no_input_flow_control(ch);
893 }
894
895 /*
896 * Adjust the RX FIFO Trigger level if baud is less than 9600.
897 * Not exactly elegant, but this is needed because of the Exar chip's
898 * delay on firing off the RX FIFO interrupt on slower baud rates.
899 */
900 if (baud < 9600) {
901 writeb(1, &ch->ch_neo_uart->rfifo);
902 ch->ch_r_tlevel = 1;
903 }
904
905 neo_assert_modem_signals(ch);
906
907 /* Get current status of the modem signals now */
908 neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
909}
910
911
912/*
913 * Our board poller function.
914 */
915static void neo_tasklet(unsigned long data)
916{
917 struct board_t *bd = (struct board_t *) data;
918 struct channel_t *ch;
919 ulong lock_flags;
920 int i;
921 int state = 0;
922 int ports = 0;
923
924 if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
925 APR(("poll_tasklet() - NULL or bad bd.\n"));
926 return;
927 }
928
929 /* Cache a couple board values */
930 DGNC_LOCK(bd->bd_lock, lock_flags);
931 state = bd->state;
932 ports = bd->nasync;
933 DGNC_UNLOCK(bd->bd_lock, lock_flags);
934
935 /*
936 * Do NOT allow the interrupt routine to read the intr registers
937 * Until we release this lock.
938 */
939 DGNC_LOCK(bd->bd_intr_lock, lock_flags);
940
941 /*
942 * If board is ready, parse deeper to see if there is anything to do.
943 */
944 if ((state == BOARD_READY) && (ports > 0)) {
945 /* Loop on each port */
946 for (i = 0; i < ports; i++) {
947 ch = bd->channels[i];
948
949 /* Just being careful... */
950 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
951 continue;
952
953 /*
954 * NOTE: Remember you CANNOT hold any channel
955 * locks when calling the input routine.
956 *
957 * During input processing, its possible we
958 * will call the Linux ld, which might in turn,
959 * do a callback right back into us, resulting
960 * in us trying to grab the channel lock twice!
961 */
962 dgnc_input(ch);
963
964 /*
965 * Channel lock is grabbed and then released
966 * inside both of these routines, but neither
967 * call anything else that could call back into us.
968 */
969 neo_copy_data_from_queue_to_uart(ch);
970 dgnc_wakeup_writes(ch);
971
972 /*
973 * Call carrier carrier function, in case something
974 * has changed.
975 */
976 dgnc_carrier(ch);
977
978 /*
979 * Check to see if we need to turn off a sending break.
980 * The timing check is done inside clear_break()
981 */
982 if (ch->ch_stop_sending_break)
983 neo_clear_break(ch, 0);
984 }
985 }
986
987 /* Allow interrupt routine to access the interrupt register again */
988 DGNC_UNLOCK(bd->bd_intr_lock, lock_flags);
989
990}
991
992
993/*
994 * dgnc_neo_intr()
995 *
996 * Neo specific interrupt handler.
997 */
998static irqreturn_t neo_intr(int irq, void *voidbrd)
999{
1000 struct board_t *brd = (struct board_t *) voidbrd;
1001 struct channel_t *ch;
1002 int port = 0;
1003 int type = 0;
1004 int current_port;
1005 u32 tmp;
1006 u32 uart_poll;
1007 unsigned long lock_flags;
1008 unsigned long lock_flags2;
1009
1010 if (!brd) {
1011 APR(("Received interrupt (%d) with null board associated\n", irq));
1012 return IRQ_NONE;
1013 }
1014
1015 /*
1016 * Check to make sure its for us.
1017 */
1018 if (brd->magic != DGNC_BOARD_MAGIC) {
1019 APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq));
1020 return IRQ_NONE;
1021 }
1022
1023 brd->intr_count++;
1024
1025 /* Lock out the slow poller from running on this board. */
1026 DGNC_LOCK(brd->bd_intr_lock, lock_flags);
1027
1028 /*
1029 * Read in "extended" IRQ information from the 32bit Neo register.
1030 * Bits 0-7: What port triggered the interrupt.
1031 * Bits 8-31: Each 3bits indicate what type of interrupt occurred.
1032 */
1033 uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
1034
1035 DPR_INTR(("%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll));
1036
1037 /*
1038 * If 0, no interrupts pending.
1039 * This can happen if the IRQ is shared among a couple Neo/Classic boards.
1040 */
1041 if (!uart_poll) {
1042 DPR_INTR(("Kernel interrupted to me, but no pending interrupts...\n"));
1043 DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
1044 return IRQ_NONE;
1045 }
1046
1047 /* At this point, we have at least SOMETHING to service, dig further... */
1048
1049 current_port = 0;
1050
1051 /* Loop on each port */
1052 while ((uart_poll & 0xff) != 0) {
1053
1054 tmp = uart_poll;
1055
1056 /* Check current port to see if it has interrupt pending */
1057 if ((tmp & dgnc_offset_table[current_port]) != 0) {
1058 port = current_port;
1059 type = tmp >> (8 + (port * 3));
1060 type &= 0x7;
1061 } else {
1062 current_port++;
1063 continue;
1064 }
1065
1066 DPR_INTR(("%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type));
1067
1068 /* Remove this port + type from uart_poll */
1069 uart_poll &= ~(dgnc_offset_table[port]);
1070
1071 if (!type) {
1072 /* If no type, just ignore it, and move onto next port */
1073 DPR_INTR(("Interrupt with no type! port: %d\n", port));
1074 continue;
1075 }
1076
1077 /* Switch on type of interrupt we have */
1078 switch (type) {
1079
1080 case UART_17158_RXRDY_TIMEOUT:
1081 /*
1082 * RXRDY Time-out is cleared by reading data in the
1083 * RX FIFO until it falls below the trigger level.
1084 */
1085
1086 /* Verify the port is in range. */
1087 if (port > brd->nasync)
1088 continue;
1089
1090 ch = brd->channels[port];
1091 neo_copy_data_from_uart_to_queue(ch);
1092
1093 /* Call our tty layer to enforce queue flow control if needed. */
1094 DGNC_LOCK(ch->ch_lock, lock_flags2);
1095 dgnc_check_queue_flow_control(ch);
1096 DGNC_UNLOCK(ch->ch_lock, lock_flags2);
1097
1098 continue;
1099
1100 case UART_17158_RX_LINE_STATUS:
1101 /*
1102 * RXRDY and RX LINE Status (logic OR of LSR[4:1])
1103 */
1104 neo_parse_lsr(brd, port);
1105 continue;
1106
1107 case UART_17158_TXRDY:
1108 /*
1109 * TXRDY interrupt clears after reading ISR register for the UART channel.
1110 */
1111
1112 /*
1113 * Yes, this is odd...
1114 * Why would I check EVERY possibility of type of
1115 * interrupt, when we know its TXRDY???
1116 * Becuz for some reason, even tho we got triggered for TXRDY,
1117 * it seems to be occassionally wrong. Instead of TX, which
1118 * it should be, I was getting things like RXDY too. Weird.
1119 */
1120 neo_parse_isr(brd, port);
1121 continue;
1122
1123 case UART_17158_MSR:
1124 /*
1125 * MSR or flow control was seen.
1126 */
1127 neo_parse_isr(brd, port);
1128 continue;
1129
1130 default:
1131 /*
1132 * The UART triggered us with a bogus interrupt type.
1133 * It appears the Exar chip, when REALLY bogged down, will throw
1134 * these once and awhile.
1135 * Its harmless, just ignore it and move on.
1136 */
1137 DPR_INTR(("%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type));
1138 continue;
1139 }
1140 }
1141
1142 /*
1143 * Schedule tasklet to more in-depth servicing at a better time.
1144 */
1145 tasklet_schedule(&brd->helper_tasklet);
1146
1147 DGNC_UNLOCK(brd->bd_intr_lock, lock_flags);
1148
1149 DPR_INTR(("dgnc_intr finish.\n"));
1150 return IRQ_HANDLED;
1151}
1152
1153
1154/*
1155 * Neo specific way of turning off the receiver.
1156 * Used as a way to enforce queue flow control when in
1157 * hardware flow control mode.
1158 */
1159static void neo_disable_receiver(struct channel_t *ch)
1160{
1161 uchar tmp = readb(&ch->ch_neo_uart->ier);
1162 tmp &= ~(UART_IER_RDI);
1163 writeb(tmp, &ch->ch_neo_uart->ier);
1164 neo_pci_posting_flush(ch->ch_bd);
1165}
1166
1167
1168/*
1169 * Neo specific way of turning on the receiver.
1170 * Used as a way to un-enforce queue flow control when in
1171 * hardware flow control mode.
1172 */
1173static void neo_enable_receiver(struct channel_t *ch)
1174{
1175 uchar tmp = readb(&ch->ch_neo_uart->ier);
1176 tmp |= (UART_IER_RDI);
1177 writeb(tmp, &ch->ch_neo_uart->ier);
1178 neo_pci_posting_flush(ch->ch_bd);
1179}
1180
1181
1182static void neo_copy_data_from_uart_to_queue(struct channel_t *ch)
1183{
1184 int qleft = 0;
1185 uchar linestatus = 0;
1186 uchar error_mask = 0;
1187 int n = 0;
1188 int total = 0;
1189 ushort head;
1190 ushort tail;
1191 ulong lock_flags;
1192
1193 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1194 return;
1195
1196 DGNC_LOCK(ch->ch_lock, lock_flags);
1197
1198 /* cache head and tail of queue */
1199 head = ch->ch_r_head & RQUEUEMASK;
1200 tail = ch->ch_r_tail & RQUEUEMASK;
1201
1202 /* Get our cached LSR */
1203 linestatus = ch->ch_cached_lsr;
1204 ch->ch_cached_lsr = 0;
1205
1206 /* Store how much space we have left in the queue */
1207 if ((qleft = tail - head - 1) < 0)
1208 qleft += RQUEUEMASK + 1;
1209
1210 /*
1211 * If the UART is not in FIFO mode, force the FIFO copy to
1212 * NOT be run, by setting total to 0.
1213 *
1214 * On the other hand, if the UART IS in FIFO mode, then ask
1215 * the UART to give us an approximation of data it has RX'ed.
1216 */
1217 if (!(ch->ch_flags & CH_FIFO_ENABLED))
1218 total = 0;
1219 else {
1220 total = readb(&ch->ch_neo_uart->rfifo);
1221
1222 /*
1223 * EXAR chip bug - RX FIFO COUNT - Fudge factor.
1224 *
1225 * This resolves a problem/bug with the Exar chip that sometimes
1226 * returns a bogus value in the rfifo register.
1227 * The count can be any where from 0-3 bytes "off".
1228 * Bizarre, but true.
1229 */
1230 if ((ch->ch_bd->dvid & 0xf0) >= UART_XR17E158_DVID) {
1231 total -= 1;
1232 }
1233 else {
1234 total -= 3;
1235 }
1236 }
1237
1238
1239 /*
1240 * Finally, bound the copy to make sure we don't overflow
1241 * our own queue...
1242 * The byte by byte copy loop below this loop this will
1243 * deal with the queue overflow possibility.
1244 */
1245 total = min(total, qleft);
1246
1247 while (total > 0) {
1248
1249 /*
1250 * Grab the linestatus register, we need to check
1251 * to see if there are any errors in the FIFO.
1252 */
1253 linestatus = readb(&ch->ch_neo_uart->lsr);
1254
1255 /*
1256 * Break out if there is a FIFO error somewhere.
1257 * This will allow us to go byte by byte down below,
1258 * finding the exact location of the error.
1259 */
1260 if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
1261 break;
1262
1263 /* Make sure we don't go over the end of our queue */
1264 n = min(((uint) total), (RQUEUESIZE - (uint) head));
1265
1266 /*
1267 * Cut down n even further if needed, this is to fix
1268 * a problem with memcpy_fromio() with the Neo on the
1269 * IBM pSeries platform.
1270 * 15 bytes max appears to be the magic number.
1271 */
1272 n = min((uint) n, (uint) 12);
1273
1274 /*
1275 * Since we are grabbing the linestatus register, which
1276 * will reset some bits after our read, we need to ensure
1277 * we don't miss our TX FIFO emptys.
1278 */
1279 if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
1280 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1281 }
1282
1283 linestatus = 0;
1284
1285 /* Copy data from uart to the queue */
1286 memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n);
1287 dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, n);
1288
1289 /*
1290 * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed
1291 * that all the data currently in the FIFO is free of
1292 * breaks and parity/frame/orun errors.
1293 */
1294 memset(ch->ch_equeue + head, 0, n);
1295
1296 /* Add to and flip head if needed */
1297 head = (head + n) & RQUEUEMASK;
1298 total -= n;
1299 qleft -= n;
1300 ch->ch_rxcount += n;
1301 }
1302
1303 /*
1304 * Create a mask to determine whether we should
1305 * insert the character (if any) into our queue.
1306 */
1307 if (ch->ch_c_iflag & IGNBRK)
1308 error_mask |= UART_LSR_BI;
1309
1310 /*
1311 * Now cleanup any leftover bytes still in the UART.
1312 * Also deal with any possible queue overflow here as well.
1313 */
1314 while (1) {
1315
1316 /*
1317 * Its possible we have a linestatus from the loop above
1318 * this, so we "OR" on any extra bits.
1319 */
1320 linestatus |= readb(&ch->ch_neo_uart->lsr);
1321
1322 /*
1323 * If the chip tells us there is no more data pending to
1324 * be read, we can then leave.
1325 * But before we do, cache the linestatus, just in case.
1326 */
1327 if (!(linestatus & UART_LSR_DR)) {
1328 ch->ch_cached_lsr = linestatus;
1329 break;
1330 }
1331
1332 /* No need to store this bit */
1333 linestatus &= ~UART_LSR_DR;
1334
1335 /*
1336 * Since we are grabbing the linestatus register, which
1337 * will reset some bits after our read, we need to ensure
1338 * we don't miss our TX FIFO emptys.
1339 */
1340 if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
1341 linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR);
1342 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1343 }
1344
1345 /*
1346 * Discard character if we are ignoring the error mask.
1347 */
1348 if (linestatus & error_mask) {
1349 uchar discard;
1350 linestatus = 0;
1351 memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
1352 continue;
1353 }
1354
1355 /*
1356 * If our queue is full, we have no choice but to drop some data.
1357 * The assumption is that HWFLOW or SWFLOW should have stopped
1358 * things way way before we got to this point.
1359 *
1360 * I decided that I wanted to ditch the oldest data first,
1361 * I hope thats okay with everyone? Yes? Good.
1362 */
1363 while (qleft < 1) {
1364 DPR_READ(("Queue full, dropping DATA:%x LSR:%x\n",
1365 ch->ch_rqueue[tail], ch->ch_equeue[tail]));
1366
1367 ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
1368 ch->ch_err_overrun++;
1369 qleft++;
1370 }
1371
1372 memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
1373 ch->ch_equeue[head] = (uchar) linestatus;
1374 dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, 1);
1375
1376 DPR_READ(("DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]));
1377
1378 /* Ditch any remaining linestatus value. */
1379 linestatus = 0;
1380
1381 /* Add to and flip head if needed */
1382 head = (head + 1) & RQUEUEMASK;
1383
1384 qleft--;
1385 ch->ch_rxcount++;
1386 }
1387
1388 /*
1389 * Write new final heads to channel structure.
1390 */
1391 ch->ch_r_head = head & RQUEUEMASK;
1392 ch->ch_e_head = head & EQUEUEMASK;
1393
1394 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1395}
1396
1397
1398/*
1399 * This function basically goes to sleep for secs, or until
1400 * it gets signalled that the port has fully drained.
1401 */
1402static int neo_drain(struct tty_struct *tty, uint seconds)
1403{
1404 ulong lock_flags;
1405 struct channel_t *ch;
1406 struct un_t *un;
1407 int rc = 0;
1408
1409 if (!tty || tty->magic != TTY_MAGIC) {
1410 return (-ENXIO);
1411 }
1412
1413 un = (struct un_t *) tty->driver_data;
1414 if (!un || un->magic != DGNC_UNIT_MAGIC) {
1415 return (-ENXIO);
1416 }
1417
1418 ch = un->un_ch;
1419 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
1420 return (-ENXIO);
1421 }
1422
1423 DPR_IOCTL(("%d Drain wait started.\n", __LINE__));
1424
1425 DGNC_LOCK(ch->ch_lock, lock_flags);
1426 un->un_flags |= UN_EMPTY;
1427 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1428
1429 /*
1430 * Go to sleep waiting for the tty layer to wake me back up when
1431 * the empty flag goes away.
1432 *
1433 * NOTE: TODO: Do something with time passed in.
1434 */
1435 rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0));
1436
1437 /* If ret is non-zero, user ctrl-c'ed us */
1438 if (rc) {
1439 DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__));
1440 }
1441 else {
1442 DPR_IOCTL(("%d Drain wait finished.\n", __LINE__));
1443 }
1444
1445 return (rc);
1446}
1447
1448
1449/*
1450 * Flush the WRITE FIFO on the Neo.
1451 *
1452 * NOTE: Channel lock MUST be held before calling this function!
1453 */
1454static void neo_flush_uart_write(struct channel_t *ch)
1455{
1456 uchar tmp = 0;
1457 int i = 0;
1458
1459 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
1460 return;
1461 }
1462
1463 writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
1464 neo_pci_posting_flush(ch->ch_bd);
1465
1466 for (i = 0; i < 10; i++) {
1467
1468 /* Check to see if the UART feels it completely flushed the FIFO. */
1469 tmp = readb(&ch->ch_neo_uart->isr_fcr);
1470 if (tmp & 4) {
1471 DPR_IOCTL(("Still flushing TX UART... i: %d\n", i));
1472 udelay(10);
1473 }
1474 else
1475 break;
1476 }
1477
1478 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1479}
1480
1481
1482/*
1483 * Flush the READ FIFO on the Neo.
1484 *
1485 * NOTE: Channel lock MUST be held before calling this function!
1486 */
1487static void neo_flush_uart_read(struct channel_t *ch)
1488{
1489 uchar tmp = 0;
1490 int i = 0;
1491
1492 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
1493 return;
1494 }
1495
1496 writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr);
1497 neo_pci_posting_flush(ch->ch_bd);
1498
1499 for (i = 0; i < 10; i++) {
1500
1501 /* Check to see if the UART feels it completely flushed the FIFO. */
1502 tmp = readb(&ch->ch_neo_uart->isr_fcr);
1503 if (tmp & 2) {
1504 DPR_IOCTL(("Still flushing RX UART... i: %d\n", i));
1505 udelay(10);
1506 }
1507 else
1508 break;
1509 }
1510}
1511
1512
1513static void neo_copy_data_from_queue_to_uart(struct channel_t *ch)
1514{
1515 ushort head;
1516 ushort tail;
1517 int n;
1518 int s;
1519 int qlen;
1520 uint len_written = 0;
1521 ulong lock_flags;
1522
1523 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1524 return;
1525
1526 DGNC_LOCK(ch->ch_lock, lock_flags);
1527
1528 /* No data to write to the UART */
1529 if (ch->ch_w_tail == ch->ch_w_head) {
1530 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1531 return;
1532 }
1533
1534 /* If port is "stopped", don't send any data to the UART */
1535 if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) {
1536 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1537 return;
1538 }
1539
1540 /*
1541 * If FIFOs are disabled. Send data directly to txrx register
1542 */
1543 if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
1544 uchar lsrbits = readb(&ch->ch_neo_uart->lsr);
1545
1546 /* Cache the LSR bits for later parsing */
1547 ch->ch_cached_lsr |= lsrbits;
1548 if (ch->ch_cached_lsr & UART_LSR_THRE) {
1549 ch->ch_cached_lsr &= ~(UART_LSR_THRE);
1550
1551 /*
1552 * If RTS Toggle mode is on, turn on RTS now if not already set,
1553 * and make sure we get an event when the data transfer has completed.
1554 */
1555 if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
1556 if (!(ch->ch_mostat & UART_MCR_RTS)) {
1557 ch->ch_mostat |= (UART_MCR_RTS);
1558 neo_assert_modem_signals(ch);
1559 }
1560 ch->ch_tun.un_flags |= (UN_EMPTY);
1561 }
1562 /*
1563 * If DTR Toggle mode is on, turn on DTR now if not already set,
1564 * and make sure we get an event when the data transfer has completed.
1565 */
1566 if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
1567 if (!(ch->ch_mostat & UART_MCR_DTR)) {
1568 ch->ch_mostat |= (UART_MCR_DTR);
1569 neo_assert_modem_signals(ch);
1570 }
1571 ch->ch_tun.un_flags |= (UN_EMPTY);
1572 }
1573
1574 writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
1575 DPR_WRITE(("Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]));
1576 ch->ch_w_tail++;
1577 ch->ch_w_tail &= WQUEUEMASK;
1578 ch->ch_txcount++;
1579 }
1580 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1581 return;
1582 }
1583
1584 /*
1585 * We have to do it this way, because of the EXAR TXFIFO count bug.
1586 */
1587 if ((ch->ch_bd->dvid & 0xf0) < UART_XR17E158_DVID) {
1588 if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) {
1589 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1590 return;
1591 }
1592
1593 len_written = 0;
1594
1595 n = readb(&ch->ch_neo_uart->tfifo);
1596
1597 if ((unsigned int) n > ch->ch_t_tlevel) {
1598 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1599 return;
1600 }
1601
1602 n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
1603 }
1604 else {
1605 n = UART_17158_TX_FIFOSIZE - readb(&ch->ch_neo_uart->tfifo);
1606 }
1607
1608 /* cache head and tail of queue */
1609 head = ch->ch_w_head & WQUEUEMASK;
1610 tail = ch->ch_w_tail & WQUEUEMASK;
1611 qlen = (head - tail) & WQUEUEMASK;
1612
1613 /* Find minimum of the FIFO space, versus queue length */
1614 n = min(n, qlen);
1615
1616 while (n > 0) {
1617
1618 s = ((head >= tail) ? head : WQUEUESIZE) - tail;
1619 s = min(s, n);
1620
1621 if (s <= 0)
1622 break;
1623
1624 /*
1625 * If RTS Toggle mode is on, turn on RTS now if not already set,
1626 * and make sure we get an event when the data transfer has completed.
1627 */
1628 if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
1629 if (!(ch->ch_mostat & UART_MCR_RTS)) {
1630 ch->ch_mostat |= (UART_MCR_RTS);
1631 neo_assert_modem_signals(ch);
1632 }
1633 ch->ch_tun.un_flags |= (UN_EMPTY);
1634 }
1635
1636 /*
1637 * If DTR Toggle mode is on, turn on DTR now if not already set,
1638 * and make sure we get an event when the data transfer has completed.
1639 */
1640 if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
1641 if (!(ch->ch_mostat & UART_MCR_DTR)) {
1642 ch->ch_mostat |= (UART_MCR_DTR);
1643 neo_assert_modem_signals(ch);
1644 }
1645 ch->ch_tun.un_flags |= (UN_EMPTY);
1646 }
1647
1648 memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
1649 dgnc_sniff_nowait_nolock(ch, "UART WRITE", ch->ch_wqueue + tail, s);
1650
1651 /* Add and flip queue if needed */
1652 tail = (tail + s) & WQUEUEMASK;
1653 n -= s;
1654 ch->ch_txcount += s;
1655 len_written += s;
1656 }
1657
1658 /* Update the final tail */
1659 ch->ch_w_tail = tail & WQUEUEMASK;
1660
1661 if (len_written > 0) {
1662 neo_pci_posting_flush(ch->ch_bd);
1663 ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1664 }
1665
1666 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1667}
1668
1669
1670static void neo_parse_modem(struct channel_t *ch, uchar signals)
1671{
1672 volatile uchar msignals = signals;
1673
1674 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1675 return;
1676
1677 DPR_MSIGS(("neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals));
1678
1679 /*
1680 * Do altpin switching. Altpin switches DCD and DSR.
1681 * This prolly breaks DSRPACE, so we should be more clever here.
1682 */
1683 if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
1684 uchar mswap = msignals;
1685
1686 if (mswap & UART_MSR_DDCD) {
1687 msignals &= ~UART_MSR_DDCD;
1688 msignals |= UART_MSR_DDSR;
1689 }
1690 if (mswap & UART_MSR_DDSR) {
1691 msignals &= ~UART_MSR_DDSR;
1692 msignals |= UART_MSR_DDCD;
1693 }
1694 if (mswap & UART_MSR_DCD) {
1695 msignals &= ~UART_MSR_DCD;
1696 msignals |= UART_MSR_DSR;
1697 }
1698 if (mswap & UART_MSR_DSR) {
1699 msignals &= ~UART_MSR_DSR;
1700 msignals |= UART_MSR_DCD;
1701 }
1702 }
1703
1704 /* Scrub off lower bits. They signify delta's, which I don't care about */
1705 msignals &= 0xf0;
1706
1707 if (msignals & UART_MSR_DCD)
1708 ch->ch_mistat |= UART_MSR_DCD;
1709 else
1710 ch->ch_mistat &= ~UART_MSR_DCD;
1711
1712 if (msignals & UART_MSR_DSR)
1713 ch->ch_mistat |= UART_MSR_DSR;
1714 else
1715 ch->ch_mistat &= ~UART_MSR_DSR;
1716
1717 if (msignals & UART_MSR_RI)
1718 ch->ch_mistat |= UART_MSR_RI;
1719 else
1720 ch->ch_mistat &= ~UART_MSR_RI;
1721
1722 if (msignals & UART_MSR_CTS)
1723 ch->ch_mistat |= UART_MSR_CTS;
1724 else
1725 ch->ch_mistat &= ~UART_MSR_CTS;
1726
1727 DPR_MSIGS(("Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
1728 ch->ch_portnum,
1729 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
1730 !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
1731 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
1732 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
1733 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
1734 !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD)));
1735}
1736
1737
1738/* Make the UART raise any of the output signals we want up */
1739static void neo_assert_modem_signals(struct channel_t *ch)
1740{
1741 uchar out;
1742
1743 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1744 return;
1745
1746 out = ch->ch_mostat;
1747
1748 if (ch->ch_flags & CH_LOOPBACK)
1749 out |= UART_MCR_LOOP;
1750
1751 writeb(out, &ch->ch_neo_uart->mcr);
1752 neo_pci_posting_flush(ch->ch_bd);
1753
1754 /* Give time for the UART to actually raise/drop the signals */
1755 udelay(10);
1756}
1757
1758
1759static void neo_send_start_character(struct channel_t *ch)
1760{
1761 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1762 return;
1763
1764 if (ch->ch_startc != _POSIX_VDISABLE) {
1765 ch->ch_xon_sends++;
1766 writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
1767 neo_pci_posting_flush(ch->ch_bd);
1768 udelay(10);
1769 }
1770}
1771
1772
1773static void neo_send_stop_character(struct channel_t *ch)
1774{
1775 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1776 return;
1777
1778 if (ch->ch_stopc != _POSIX_VDISABLE) {
1779 ch->ch_xoff_sends++;
1780 writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
1781 neo_pci_posting_flush(ch->ch_bd);
1782 udelay(10);
1783 }
1784}
1785
1786
1787/*
1788 * neo_uart_init
1789 */
1790static void neo_uart_init(struct channel_t *ch)
1791{
1792
1793 writeb(0, &ch->ch_neo_uart->ier);
1794 writeb(0, &ch->ch_neo_uart->efr);
1795 writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
1796
1797
1798 /* Clear out UART and FIFO */
1799 readb(&ch->ch_neo_uart->txrx);
1800 writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
1801 readb(&ch->ch_neo_uart->lsr);
1802 readb(&ch->ch_neo_uart->msr);
1803
1804 ch->ch_flags |= CH_FIFO_ENABLED;
1805
1806 /* Assert any signals we want up */
1807 writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
1808 neo_pci_posting_flush(ch->ch_bd);
1809}
1810
1811
1812/*
1813 * Make the UART completely turn off.
1814 */
1815static void neo_uart_off(struct channel_t *ch)
1816{
1817 /* Turn off UART enhanced bits */
1818 writeb(0, &ch->ch_neo_uart->efr);
1819
1820 /* Stop all interrupts from occurring. */
1821 writeb(0, &ch->ch_neo_uart->ier);
1822 neo_pci_posting_flush(ch->ch_bd);
1823}
1824
1825
1826static uint neo_get_uart_bytes_left(struct channel_t *ch)
1827{
1828 uchar left = 0;
1829 uchar lsr = readb(&ch->ch_neo_uart->lsr);
1830
1831 /* We must cache the LSR as some of the bits get reset once read... */
1832 ch->ch_cached_lsr |= lsr;
1833
1834 /* Determine whether the Transmitter is empty or not */
1835 if (!(lsr & UART_LSR_TEMT)) {
1836 if (ch->ch_flags & CH_TX_FIFO_EMPTY) {
1837 tasklet_schedule(&ch->ch_bd->helper_tasklet);
1838 }
1839 left = 1;
1840 } else {
1841 ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
1842 left = 0;
1843 }
1844
1845 return left;
1846}
1847
1848
1849/* Channel lock MUST be held by the calling function! */
1850static void neo_send_break(struct channel_t *ch, int msecs)
1851{
1852 /*
1853 * If we receive a time of 0, this means turn off the break.
1854 */
1855 if (msecs == 0) {
1856 if (ch->ch_flags & CH_BREAK_SENDING) {
1857 uchar temp = readb(&ch->ch_neo_uart->lcr);
1858 writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
1859 neo_pci_posting_flush(ch->ch_bd);
1860 ch->ch_flags &= ~(CH_BREAK_SENDING);
1861 ch->ch_stop_sending_break = 0;
1862 DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies));
1863 }
1864 return;
1865 }
1866
1867 /*
1868 * Set the time we should stop sending the break.
1869 * If we are already sending a break, toss away the existing
1870 * time to stop, and use this new value instead.
1871 */
1872 ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs);
1873
1874 /* Tell the UART to start sending the break */
1875 if (!(ch->ch_flags & CH_BREAK_SENDING)) {
1876 uchar temp = readb(&ch->ch_neo_uart->lcr);
1877 writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
1878 neo_pci_posting_flush(ch->ch_bd);
1879 ch->ch_flags |= (CH_BREAK_SENDING);
1880 DPR_IOCTL(("Port %d. Starting UART_LCR_SBC! start: %lx should end: %lx\n",
1881 ch->ch_portnum, jiffies, ch->ch_stop_sending_break));
1882 }
1883}
1884
1885
1886/*
1887 * neo_send_immediate_char.
1888 *
1889 * Sends a specific character as soon as possible to the UART,
1890 * jumping over any bytes that might be in the write queue.
1891 *
1892 * The channel lock MUST be held by the calling function.
1893 */
1894static void neo_send_immediate_char(struct channel_t *ch, unsigned char c)
1895{
1896 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1897 return;
1898
1899 writeb(c, &ch->ch_neo_uart->txrx);
1900 neo_pci_posting_flush(ch->ch_bd);
1901}
1902
1903
1904static unsigned int neo_read_eeprom(unsigned char *base, unsigned int address)
1905{
1906 unsigned int enable;
1907 unsigned int bits;
1908 unsigned int databit;
1909 unsigned int val;
1910
1911 /* enable chip select */
1912 writeb(NEO_EECS, base + NEO_EEREG);
1913 /* READ */
1914 enable = (address | 0x180);
1915
1916 for (bits = 9; bits--; ) {
1917 databit = (enable & (1 << bits)) ? NEO_EEDI : 0;
1918 /* Set read address */
1919 writeb(databit | NEO_EECS, base + NEO_EEREG);
1920 writeb(databit | NEO_EECS | NEO_EECK, base + NEO_EEREG);
1921 }
1922
1923 val = 0;
1924
1925 for (bits = 17; bits--; ) {
1926 /* clock to EEPROM */
1927 writeb(NEO_EECS, base + NEO_EEREG);
1928 writeb(NEO_EECS | NEO_EECK, base + NEO_EEREG);
1929 val <<= 1;
1930 /* read EEPROM */
1931 if (readb(base + NEO_EEREG) & NEO_EEDO)
1932 val |= 1;
1933 }
1934
1935 /* clock falling edge */
1936 writeb(NEO_EECS, base + NEO_EEREG);
1937
1938 /* drop chip select */
1939 writeb(0x00, base + NEO_EEREG);
1940
1941 return val;
1942}
1943
1944
1945static void neo_vpd(struct board_t *brd)
1946{
1947 unsigned int i = 0;
1948 unsigned int a;
1949
1950 if (!brd || brd->magic != DGNC_BOARD_MAGIC)
1951 return;
1952
1953 if (!brd->re_map_membase)
1954 return;
1955
1956 /* Store the VPD into our buffer */
1957 for (i = 0; i < NEO_VPD_IMAGESIZE; i++) {
1958 a = neo_read_eeprom(brd->re_map_membase, i);
1959 brd->vpd[i*2] = a & 0xff;
1960 brd->vpd[(i*2)+1] = (a >> 8) & 0xff;
1961 }
1962
1963 if (((brd->vpd[0x08] != 0x82) /* long resource name tag */
1964 && (brd->vpd[0x10] != 0x82)) /* long resource name tag (PCI-66 files)*/
1965 || (brd->vpd[0x7F] != 0x78)) /* small resource end tag */
1966 {
1967 memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE);
1968 }
1969 else {
1970 /* Search for the serial number */
1971 for (i = 0; i < NEO_VPD_IMAGESIZE * 2; i++) {
1972 if (brd->vpd[i] == 'S' && brd->vpd[i + 1] == 'N') {
1973 strncpy(brd->serial_num, &(brd->vpd[i + 3]), 9);
1974 }
1975 }
1976 }
1977}
diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h
new file mode 100644
index 000000000000..ffb42099b9fd
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_neo.h
@@ -0,0 +1,157 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 *
21 */
22
23#ifndef __DGNC_NEO_H
24#define __DGNC_NEO_H
25
26#include "dgnc_types.h"
27#include "dgnc_driver.h"
28
29/************************************************************************
30 * Per channel/port NEO UART structure *
31 ************************************************************************
32 * Base Structure Entries Usage Meanings to Host *
33 * *
34 * W = read write R = read only *
35 * U = Unused. *
36 ************************************************************************/
37
38struct neo_uart_struct {
39 volatile uchar txrx; /* WR RHR/THR - Holding Reg */
40 volatile uchar ier; /* WR IER - Interrupt Enable Reg */
41 volatile uchar isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
42 volatile uchar lcr; /* WR LCR - Line Control Reg */
43 volatile uchar mcr; /* WR MCR - Modem Control Reg */
44 volatile uchar lsr; /* WR LSR - Line Status Reg */
45 volatile uchar msr; /* WR MSR - Modem Status Reg */
46 volatile uchar spr; /* WR SPR - Scratch Pad Reg */
47 volatile uchar fctr; /* WR FCTR - Feature Control Reg */
48 volatile uchar efr; /* WR EFR - Enhanced Function Reg */
49 volatile uchar tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */
50 volatile uchar rfifo; /* WR RXCNT/RXTRG - Recieve FIFO Reg */
51 volatile uchar xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */
52 volatile uchar xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */
53 volatile uchar xonchar1; /* WR XON 1 - Xon Character 1 Reg */
54 volatile uchar xonchar2; /* WR XON 2 - XOn Character 2 Reg */
55
56 volatile uchar reserved1[0x2ff - 0x200]; /* U Reserved by Exar */
57 volatile uchar txrxburst[64]; /* RW 64 bytes of RX/TX FIFO Data */
58 volatile uchar reserved2[0x37f - 0x340]; /* U Reserved by Exar */
59 volatile uchar rxburst_with_errors[64]; /* R 64 bytes of RX FIFO Data + LSR */
60};
61
62/* Where to read the extended interrupt register (32bits instead of 8bits) */
63#define UART_17158_POLL_ADDR_OFFSET 0x80
64
65/* These are the current dvid's of the Neo boards */
66#define UART_XR17C158_DVID 0x20
67#define UART_XR17D158_DVID 0x20
68#define UART_XR17E158_DVID 0x40
69
70#define NEO_EECK 0x10 /* Clock */
71#define NEO_EECS 0x20 /* Chip Select */
72#define NEO_EEDI 0x40 /* Data In is an Output Pin */
73#define NEO_EEDO 0x80 /* Data Out is an Input Pin */
74#define NEO_EEREG 0x8E /* offset to EEPROM control reg */
75
76
77#define NEO_VPD_IMAGESIZE 0x40 /* size of image to read from EEPROM in words */
78#define NEO_VPD_IMAGEBYTES (NEO_VPD_IMAGESIZE * 2)
79
80/*
81 * These are the redefinitions for the FCTR on the XR17C158, since
82 * Exar made them different than their earlier design. (XR16C854)
83 */
84
85/* These are only applicable when table D is selected */
86#define UART_17158_FCTR_RTS_NODELAY 0x00
87#define UART_17158_FCTR_RTS_4DELAY 0x01
88#define UART_17158_FCTR_RTS_6DELAY 0x02
89#define UART_17158_FCTR_RTS_8DELAY 0x03
90#define UART_17158_FCTR_RTS_12DELAY 0x12
91#define UART_17158_FCTR_RTS_16DELAY 0x05
92#define UART_17158_FCTR_RTS_20DELAY 0x13
93#define UART_17158_FCTR_RTS_24DELAY 0x06
94#define UART_17158_FCTR_RTS_28DELAY 0x14
95#define UART_17158_FCTR_RTS_32DELAY 0x07
96#define UART_17158_FCTR_RTS_36DELAY 0x16
97#define UART_17158_FCTR_RTS_40DELAY 0x08
98#define UART_17158_FCTR_RTS_44DELAY 0x09
99#define UART_17158_FCTR_RTS_48DELAY 0x10
100#define UART_17158_FCTR_RTS_52DELAY 0x11
101
102#define UART_17158_FCTR_RTS_IRDA 0x10
103#define UART_17158_FCTR_RS485 0x20
104#define UART_17158_FCTR_TRGA 0x00
105#define UART_17158_FCTR_TRGB 0x40
106#define UART_17158_FCTR_TRGC 0x80
107#define UART_17158_FCTR_TRGD 0xC0
108
109/* 17158 trigger table selects.. */
110#define UART_17158_FCTR_BIT6 0x40
111#define UART_17158_FCTR_BIT7 0x80
112
113/* 17158 TX/RX memmapped buffer offsets */
114#define UART_17158_RX_FIFOSIZE 64
115#define UART_17158_TX_FIFOSIZE 64
116
117/* 17158 Extended IIR's */
118#define UART_17158_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */
119#define UART_17158_IIR_XONXOFF 0x10 /* Received an XON/XOFF char */
120#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR state change */
121#define UART_17158_IIR_FIFO_ENABLED 0xC0 /* 16550 FIFOs are Enabled */
122
123/*
124 * These are the extended interrupts that get sent
125 * back to us from the UART's 32bit interrupt register
126 */
127#define UART_17158_RX_LINE_STATUS 0x1 /* RX Ready */
128#define UART_17158_RXRDY_TIMEOUT 0x2 /* RX Ready Timeout */
129#define UART_17158_TXRDY 0x3 /* TX Ready */
130#define UART_17158_MSR 0x4 /* Modem State Change */
131#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding Reg Empty */
132#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO Data error */
133
134/*
135 * These are the EXTENDED definitions for the 17C158's Interrupt
136 * Enable Register.
137 */
138#define UART_17158_EFR_ECB 0x10 /* Enhanced control bit */
139#define UART_17158_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */
140#define UART_17158_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */
141#define UART_17158_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */
142#define UART_17158_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */
143
144#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */
145#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */
146
147#define UART_17158_IER_RSVD1 0x10 /* Reserved by Exar */
148#define UART_17158_IER_XOFF 0x20 /* Xoff Interrupt Enable */
149#define UART_17158_IER_RTSDTR 0x40 /* Output Interrupt Enable */
150#define UART_17158_IER_CTSDSR 0x80 /* Input Interrupt Enable */
151
152/*
153 * Our Global Variables
154 */
155extern struct board_ops dgnc_neo_ops;
156
157#endif
diff --git a/drivers/staging/dgnc/dgnc_pci.h b/drivers/staging/dgnc/dgnc_pci.h
new file mode 100644
index 000000000000..5550707ba1fb
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_pci.h
@@ -0,0 +1,77 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 */
21
22/* $Id: dgnc_pci.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ */
23
24#ifndef __DGNC_PCI_H
25#define __DGNC_PCI_H
26
27#define PCIMAX 32 /* maximum number of PCI boards */
28
29#define DIGI_VID 0x114F
30
31#define PCI_DEVICE_CLASSIC_4_DID 0x0028
32#define PCI_DEVICE_CLASSIC_8_DID 0x0029
33#define PCI_DEVICE_CLASSIC_4_422_DID 0x00D0
34#define PCI_DEVICE_CLASSIC_8_422_DID 0x00D1
35#define PCI_DEVICE_NEO_4_DID 0x00B0
36#define PCI_DEVICE_NEO_8_DID 0x00B1
37#define PCI_DEVICE_NEO_2DB9_DID 0x00C8
38#define PCI_DEVICE_NEO_2DB9PRI_DID 0x00C9
39#define PCI_DEVICE_NEO_2RJ45_DID 0x00CA
40#define PCI_DEVICE_NEO_2RJ45PRI_DID 0x00CB
41#define PCI_DEVICE_NEO_1_422_DID 0x00CC
42#define PCI_DEVICE_NEO_1_422_485_DID 0x00CD
43#define PCI_DEVICE_NEO_2_422_485_DID 0x00CE
44#define PCI_DEVICE_NEO_EXPRESS_8_DID 0x00F0
45#define PCI_DEVICE_NEO_EXPRESS_4_DID 0x00F1
46#define PCI_DEVICE_NEO_EXPRESS_4RJ45_DID 0x00F2
47#define PCI_DEVICE_NEO_EXPRESS_8RJ45_DID 0x00F3
48#define PCI_DEVICE_NEO_EXPRESS_4_IBM_DID 0x00F4
49
50#define PCI_DEVICE_CLASSIC_4_PCI_NAME "ClassicBoard 4 PCI"
51#define PCI_DEVICE_CLASSIC_8_PCI_NAME "ClassicBoard 8 PCI"
52#define PCI_DEVICE_CLASSIC_4_422_PCI_NAME "ClassicBoard 4 422 PCI"
53#define PCI_DEVICE_CLASSIC_8_422_PCI_NAME "ClassicBoard 8 422 PCI"
54#define PCI_DEVICE_NEO_4_PCI_NAME "Neo 4 PCI"
55#define PCI_DEVICE_NEO_8_PCI_NAME "Neo 8 PCI"
56#define PCI_DEVICE_NEO_2DB9_PCI_NAME "Neo 2 - DB9 Universal PCI"
57#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME "Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
58#define PCI_DEVICE_NEO_2RJ45_PCI_NAME "Neo 2 - RJ45 Universal PCI"
59#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME "Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
60#define PCI_DEVICE_NEO_1_422_PCI_NAME "Neo 1 422 PCI"
61#define PCI_DEVICE_NEO_1_422_485_PCI_NAME "Neo 1 422/485 PCI"
62#define PCI_DEVICE_NEO_2_422_485_PCI_NAME "Neo 2 422/485 PCI"
63
64#define PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME "Neo 8 PCI Express"
65#define PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME "Neo 4 PCI Express"
66#define PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME "Neo 4 PCI Express RJ45"
67#define PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME "Neo 8 PCI Express RJ45"
68#define PCI_DEVICE_NEO_EXPRESS_4_IBM_PCI_NAME "Neo 4 PCI Express IBM"
69
70
71/* Size of Memory and I/O for PCI (4 K) */
72#define PCI_RAM_SIZE 0x1000
73
74/* Size of Memory (2MB) */
75#define PCI_MEM_SIZE 0x1000
76
77#endif
diff --git a/drivers/staging/dgnc/dgnc_proc.c b/drivers/staging/dgnc/dgnc_proc.c
new file mode 100644
index 000000000000..8fbaf3b38e60
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_proc.c
@@ -0,0 +1,1551 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 *
31 * $Id: dgnc_proc.c,v 1.3 2011/06/22 12:16:35 markh Exp $
32 */
33
34#include <linux/kernel.h>
35#include <linux/version.h>
36#include <linux/sched.h> /* For jiffies, task states */
37#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
38#include <linux/module.h>
39#include <linux/ctype.h>
40#include <linux/proc_fs.h>
41#include <linux/serial_reg.h>
42#include <linux/sched.h> /* For in_egroup_p() */
43#include <linux/string.h>
44#include <asm/uaccess.h> /* For copy_from_user/copy_to_user */
45
46#include "dgnc_driver.h"
47#include "dgnc_proc.h"
48#include "dgnc_mgmt.h"
49
50#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
51#define init_MUTEX(sem) sema_init(sem, 1)
52#define DECLARE_MUTEX(name) \
53 struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
54#endif
55
56
57/* The /proc/dgnc directory */
58static struct proc_dir_entry *ProcDGNC;
59
60
61/* File operation declarations */
62static int dgnc_gen_proc_open(struct inode *, struct file *);
63static int dgnc_gen_proc_close(struct inode *, struct file *);
64static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
65static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
66
67static int dgnc_proc_chk_perm(struct inode *, int);
68
69static const struct file_operations dgnc_proc_file_ops =
70{
71 .owner = THIS_MODULE,
72 .read = dgnc_gen_proc_read, /* read */
73 .write = dgnc_gen_proc_write, /* write */
74 .open = dgnc_gen_proc_open, /* open */
75 .release = dgnc_gen_proc_close, /* release */
76};
77
78
79static struct inode_operations dgnc_proc_inode_ops =
80{
81 .permission = dgnc_proc_chk_perm
82};
83
84
85static void dgnc_register_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *);
86static void dgnc_unregister_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *);
87static void dgnc_remove_proc_entry(struct proc_dir_entry *pde);
88
89
90/* Stuff in /proc/ */
91static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
92 char __user *buffer, ssize_t *lenp, loff_t *ppos);
93static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
94 const char __user *buffer, ssize_t *lenp, loff_t *ppos);
95
96static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
97 char __user *buffer, ssize_t *lenp, loff_t *ppos);
98
99static struct dgnc_proc_entry dgnc_table[] = {
100 {DGNC_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_info, &dgnc_write_info,
101 NULL, __SEMAPHORE_INITIALIZER(dgnc_table[0].excl_sem, 1), 0, NULL },
102 {DGNC_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_mknod, NULL,
103 NULL, __SEMAPHORE_INITIALIZER(dgnc_table[1].excl_sem, 1), 0, NULL },
104 {0}
105};
106
107
108/* Stuff in /proc/<board>/ */
109static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
110 char __user *buffer, ssize_t *lenp, loff_t *ppos);
111static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp,
112 char __user *buffer, ssize_t *lenp, loff_t *ppos);
113static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
114 char __user *buffer, ssize_t *lenp, loff_t *ppos);
115static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp,
116 char __user *buffer, ssize_t *lenp, loff_t *ppos);
117static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp,
118 char __user *buffer, ssize_t *lenp, loff_t *ppos);
119static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp,
120 char __user *buffer, ssize_t *lenp, loff_t *ppos);
121
122static struct dgnc_proc_entry dgnc_board_table[] = {
123 {DGNC_BOARD_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_board_info, NULL,
124 NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[0].excl_sem, 1), 0, NULL },
125 {DGNC_BOARD_VPD, "vpd", 0600, NULL, NULL, NULL, &dgnc_read_board_vpd, NULL,
126 NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[1].excl_sem, 1), 0, NULL },
127 {DGNC_BOARD_TTYSTATS, "stats", 0600, NULL, NULL, NULL, &dgnc_read_board_ttystats, NULL,
128 NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[2].excl_sem, 1), 0, NULL },
129 {DGNC_BOARD_TTYINTR, "intr", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyintr, NULL,
130 NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[3].excl_sem, 1), 0, NULL },
131 {DGNC_BOARD_TTYFLAGS, "flags", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyflags, NULL,
132 NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[4].excl_sem, 1), 0, NULL },
133 {DGNC_BOARD_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_board_mknod, NULL,
134 NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[5].excl_sem, 1), 0, NULL },
135 {0}
136};
137
138
139/* Stuff in /proc/<board>/<channel> */
140static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
141 char __user *buffer, ssize_t *lenp, loff_t *ppos);
142static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
143 void *buffer, ssize_t *lenp, loff_t *ppos);
144static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
145 void *buffer, ssize_t *lenp, loff_t *ppos);
146static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
147 char __user *buffer, ssize_t *lenp, loff_t *ppos);
148static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp,
149 char __user *buffer, ssize_t *lenp, loff_t *ppos);
150static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp,
151 char __user *buffer, ssize_t *lenp, loff_t *ppos);
152
153static struct dgnc_proc_entry dgnc_channel_table[] = {
154 {DGNC_PORT_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_channel_info, NULL,
155 NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[0].excl_sem, 1), 0, NULL },
156 {DGNC_PORT_SNIFF, "sniff", 0600, NULL, &dgnc_open_channel_sniff, &dgnc_close_channel_sniff, &dgnc_read_channel_sniff, NULL,
157 NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[1].excl_sem, 1), 0, NULL},
158 {DGNC_PORT_CUSTOM_TTYNAME, "ttyname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_ttyname, NULL,
159 NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[2].excl_sem, 1), 0, NULL },
160 {DGNC_PORT_CUSTOM_PRNAME, "prname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_prname, NULL,
161 NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[3].excl_sem, 1), 0, NULL },
162 {0}
163};
164
165
166/*
167 * dgnc_test_perm does NOT grant the superuser all rights automatically, because
168 * some entries are readonly even to root.
169 */
170static inline int dgnc_test_perm(int mode, int op)
171{
172#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
173 if (!current->euid)
174#else
175 if (!current_euid())
176#endif
177 mode >>= 6;
178 else if (in_egroup_p(0))
179 mode >>= 3;
180 if ((mode & op & 0007) == op)
181 return 0;
182 if (capable(CAP_SYS_ADMIN))
183 return 0;
184 return -EACCES;
185}
186
187
188/*
189 * /proc/sys support
190 */
191static inline int dgnc_proc_match(int len, const char *name, struct proc_dir_entry *de)
192{
193 if (!de || !de->low_ino)
194 return 0;
195 if (de->namelen != len)
196 return 0;
197 return !memcmp(name, de->name, len);
198}
199
200
201/*
202 * Scan the entries in table and add them all to /proc at the position
203 * referred to by "root"
204 */
205static void dgnc_register_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root)
206{
207 struct proc_dir_entry *de;
208 int len;
209 mode_t mode;
210
211 for (; table->magic; table++) {
212 /* Can't do anything without a proc name. */
213 if (!table->name) {
214 DPR_PROC(("dgnc_register_proc_table, no name...\n"));
215 continue;
216 }
217
218 /* Maybe we can't do anything with it... */
219 if (!table->read_handler && !table->write_handler && !table->child) {
220 DPR_PROC((KERN_WARNING "DGNC PROC: Can't register %s\n", table->name));
221 continue;
222 }
223
224 len = strlen(table->name);
225 mode = table->mode;
226 de = NULL;
227
228 if (!table->child) {
229 mode |= S_IFREG;
230 } else {
231 mode |= S_IFDIR;
232 for (de = root->subdir; de; de = de->next) {
233 if (dgnc_proc_match(len, table->name, de))
234 break;
235 }
236
237 /* If the subdir exists already, de is non-NULL */
238 }
239
240 if (!de) {
241 de = create_proc_entry(table->name, mode, root);
242 if (!de)
243 continue;
244 de->data = (void *) table;
245 if (!table->child) {
246 de->proc_iops = &dgnc_proc_inode_ops;
247 de->proc_fops = &dgnc_proc_file_ops;
248 }
249 }
250
251 table->de = de;
252
253 if (de->mode & S_IFDIR)
254 dgnc_register_proc_table(table->child, de);
255
256 }
257}
258
259
260
261/*
262 * Unregister a /proc sysctl table and any subdirectories.
263 */
264static void dgnc_unregister_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root)
265{
266 struct proc_dir_entry *de;
267
268 for (; table->magic; table++) {
269 if (!(de = table->de))
270 continue;
271
272 if (de->mode & S_IFDIR) {
273 if (!table->child) {
274 DPR_PROC((KERN_ALERT "Help - malformed sysctl tree on free\n"));
275 continue;
276 }
277
278 /* recurse down into subdirectory... */
279 DPR_PROC(("Recursing down a directory...\n"));
280 dgnc_unregister_proc_table(table->child, de);
281
282 /* Don't unregister directories which still have entries.. */
283 if (de->subdir)
284 continue;
285 }
286
287 /* Don't unregister proc entries that are still being used.. */
288 if ((atomic_read(&de->count)) != 1) {
289 DPR_PROC(("proc entry in use... Not removing...\n"));
290 continue;
291 }
292
293 dgnc_remove_proc_entry(de);
294 table->de = NULL;
295 }
296}
297
298
299
300static int dgnc_gen_proc_open(struct inode *inode, struct file *file)
301{
302 struct proc_dir_entry *de;
303 struct dgnc_proc_entry *entry;
304 int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
305 void *buffer, ssize_t *lenp, loff_t *ppos);
306 int ret = 0, error = 0;
307
308 de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
309 if (!de || !de->data) {
310 ret = -ENXIO;
311 goto done;
312 }
313
314 entry = (struct dgnc_proc_entry *) de->data;
315 if (!entry) {
316 ret = -ENXIO;
317 goto done;
318 }
319
320 down(&entry->excl_sem);
321
322 if (entry->excl_cnt) {
323 ret = -EBUSY;
324 } else {
325 entry->excl_cnt++;
326
327 handler = entry->open_handler;
328 if (handler) {
329 error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL);
330 if (error) {
331 entry->excl_cnt--;
332 ret = error;
333 }
334 }
335 }
336
337 up(&entry->excl_sem);
338
339done:
340
341 return ret;
342}
343
344
345static int dgnc_gen_proc_close(struct inode *inode, struct file *file)
346{
347 struct proc_dir_entry *de;
348 int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
349 void *buffer, ssize_t *lenp, loff_t *ppos);
350 struct dgnc_proc_entry *entry;
351 int error = 0;
352
353 de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
354 if (!de || !de->data)
355 goto done;
356
357 entry = (struct dgnc_proc_entry *) de->data;
358 if (!entry)
359 goto done;
360
361 down(&entry->excl_sem);
362
363 if (entry->excl_cnt)
364 entry->excl_cnt = 0;
365
366
367 handler = entry->close_handler;
368 if (handler) {
369 error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL);
370 }
371
372 up(&entry->excl_sem);
373
374done:
375 return 0;
376}
377
378
379static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
380{
381 struct proc_dir_entry *de;
382 struct dgnc_proc_entry *entry;
383 int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
384 char __user *buffer, ssize_t *lenp, loff_t *ppos2);
385 ssize_t res;
386 ssize_t error;
387
388 de = (struct proc_dir_entry*) PDE(file->f_dentry->d_inode);
389 if (!de || !de->data)
390 return -ENXIO;
391
392 entry = (struct dgnc_proc_entry *) de->data;
393 if (!entry)
394 return -ENXIO;
395
396 /* Test for read permission */
397 if (dgnc_test_perm(entry->mode, 4))
398 return -EPERM;
399
400 res = count;
401
402 handler = entry->read_handler;
403 if (!handler)
404 return -ENXIO;
405
406 error = (*handler) (entry, OUTBOUND, file, buf, &res, ppos);
407 if (error)
408 return error;
409
410 return res;
411}
412
413
414static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf,
415 size_t count, loff_t *ppos)
416{
417 struct proc_dir_entry *de;
418 struct dgnc_proc_entry *entry;
419 int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
420 const char __user *buffer, ssize_t *lenp, loff_t *ppos2);
421 ssize_t res;
422 ssize_t error;
423
424 de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode);
425 if (!de || !de->data)
426 return -ENXIO;
427
428 entry = (struct dgnc_proc_entry *) de->data;
429 if (!entry)
430 return -ENXIO;
431
432 /* Test for write permission */
433 if (dgnc_test_perm(entry->mode, 2))
434 return -EPERM;
435
436 res = count;
437
438 handler = entry->write_handler;
439 if (!handler)
440 return -ENXIO;
441
442 error = (*handler) (entry, INBOUND, file, buf, &res, ppos);
443 if (error)
444 return error;
445
446 return res;
447}
448
449
450static int dgnc_proc_chk_perm(struct inode *inode, int op)
451{
452 return dgnc_test_perm(inode->i_mode, op);
453}
454
455
456/*
457 * Return what is (hopefully) useful information about the
458 * driver.
459 */
460static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
461 char __user *buffer, ssize_t *lenp, loff_t *ppos)
462{
463 static int done = 0;
464 static char buf[4096];
465 char *p = buf;
466
467 DPR_PROC(("dgnc_proc_info\n"));
468
469 if (done) {
470 done = 0;
471 *lenp = 0;
472 return 0;
473 }
474
475 p += sprintf(p, "Driver:\t\t%s\n", DG_NAME);
476 p += sprintf(p, "\n");
477 p += sprintf(p, "Debug:\t\t0x%x\n", dgnc_debug);
478 p += sprintf(p, "Sysfs Support:\t0x1\n");
479 p += sprintf(p, "Rawreadok:\t0x%x\n", dgnc_rawreadok);
480 p += sprintf(p, "Max Boards:\t%d\n", MAXBOARDS);
481 p += sprintf(p, "Total Boards:\t%d\n", dgnc_NumBoards);
482 p += sprintf(p, "Poll rate:\t%dms\n", dgnc_poll_tick);
483 p += sprintf(p, "Poll counter:\t%ld\n", dgnc_poll_counter);
484 p += sprintf(p, "State:\t\t%s\n", dgnc_driver_state_text[dgnc_driver_state]);
485
486 if (copy_to_user(buffer, buf, (p - (char *) buf)))
487 return -EFAULT;
488
489 *lenp = p - (char *) buf;
490 *ppos += p - (char *) buf;
491 done = 1;
492 return 0;
493}
494
495
496/*
497 * When writing to the "info" entry point, I actually allow one
498 * to modify certain variables. This may be a sleazy overload
499 * of this /proc entry, but I don't want:
500 *
501 * a. to clutter /proc more than I have to
502 * b. to overload the "config" entry, which would be somewhat
503 * more natural
504 * c. necessarily advertise the fact this ability exists
505 *
506 * The continued support of this feature has not yet been
507 * guaranteed.
508 *
509 * Writing operates on a "state machine" principle.
510 *
511 * State 0: waiting for a symbol to start. Waiting for anything
512 * which isn't " ' = or whitespace.
513 * State 1: reading a symbol. If the character is a space, move
514 * to state 2. If =, move to state 3. If " or ', move
515 * to state 0.
516 * State 2: Waiting for =... suck whitespace. If anything other
517 * than whitespace, drop to state 0.
518 * State 3: Got =. Suck whitespace waiting for value to start.
519 * If " or ', go to state 4 (and remember which quote it
520 * was). Otherwise, go to state 5.
521 * State 4: Reading value, within quotes. Everything is added to
522 * value up until the matching quote. When you hit the
523 * matching quote, try to set the variable, then state 0.
524 * State 5: Reading value, outside quotes. Everything not " ' =
525 * or whitespace goes in value. Hitting one of the
526 * terminators tosses us back to state 0 after trying to
527 * set the variable.
528 */
529typedef enum {
530 INFO_NONE, INFO_INT, INFO_CHAR, INFO_SHORT,
531 INFO_LONG, INFO_PTR, INFO_STRING, INFO_END
532} info_proc_var_val;
533
534static struct {
535 char *name;
536 info_proc_var_val type;
537 int rw; /* 0=readonly */
538 void *val_ptr;
539} dgnc_info_vars[] = {
540 { "rawreadok", INFO_INT, 1, (void *) &dgnc_rawreadok },
541 { "pollrate", INFO_INT, 1, (void *) &dgnc_poll_tick },
542 { NULL, INFO_NONE, 0, NULL },
543 { "debug", INFO_LONG, 1, (void *) &dgnc_debug },
544 { NULL, INFO_END, 0, NULL }
545};
546
547static void dgnc_set_info_var(char *name, char *val)
548{
549 int i;
550 unsigned long newval;
551 unsigned char charval;
552 unsigned short shortval;
553 unsigned int intval;
554
555 for (i = 0; dgnc_info_vars[i].type != INFO_END; i++) {
556 if (dgnc_info_vars[i].name)
557 if (!strcmp(name, dgnc_info_vars[i].name))
558 break;
559 }
560
561 if (dgnc_info_vars[i].type == INFO_END)
562 return;
563 if (dgnc_info_vars[i].rw == 0)
564 return;
565 if (dgnc_info_vars[i].val_ptr == NULL)
566 return;
567
568 newval = simple_strtoul(val, NULL, 0 );
569
570 switch (dgnc_info_vars[i].type) {
571 case INFO_CHAR:
572 charval = newval & 0xff;
573 APR(("Modifying %s (%lx) <= 0x%02x (%d)\n",
574 name, (long)(dgnc_info_vars[i].val_ptr ),
575 charval, charval));
576 *(uchar *)(dgnc_info_vars[i].val_ptr) = charval;
577 break;
578 case INFO_SHORT:
579 shortval = newval & 0xffff;
580 APR(("Modifying %s (%lx) <= 0x%04x (%d)\n",
581 name, (long)(dgnc_info_vars[i].val_ptr),
582 shortval, shortval));
583 *(ushort *)(dgnc_info_vars[i].val_ptr) = shortval;
584 break;
585 case INFO_INT:
586 intval = newval & 0xffffffff;
587 APR(("Modifying %s (%lx) <= 0x%08x (%d)\n",
588 name, (long)(dgnc_info_vars[i].val_ptr),
589 intval, intval));
590 *(uint *)(dgnc_info_vars[i].val_ptr) = intval;
591 break;
592 case INFO_LONG:
593 APR(("Modifying %s (%lx) <= 0x%lx (%ld)\n",
594 name, (long)(dgnc_info_vars[i].val_ptr),
595 newval, newval));
596 *(ulong *)(dgnc_info_vars[i].val_ptr) = newval;
597 break;
598 case INFO_PTR:
599 case INFO_STRING:
600 case INFO_END:
601 case INFO_NONE:
602 default:
603 break;
604 }
605}
606
607static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
608 const char __user *buffer, ssize_t *lenp, loff_t *ppos)
609{
610 static int state = 0;
611 #define MAXSYM 255
612 static int sympos, valpos;
613 static char sym[MAXSYM + 1];
614 static char val[MAXSYM + 1];
615 static int quotchar = 0;
616
617 int i;
618
619 long len;
620 #define INBUFLEN 256
621 char inbuf[INBUFLEN];
622
623 if (*ppos == 0) {
624 state = 0;
625 sympos = 0; sym[0] = 0;
626 valpos = 0; val[0] = 0;
627 quotchar = 0;
628 }
629
630 if ((!*lenp) || (dir != INBOUND)) {
631 *lenp = 0;
632 return 0;
633 }
634
635 len = *lenp;
636
637 if (len > INBUFLEN - 1)
638 len = INBUFLEN - 1;
639
640 if (copy_from_user(inbuf, buffer, len))
641 return -EFAULT;
642
643 inbuf[len] = 0;
644
645 for (i = 0; i < len; i++) {
646 unsigned char c = inbuf[i];
647
648 switch (state) {
649 case 0:
650 quotchar = sympos = valpos = sym[0] = val[0] = 0;
651 if (!isspace(c) && (c != '\"') &&
652 (c != '\'') && (c != '=')) {
653 sym[sympos++] = c;
654 state = 1;
655 break;
656 }
657 break;
658 case 1:
659 if (isspace(c)) {
660 sym[sympos] = 0;
661 state = 2;
662 break;
663 }
664 if (c == '=') {
665 sym[sympos] = 0;
666 state = 3;
667 break;
668 }
669 if ((c == '\"' ) || ( c == '\'' )) {
670 state = 0;
671 break;
672 }
673 if (sympos < MAXSYM) sym[sympos++] = c;
674 break;
675 case 2:
676 if (isspace(c)) break;
677 if (c == '=') {
678 state = 3;
679 break;
680 }
681 if ((c != '\"') && (c != '\'')) {
682 quotchar = sympos = valpos = sym[0] = val[0] = 0;
683 sym[sympos++] = c;
684 state = 1;
685 break;
686 }
687 state = 0;
688 break;
689 case 3:
690 if (isspace(c)) break;
691 if (c == '=') {
692 state = 0;
693 break;
694 }
695 if ((c == '\"') || (c == '\'')) {
696 state = 4;
697 quotchar = c;
698 break;
699 }
700 val[valpos++] = c;
701 state = 5;
702 break;
703 case 4:
704 if (c == quotchar) {
705 val[valpos] = 0;
706 dgnc_set_info_var(sym, val);
707 state = 0;
708 break;
709 }
710 if (valpos < MAXSYM) val[valpos++] = c;
711 break;
712 case 5:
713 if (isspace(c) || (c == '\"') ||
714 (c == '\'') || (c == '=')) {
715 val[valpos] = 0;
716 dgnc_set_info_var(sym, val);
717 state = 0;
718 break;
719 }
720 if (valpos < MAXSYM) val[valpos++] = c;
721 break;
722 default:
723 break;
724 }
725 }
726
727 *lenp = len;
728 *ppos += len;
729
730 return len;
731}
732
733
734/*
735 * Return mknod information for the driver's devices.
736 */
737static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
738 char __user *buffer, ssize_t *lenp, loff_t *ppos)
739{
740 static int done = 0;
741 static char buf[4096];
742 char *p = buf;
743 int i = 0;
744
745 DPR_PROC(("dgnc_proc_info\n"));
746
747 if (done) {
748 done = 0;
749 *lenp = 0;
750 return 0;
751 }
752
753 DPR_PROC(("dgnc_proc_mknod\n"));
754
755 p += sprintf(p, "#\tCreate the management devices.\n");
756
757 for (i = 0; i < MAXMGMTDEVICES; i++) {
758 char tmp[100];
759 sprintf(tmp, "/dev/dg/dgnc/mgmt%d", i);
760 p += sprintf(p, "%s\t%d\t%d\t%d\n",
761 tmp, dgnc_Major, i, 1);
762 }
763
764 if (copy_to_user(buffer, buf, (p - (char *) buf)))
765 return -EFAULT;
766
767 *lenp = p - (char *) buf;
768 *ppos += p - (char *) buf;
769 done = 1;
770 return 0;
771}
772
773
774/*
775 * Return what is (hopefully) useful information about the specific board.
776 */
777static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
778 char __user *buffer, ssize_t *lenp, loff_t *ppos)
779{
780 struct board_t *brd;
781 static int done = 0;
782 static char buf[4096];
783 char *p = buf;
784 char *name;
785
786 DPR_PROC(("dgnc_proc_brd_info\n"));
787
788 brd = (struct board_t *) table->data;
789
790 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
791 done = 0;
792 *lenp = 0;
793 return 0;
794 }
795
796 name = brd->name;
797
798 p += sprintf(p, "Board Name = %s\n", name);
799 if (brd->serial_num[0] == '\0')
800 p += sprintf(p, "Serial number = <UNKNOWN>\n");
801 else
802 p += sprintf(p, "Serial number = %s\n", brd->serial_num);
803
804 p += sprintf(p, "Board Type = %d\n", brd->type);
805 p += sprintf(p, "Number of Ports = %d\n", brd->nasync);
806
807 /*
808 * report some things about the PCI bus that are important
809 * to some applications
810 */
811 p += sprintf(p, "Vendor ID = 0x%x\n", brd->vendor);
812 p += sprintf(p, "Device ID = 0x%x\n", brd->device);
813 p += sprintf(p, "Subvendor ID = 0x%x\n", brd->subvendor);
814 p += sprintf(p, "Subdevice ID = 0x%x\n", brd->subdevice);
815 p += sprintf(p, "Bus = %d\n", brd->pci_bus);
816 p += sprintf(p, "Slot = %d\n", brd->pci_slot);
817
818 /*
819 * report the physical addresses assigned to us when we got
820 * registered
821 */
822 p += sprintf(p, "Memory Base Address = 0x%lx\n", brd->membase);
823 p += sprintf(p, "Remapped Memory Base Address = 0x%p\n", brd->re_map_membase);
824
825 p += sprintf(p, "Current state of board = %s\n", dgnc_state_text[brd->state]);
826 p += sprintf(p, "Interrupt #: %d. Times interrupted: %ld\n",
827 brd->irq, brd->intr_count);
828
829 p += sprintf(p, "TX interrupts: %ld RX interrupts: %ld\n",
830 brd->intr_tx, brd->intr_rx);
831 p += sprintf(p, "Modem interrupts: %ld\n", brd->intr_modem);
832
833 p += sprintf(p, "Majors allocated to board = TTY: %d PR: %d\n",
834 brd->SerialDriver.major, brd->PrintDriver.major);
835
836
837 if (copy_to_user(buffer, buf, (p - (char *) buf)))
838 return -EFAULT;
839
840 *lenp = p - (char *) buf;
841 *ppos += p - (char *) buf;
842 done = 1;
843 return 0;
844}
845
846
847
848static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp,
849 char __user *buffer, ssize_t *lenp, loff_t *ppos)
850{
851 struct board_t *brd;
852 static int done = 0;
853 static char buf[4096];
854 int i = 0, j = 0;
855 char *p = buf;
856
857 DPR_PROC(("dgnc_proc_brd_info\n"));
858
859 brd = (struct board_t *) table->data;
860
861 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
862 done = 0;
863 *lenp = 0;
864 return 0;
865 }
866
867 p += sprintf(p, "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII\n");
868
869 for (i = 0; i < 0x40 * 2; i++) {
870 j = i;
871 if (!(i % 16)) {
872 if (j > 0) {
873 p += sprintf(p, " ");
874 for (j = i - 16; j < i; j++) {
875 if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e)
876 p += sprintf(p, "%c", brd->vpd[j]);
877 else
878 p += sprintf(p, ".");
879 }
880 p += sprintf(p, "\n");
881 }
882 p += sprintf(p, "%04X ", i);
883 }
884 p += sprintf(p, "%02X ", brd->vpd[i]);
885 }
886 if (!(i % 16)) {
887 p += sprintf(p, " ");
888 for (j = i - 16; j < i; j++) {
889 if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e)
890 p += sprintf(p, "%c", brd->vpd[j]);
891 else
892 p += sprintf(p, ".");
893 }
894 p += sprintf(p, "\n");
895 }
896
897 p += sprintf(p, "\n");
898
899 if (copy_to_user(buffer, buf, (p - (char *) buf)))
900 return -EFAULT;
901
902 *lenp = p - (char *) buf;
903 *ppos += p - (char *) buf;
904 done = 1;
905 return 0;
906}
907
908
909/*
910 * Return what is (hopefully) useful stats about the specific board's ttys
911 */
912static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp,
913 char __user *buffer, ssize_t *lenp, loff_t *ppos)
914{
915 struct board_t *brd;
916 static int done = 0;
917 static char buf[4096];
918 char *p = buf;
919 int i = 0;
920
921 DPR_PROC(("dgnc_proc_brd_info\n"));
922
923 brd = (struct board_t *) table->data;
924
925 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
926 done = 0;
927 *lenp = 0;
928 return 0;
929 }
930
931 /* Prepare the Header Labels */
932 p += sprintf(p, "%2s %10s %23s %10s %9s\n",
933 "Ch", "Chars Rx", " Rx Par--Brk--Frm--Ovr",
934 "Chars Tx", "XON XOFF");
935
936 for (i = 0; i < brd->nasync; i++) {
937
938 struct channel_t *ch = brd->channels[i];
939
940 p += sprintf(p, "%2d ", i);
941 p += sprintf(p, "%10ld ", ch->ch_rxcount);
942 p += sprintf(p, " %4ld %4ld %4ld %4ld ", ch->ch_err_parity,
943 ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun);
944 p += sprintf(p, "%10ld ", ch->ch_txcount);
945 p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends);
946
947 p += sprintf(p, "\n");
948 }
949
950 if (copy_to_user(buffer, buf, (p - (char *) buf)))
951 return -EFAULT;
952
953 *lenp = p - (char *) buf;
954 *ppos += p - (char *) buf;
955 done = 1;
956 return 0;
957}
958
959
960/*
961 * Return what is (hopefully) useful stats about the specific board's tty intrs
962 */
963static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp,
964 char __user *buffer, ssize_t *lenp, loff_t *ppos)
965{
966 struct board_t *brd;
967 static int done = 0;
968 static char buf[4096];
969 char *p = buf;
970 int i = 0;
971
972 DPR_PROC(("dgnc_proc_brd_info\n"));
973
974 brd = (struct board_t *) table->data;
975
976 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
977 done = 0;
978 *lenp = 0;
979 return 0;
980 }
981
982 /* Prepare the Header Labels */
983 p += sprintf(p, "%2s %14s %14s %14s\n",
984 "Ch", "TX interrupts", "RX interrupts", "Modem interrupts");
985
986 for (i = 0; i < brd->nasync; i++) {
987
988 struct channel_t *ch = brd->channels[i];
989
990 p += sprintf(p, "%2d ", i);
991
992 p += sprintf(p, " %14ld %14ld %14ld",
993 ch->ch_intr_tx, ch->ch_intr_rx, ch->ch_intr_modem);
994
995 p += sprintf(p, "\n");
996 }
997
998 if (copy_to_user(buffer, buf, (p - (char *) buf)))
999 return -EFAULT;
1000
1001 *lenp = p - (char *) buf;
1002 *ppos += p - (char *) buf;
1003 done = 1;
1004 return 0;
1005}
1006
1007
1008/*
1009 * Return what is (hopefully) useful flags about the specific board's ttys
1010 */
1011static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp,
1012 char __user *buffer, ssize_t *lenp, loff_t *ppos)
1013{
1014 struct board_t *brd;
1015 static int done = 0;
1016 static char buf[4096];
1017 char *p = buf;
1018 int i = 0;
1019
1020 DPR_PROC(("dgnc_proc_brd_info\n"));
1021
1022 brd = (struct board_t *) table->data;
1023
1024 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
1025 done = 0;
1026 *lenp = 0;
1027 return 0;
1028 }
1029
1030 /* Prepare the Header Labels */
1031 p += sprintf(p, "%2s %5s %5s %5s %5s %5s %10s Line Status Flags\n",
1032 "Ch", "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud");
1033
1034 for (i = 0; i < brd->nasync; i++) {
1035
1036 struct channel_t *ch = brd->channels[i];
1037
1038 p += sprintf(p, "%2d ", i);
1039 p += sprintf(p, "%5x ", ch->ch_c_cflag);
1040 p += sprintf(p, "%5x ", ch->ch_c_iflag);
1041 p += sprintf(p, "%5x ", ch->ch_c_oflag);
1042 p += sprintf(p, "%5x ", ch->ch_c_lflag);
1043 p += sprintf(p, "%5x ", ch->ch_digi.digi_flags);
1044 p += sprintf(p, "%10d ", ch->ch_old_baud);
1045
1046 if (!ch->ch_open_count) {
1047 p += sprintf(p, " -- -- -- -- -- -- --") ;
1048 } else {
1049 p += sprintf(p, " op %s %s %s %s %s %s",
1050 (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--",
1051 (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--",
1052 (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--",
1053 (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--",
1054 (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--",
1055 (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--");
1056 }
1057
1058 p += sprintf(p, "\n");
1059 }
1060 if (copy_to_user(buffer, buf, (p - (char *) buf)))
1061 return -EFAULT;
1062
1063 *lenp = p - (char *) buf;
1064 *ppos += p - (char *) buf;
1065 done = 1;
1066 return 0;
1067}
1068
1069
1070/*
1071 * Return mknod information for the board's devices.
1072 */
1073static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp,
1074 char __user *buffer, ssize_t *lenp, loff_t *ppos)
1075{
1076 struct board_t *brd;
1077 static int done = 0;
1078 static char buf[4096];
1079 char str[MAXTTYNAMELEN];
1080 char *p = buf;
1081
1082 DPR_PROC(("dgnc_proc_brd_info\n"));
1083
1084 brd = (struct board_t *) table->data;
1085
1086 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
1087 done = 0;
1088 *lenp = 0;
1089 return 0;
1090 }
1091
1092 /*
1093 * For each board, output the device information in
1094 * a handy table format...
1095 */
1096 p += sprintf(p, "# Create the TTY and PR devices\n");
1097
1098 /* TTY devices */
1099 sprintf(str, "ttyn%d%%p", brd->boardnum + 1);
1100 p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str,
1101 brd->dgnc_Serial_Major, 0, brd->maxports);
1102
1103 /* PR devices */
1104 sprintf(str, "prn%d%%p", brd->boardnum + 1);
1105 p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str,
1106 brd->dgnc_TransparentPrint_Major, 128, brd->maxports);
1107
1108 if (copy_to_user(buffer, buf, (p - (char *) buf)))
1109 return -EFAULT;
1110
1111 *lenp = p - (char *) buf;
1112 *ppos += p - (char *) buf;
1113 done = 1;
1114 return 0;
1115}
1116
1117
1118/*
1119 * Return what is (hopefully) useful information about the specific channel.
1120 */
1121static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
1122 char __user *buffer, ssize_t *lenp, loff_t *ppos)
1123{
1124 struct channel_t *ch;
1125 static int done = 0;
1126 static char buf[4096];
1127 char *p = buf;
1128
1129 DPR_PROC(("dgnc_proc_info\n"));
1130
1131 ch = (struct channel_t *) table->data;
1132
1133 if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
1134 done = 0;
1135 *lenp = 0;
1136 return 0;
1137 }
1138
1139 p += sprintf(p, "Port number:\t\t%d\n", ch->ch_portnum);
1140 p += sprintf(p, "\n");
1141
1142 /* Prepare the Header Labels */
1143 p += sprintf(p, "%10s %23s %10s %9s\n",
1144 "Chars Rx", " Rx Par--Brk--Frm--Ovr",
1145 "Chars Tx", "XON XOFF");
1146 p += sprintf(p, "%10ld ", ch->ch_rxcount);
1147 p += sprintf(p, " %4ld %4ld %4ld %4ld ", ch->ch_err_parity,
1148 ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun);
1149 p += sprintf(p, "%10ld ", ch->ch_txcount);
1150 p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends);
1151 p += sprintf(p, "\n\n");
1152
1153 /* Prepare the Header Labels */
1154 p += sprintf(p, "%5s %5s %5s %5s %5s %10s Line Status Flags\n",
1155 "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud");
1156
1157 p += sprintf(p, "%5x ", ch->ch_c_cflag);
1158 p += sprintf(p, "%5x ", ch->ch_c_iflag);
1159 p += sprintf(p, "%5x ", ch->ch_c_oflag);
1160 p += sprintf(p, "%5x ", ch->ch_c_lflag);
1161 p += sprintf(p, "%5x ", ch->ch_digi.digi_flags);
1162 p += sprintf(p, "%10d ", ch->ch_old_baud);
1163 if (!ch->ch_open_count) {
1164 p += sprintf(p, " -- -- -- -- -- -- --") ;
1165 } else {
1166 p += sprintf(p, " op %s %s %s %s %s %s",
1167 (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--",
1168 (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--",
1169 (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--",
1170 (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--",
1171 (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--",
1172 (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--");
1173 }
1174 p += sprintf(p, "\n\n");
1175
1176 if (copy_to_user(buffer, buf, (p - (char *) buf)))
1177 return -EFAULT;
1178
1179 *lenp = p - (char *) buf;
1180 *ppos += p - (char *) buf;
1181 done = 1;
1182 return 0;
1183}
1184
1185
1186/*
1187 * Return mknod information for the board's devices.
1188 */
1189static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp,
1190 char __user *buffer, ssize_t *lenp, loff_t *ppos)
1191{
1192 struct channel_t *ch;
1193 struct board_t *brd;
1194 static int done = 0;
1195 static char buf[4096];
1196 char *p = buf;
1197 int cn;
1198 int bn;
1199
1200 DPR_PROC(("dgnc_proc_brd_info\n"));
1201
1202 ch = (struct channel_t *) table->data;
1203
1204 if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
1205 done = 0;
1206 *lenp = 0;
1207 return 0;
1208 }
1209
1210 brd = ch->ch_bd;
1211
1212 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
1213 done = 0;
1214 *lenp = 0;
1215 return 0;
1216 }
1217
1218 bn = brd->boardnum;
1219 cn = ch->ch_portnum;
1220
1221 p += sprintf(p, "ttyn%d%c\n", bn + 1, 'a' + cn);
1222
1223 if (copy_to_user(buffer, buf, (p - (char *) buf)))
1224 return -EFAULT;
1225
1226 *lenp = p - (char *) buf;
1227 *ppos += p - (char *) buf;
1228 done = 1;
1229 return 0;
1230}
1231
1232
1233
1234
1235/*
1236 * Return mknod information for the board's devices.
1237 */
1238static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp,
1239 char __user *buffer, ssize_t *lenp, loff_t *ppos)
1240{
1241 struct channel_t *ch;
1242 struct board_t *brd;
1243 static int done = 0;
1244 static char buf[4096];
1245 char *p = buf;
1246 int cn;
1247 int bn;
1248
1249 DPR_PROC(("dgnc_proc_brd_info\n"));
1250
1251 ch = (struct channel_t *) table->data;
1252
1253 if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
1254 done = 0;
1255 *lenp = 0;
1256 return 0;
1257 }
1258
1259 brd = ch->ch_bd;
1260
1261 if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) {
1262 done = 0;
1263 *lenp = 0;
1264 return 0;
1265 }
1266
1267 bn = brd->boardnum;
1268 cn = ch->ch_portnum;
1269
1270 p += sprintf(p, "prn%d%c\n", bn + 1, 'a' + cn);
1271
1272 if (copy_to_user(buffer, buf, (p - (char *) buf)))
1273 return -EFAULT;
1274
1275 *lenp = p - (char *) buf;
1276 *ppos += p - (char *) buf;
1277 done = 1;
1278 return 0;
1279}
1280
1281
1282static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
1283 void *buffer, ssize_t *lenp, loff_t *ppos)
1284{
1285 struct channel_t *ch;
1286 ulong lock_flags;
1287
1288 ch = (struct channel_t *) table->data;
1289
1290 if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC))
1291 return 0;
1292
1293 ch->ch_sniff_buf = dgnc_driver_kzmalloc(SNIFF_MAX, GFP_KERNEL);
1294
1295 DGNC_LOCK(ch->ch_lock, lock_flags);
1296 ch->ch_sniff_flags |= SNIFF_OPEN;
1297 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1298
1299 return 0;
1300}
1301
1302static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
1303 void *buffer, ssize_t *lenp, loff_t *ppos)
1304{
1305 struct channel_t *ch;
1306 ulong lock_flags;
1307
1308 ch = (struct channel_t *) table->data;
1309
1310 if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC))
1311 return 0;
1312
1313 DGNC_LOCK(ch->ch_lock, lock_flags);
1314 ch->ch_sniff_flags &= ~(SNIFF_OPEN);
1315 kfree(ch->ch_sniff_buf);
1316 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1317
1318 return 0;
1319}
1320
1321
1322/*
1323 * Copy data from the monitoring buffer to the user, freeing space
1324 * in the monitoring buffer for more messages
1325 *
1326 */
1327static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
1328 char __user *buffer, ssize_t *lenp, loff_t *ppos)
1329{
1330 struct channel_t *ch;
1331 int n;
1332 int r;
1333 int offset = 0;
1334 int res = 0;
1335 ssize_t rtn = 0;
1336 ulong lock_flags;
1337
1338 ch = (struct channel_t *) table->data;
1339
1340 if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) {
1341 rtn = -ENXIO;
1342 goto done;
1343 }
1344
1345 /*
1346 * Wait for some data to appear in the buffer.
1347 */
1348 DGNC_LOCK(ch->ch_lock, lock_flags);
1349
1350 for (;;) {
1351 n = (ch->ch_sniff_in - ch->ch_sniff_out) & SNIFF_MASK;
1352
1353 if (n != 0)
1354 break;
1355
1356 ch->ch_sniff_flags |= SNIFF_WAIT_DATA;
1357
1358 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1359
1360 /*
1361 * Go to sleep waiting until the condition becomes true.
1362 */
1363 rtn = wait_event_interruptible(ch->ch_sniff_wait,
1364 ((ch->ch_sniff_flags & SNIFF_WAIT_DATA) == 0));
1365
1366 if (rtn)
1367 goto done;
1368
1369 DGNC_LOCK(ch->ch_lock, lock_flags);
1370 }
1371
1372 /*
1373 * Read whatever is there.
1374 */
1375
1376 if (n > *lenp)
1377 n = *lenp;
1378
1379 res = n;
1380
1381 r = SNIFF_MAX - ch->ch_sniff_out;
1382
1383 if (r <= n) {
1384 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1385 rtn = copy_to_user(buffer, ch->ch_sniff_buf + ch->ch_sniff_out, r);
1386 if (rtn) {
1387 rtn = -EFAULT;
1388 goto done;
1389 }
1390
1391 DGNC_LOCK(ch->ch_lock, lock_flags);
1392
1393 ch->ch_sniff_out = 0;
1394 n -= r;
1395 offset = r;
1396 }
1397
1398 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1399 rtn = copy_to_user(buffer + offset, ch->ch_sniff_buf + ch->ch_sniff_out, n);
1400 if (rtn) {
1401 rtn = -EFAULT;
1402 goto done;
1403 }
1404 DGNC_LOCK(ch->ch_lock, lock_flags);
1405
1406 ch->ch_sniff_out += n;
1407 *ppos += res;
1408 rtn = res;
1409// rtn = 0;
1410
1411 /*
1412 * Wakeup any thread waiting for buffer space.
1413 */
1414
1415 if (ch->ch_sniff_flags & SNIFF_WAIT_SPACE) {
1416 ch->ch_sniff_flags &= ~SNIFF_WAIT_SPACE;
1417 wake_up_interruptible(&ch->ch_sniff_wait);
1418 }
1419
1420 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1421
1422done:
1423 return rtn;
1424}
1425
1426
1427/*
1428 * Register the basic /proc/dgnc files that appear whenever
1429 * the driver is loaded.
1430 */
1431void dgnc_proc_register_basic_prescan(void)
1432{
1433 /*
1434 * Register /proc/dgnc
1435 */
1436 ProcDGNC = proc_create("dgnc", (0700 | S_IFDIR), NULL, &dgnc_proc_file_ops);
1437 dgnc_register_proc_table(dgnc_table, ProcDGNC);
1438}
1439
1440
1441/*
1442 * Register the basic /proc/dgnc files that appear whenever
1443 * the driver is loaded.
1444 */
1445void dgnc_proc_register_basic_postscan(int board_num)
1446{
1447 int i, j;
1448 char board[10];
1449 sprintf(board, "%d", board_num);
1450
1451 /* Set proc board entry pointer */
1452 dgnc_Board[board_num]->proc_entry_pointer = create_proc_entry(board, (0700 | S_IFDIR), ProcDGNC);
1453
1454 /* Create a new copy of the board_table... */
1455 dgnc_Board[board_num]->dgnc_board_table = dgnc_driver_kzmalloc(sizeof(dgnc_board_table),
1456 GFP_KERNEL);
1457
1458 /* Now copy the default table into that memory */
1459 memcpy(dgnc_Board[board_num]->dgnc_board_table, dgnc_board_table, sizeof(dgnc_board_table));
1460
1461 /* Initialize semaphores in each table slot */
1462 for (i = 0; i < 999; i++) {
1463 if (!dgnc_Board[board_num]->dgnc_board_table[i].magic) {
1464 break;
1465 }
1466
1467 init_MUTEX(&(dgnc_Board[board_num]->dgnc_board_table[i].excl_sem));
1468 dgnc_Board[board_num]->dgnc_board_table[i].data = dgnc_Board[board_num];
1469
1470 }
1471
1472 /* Register board table into proc */
1473 dgnc_register_proc_table(dgnc_Board[board_num]->dgnc_board_table,
1474 dgnc_Board[board_num]->proc_entry_pointer);
1475
1476 /*
1477 * Add new entries for each port.
1478 */
1479 for (i = 0; i < dgnc_Board[board_num]->nasync; i++) {
1480
1481 char channel[10];
1482 sprintf(channel, "%d", i);
1483
1484 /* Set proc channel entry pointer */
1485 dgnc_Board[board_num]->channels[i]->proc_entry_pointer =
1486 create_proc_entry(channel, (0700 | S_IFDIR),
1487 dgnc_Board[board_num]->proc_entry_pointer);
1488
1489 /* Create a new copy of the channel_table... */
1490 dgnc_Board[board_num]->channels[i]->dgnc_channel_table =
1491 dgnc_driver_kzmalloc(sizeof(dgnc_channel_table), GFP_KERNEL);
1492
1493 /* Now copy the default table into that memory */
1494 memcpy(dgnc_Board[board_num]->channels[i]->dgnc_channel_table,
1495 dgnc_channel_table, sizeof(dgnc_channel_table));
1496
1497 /* Initialize semaphores in each table slot */
1498 for (j = 0; j < 999; j++) {
1499 if (!dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].magic) {
1500 break;
1501 }
1502
1503 init_MUTEX(&(dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].excl_sem));
1504 dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].data =
1505 dgnc_Board[board_num]->channels[i];
1506 }
1507
1508 /* Register channel table into proc */
1509 dgnc_register_proc_table(dgnc_Board[board_num]->channels[i]->dgnc_channel_table,
1510 dgnc_Board[board_num]->channels[i]->proc_entry_pointer);
1511 }
1512}
1513
1514
1515static void dgnc_remove_proc_entry(struct proc_dir_entry *pde)
1516{
1517 if (!pde) {
1518 DPR_PROC(("dgnc_remove_proc_entry... NULL entry... not removing...\n"));
1519 return;
1520 }
1521
1522 remove_proc_entry(pde->name, pde->parent);
1523}
1524
1525
1526void dgnc_proc_unregister_all(void)
1527{
1528 int i = 0, j = 0;
1529
1530 /* Walk each board, blowing away their proc entries... */
1531 for (i = 0; i < dgnc_NumBoards; i++) {
1532
1533 /* Walk each channel, blowing away their proc entries... */
1534 for (j = 0; j < dgnc_Board[i]->nasync; j++) {
1535
1536 dgnc_unregister_proc_table(dgnc_Board[i]->channels[j]->dgnc_channel_table,
1537 dgnc_Board[i]->channels[j]->proc_entry_pointer);
1538 dgnc_remove_proc_entry(dgnc_Board[i]->channels[j]->proc_entry_pointer);
1539 kfree(dgnc_Board[i]->channels[j]->dgnc_channel_table);
1540 }
1541
1542 dgnc_unregister_proc_table(dgnc_Board[i]->dgnc_board_table,
1543 dgnc_Board[i]->proc_entry_pointer);
1544 dgnc_remove_proc_entry(dgnc_Board[i]->proc_entry_pointer);
1545 kfree(dgnc_Board[i]->dgnc_board_table);
1546 }
1547
1548 /* Blow away the top proc entry */
1549 dgnc_unregister_proc_table(dgnc_table, ProcDGNC);
1550 dgnc_remove_proc_entry(ProcDGNC);
1551}
diff --git a/drivers/staging/dgnc/dgnc_proc.h b/drivers/staging/dgnc/dgnc_proc.h
new file mode 100644
index 000000000000..19670e29d570
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_proc.h
@@ -0,0 +1,147 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 *
21 *
22 * $Id: dgnc_proc.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
23 *
24 * Description:
25 *
26 * Describes the private structures used to manipulate the "special"
27 * proc constructs (not read-only) used by the Digi Neo software.
28 * The concept is borrowed heavily from the "sysctl" interface of
29 * the kernel. I decided not to use the structures and functions
30 * provided by the kernel for two reasons:
31 *
32 * 1. Due to the planned use of "/proc" in the Neo driver, many
33 * of the functions of the "sysctl" interface would go unused.
34 * A simpler interface will be easier to maintain.
35 *
36 * 2. I'd rather divorce our "added package" from the kernel internals.
37 * If the "sysctl" structures should change, I will be insulated
38 * from those changes. These "/proc" entries won't be under the
39 * "sys" tree anyway, so there is no need to maintain a strict
40 * dependence relationship.
41 *
42 * Author:
43 *
44 * Scott H Kilau
45 *
46 */
47
48#ifndef _DGNC_RW_PROC_H
49#define _DGNC_RW_PROC_H
50
51/*
52 * The list of DGNC entries with r/w capabilities.
53 * These magic numbers are used for identification purposes.
54 */
55enum {
56 DGNC_INFO = 1, /* Get info about the running module */
57 DGNC_MKNOD = 2, /* Get info about driver devices */
58 DGNC_BOARD_INFO = 3, /* Get info about the specific board */
59 DGNC_BOARD_VPD = 4, /* Get info about the board's VPD */
60 DGNC_BOARD_TTYSTATS = 5, /* Get info about the board's tty stats */
61 DGNC_BOARD_TTYINTR = 6, /* Get info about the board's tty intrs */
62 DGNC_BOARD_TTYFLAGS = 7, /* Get info about the board's tty flags */
63 DGNC_BOARD_MKNOD = 8, /* Get info about board devices */
64 DGNC_PORT_INFO = 9, /* Get info about the specific port */
65 DGNC_PORT_SNIFF = 10, /* Sniff data in/out of specific port */
66 DGNC_PORT_CUSTOM_TTYNAME = 11, /* Get info about UDEV tty name */
67 DGNC_PORT_CUSTOM_PRNAME = 12, /* Get info about UDEV pr name */
68};
69
70/*
71 * Directions for proc handlers
72 */
73enum {
74 INBOUND = 1, /* Data being written to kernel */
75 OUTBOUND = 2, /* Data being read from the kernel */
76};
77
78/*
79 * Each entry in a DGNC proc directory is described with a
80 * "dgnc_proc_entry" structure. A collection of these
81 * entries (in an array) represents the members associated
82 * with a particular "/proc" directory, and is referred to
83 * as a table. All "tables" are terminated by an entry with
84 * zeros for every member.
85 *
86 * The structure members are as follows:
87 *
88 * int magic -- ID number associated with this particular
89 * entry. Should be unique across all of
90 * DGNC.
91 *
92 * const char *name -- ASCII name associated with the /proc entry.
93 *
94 * mode_t mode -- File access permisssions for the /proc entry.
95 *
96 * dgnc_proc_entry *child -- When set, this entry refers to a directory,
97 * and points to the table which describes the
98 * entries in the subdirectory
99 *
100 * dgnc_proc_handler *open_handler -- When set, points to the fxn which
101 * does any "extra" open stuff.
102 *
103 * dgnc_proc_handler *close_handler -- When set, points to the fxn which
104 * does any "extra" close stuff.
105 *
106 * dgnc_proc_handler *read_handler -- When set, points to the fxn which
107 * handle outbound data flow
108 *
109 * dgnc_proc_handler *write_handler -- When set, points to the fxn which
110 * handles inbound data flow
111 *
112 * struct proc_dir_entry *de -- Pointer to the directory entry for this
113 * object once registered. Used to grab
114 * the handle of the object for
115 * unregistration
116 *
117 * void *data; When set, points to the parent structure
118 *
119 */
120
121struct dgnc_proc_entry {
122 int magic; /* Integer identifier */
123 const char *name; /* ASCII identifier */
124 mode_t mode; /* File access permissions */
125 struct dgnc_proc_entry *child; /* Child pointer */
126
127 int (*open_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
128 void *buffer, ssize_t *lenp, loff_t *ppos);
129 int (*close_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
130 void *buffer, ssize_t *lenp, loff_t *ppos);
131 int (*read_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
132 char __user *buffer, ssize_t *lenp, loff_t *ppos);
133 int (*write_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp,
134 const char __user *buffer, ssize_t *lenp, loff_t *ppos);
135
136 struct proc_dir_entry *de; /* proc entry pointer */
137 struct semaphore excl_sem; /* Protects exclusive access var */
138 int excl_cnt; /* Counts number of curr accesses */
139 void *data; /* Allows storing a pointer to parent */
140};
141
142void dgnc_proc_register_basic_prescan(void);
143void dgnc_proc_register_basic_postscan(int board_num);
144void dgnc_proc_unregister_all(void);
145
146
147#endif /* _DGNC_RW_PROC_H */
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c
new file mode 100644
index 000000000000..af49e44382f5
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_sysfs.c
@@ -0,0 +1,761 @@
1/*
2 * Copyright 2004 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 *
31 *
32 * $Id: dgnc_sysfs.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
33 */
34
35
36#include <linux/kernel.h>
37#include <linux/version.h>
38#include <linux/module.h>
39#include <linux/ctype.h>
40#include <linux/string.h>
41#include <linux/serial_reg.h>
42#include <linux/device.h>
43#include <linux/pci.h>
44#include <linux/kdev_t.h>
45
46#include "dgnc_driver.h"
47#include "dgnc_proc.h"
48#include "dgnc_mgmt.h"
49
50
51static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf)
52{
53 return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
54}
55static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL);
56
57
58static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf)
59{
60 return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards);
61}
62static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL);
63
64
65static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf)
66{
67 return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
68}
69static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL);
70
71
72static ssize_t dgnc_driver_pollcounter_show(struct device_driver *ddp, char *buf)
73{
74 return snprintf(buf, PAGE_SIZE, "%ld\n", dgnc_poll_counter);
75}
76static DRIVER_ATTR(pollcounter, S_IRUSR, dgnc_driver_pollcounter_show, NULL);
77
78
79static ssize_t dgnc_driver_state_show(struct device_driver *ddp, char *buf)
80{
81 return snprintf(buf, PAGE_SIZE, "%s\n", dgnc_driver_state_text[dgnc_driver_state]);
82}
83static DRIVER_ATTR(state, S_IRUSR, dgnc_driver_state_show, NULL);
84
85
86static ssize_t dgnc_driver_debug_show(struct device_driver *ddp, char *buf)
87{
88 return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_debug);
89}
90
91static ssize_t dgnc_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
92{
93 sscanf(buf, "0x%x\n", &dgnc_debug);
94 return count;
95}
96static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgnc_driver_debug_show, dgnc_driver_debug_store);
97
98
99static ssize_t dgnc_driver_rawreadok_show(struct device_driver *ddp, char *buf)
100{
101 return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_rawreadok);
102}
103
104static ssize_t dgnc_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
105{
106 sscanf(buf, "0x%x\n", &dgnc_rawreadok);
107 return count;
108}
109static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgnc_driver_rawreadok_show, dgnc_driver_rawreadok_store);
110
111
112static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf)
113{
114 return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick);
115}
116
117static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
118{
119 sscanf(buf, "%d\n", &dgnc_poll_tick);
120 return count;
121}
122static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store);
123
124
125void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
126{
127 int rc = 0;
128 struct device_driver *driverfs = &dgnc_driver->driver;
129
130 rc |= driver_create_file(driverfs, &driver_attr_version);
131 rc |= driver_create_file(driverfs, &driver_attr_boards);
132 rc |= driver_create_file(driverfs, &driver_attr_maxboards);
133 rc |= driver_create_file(driverfs, &driver_attr_debug);
134 rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
135 rc |= driver_create_file(driverfs, &driver_attr_pollrate);
136 rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
137 rc |= driver_create_file(driverfs, &driver_attr_state);
138 if (rc) {
139 printk(KERN_ERR "DGNC: sysfs driver_create_file failed!\n");
140 }
141}
142
143
144void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
145{
146 struct device_driver *driverfs = &dgnc_driver->driver;
147 driver_remove_file(driverfs, &driver_attr_version);
148 driver_remove_file(driverfs, &driver_attr_boards);
149 driver_remove_file(driverfs, &driver_attr_maxboards);
150 driver_remove_file(driverfs, &driver_attr_debug);
151 driver_remove_file(driverfs, &driver_attr_rawreadok);
152 driver_remove_file(driverfs, &driver_attr_pollrate);
153 driver_remove_file(driverfs, &driver_attr_pollcounter);
154 driver_remove_file(driverfs, &driver_attr_state);
155}
156
157
158#define DGNC_VERIFY_BOARD(p, bd) \
159 if (!p) \
160 return (0); \
161 \
162 bd = dev_get_drvdata(p); \
163 if (!bd || bd->magic != DGNC_BOARD_MAGIC) \
164 return (0); \
165 if (bd->state != BOARD_READY) \
166 return (0); \
167
168
169
170static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf)
171{
172 struct board_t *bd;
173 int count = 0;
174 int i = 0;
175
176 DGNC_VERIFY_BOARD(p, bd);
177
178 count += sprintf(buf + count, "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F");
179 for (i = 0; i < 0x40 * 2; i++) {
180 if (!(i % 16))
181 count += sprintf(buf + count, "\n%04X ", i * 2);
182 count += sprintf(buf + count, "%02X ", bd->vpd[i]);
183 }
184 count += sprintf(buf + count, "\n");
185
186 return count;
187}
188static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL);
189
190static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf)
191{
192 struct board_t *bd;
193 int count = 0;
194
195 DGNC_VERIFY_BOARD(p, bd);
196
197 if (bd->serial_num[0] == '\0')
198 count += sprintf(buf + count, "<UNKNOWN>\n");
199 else
200 count += sprintf(buf + count, "%s\n", bd->serial_num);
201
202 return count;
203}
204static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL);
205
206
207static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
208{
209 struct board_t *bd;
210 int count = 0;
211 int i = 0;
212
213 DGNC_VERIFY_BOARD(p, bd);
214
215 for (i = 0; i < bd->nasync; i++) {
216 count += snprintf(buf + count, PAGE_SIZE - count,
217 "%d %s\n", bd->channels[i]->ch_portnum,
218 bd->channels[i]->ch_open_count ? "Open" : "Closed");
219 }
220 return count;
221}
222static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL);
223
224
225static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
226{
227 struct board_t *bd;
228 int count = 0;
229 int i = 0;
230
231 DGNC_VERIFY_BOARD(p, bd);
232
233 for (i = 0; i < bd->nasync; i++) {
234 count += snprintf(buf + count, PAGE_SIZE - count,
235 "%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_old_baud);
236 }
237 return count;
238}
239static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL);
240
241
242static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
243{
244 struct board_t *bd;
245 int count = 0;
246 int i = 0;
247
248 DGNC_VERIFY_BOARD(p, bd);
249
250 for (i = 0; i < bd->nasync; i++) {
251 if (bd->channels[i]->ch_open_count) {
252 count += snprintf(buf + count, PAGE_SIZE - count,
253 "%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
254 (bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
255 (bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
256 (bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
257 (bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
258 (bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
259 (bd->channels[i]->ch_mistat & UART_MSR_RI) ? "RI" : "");
260 } else {
261 count += snprintf(buf + count, PAGE_SIZE - count,
262 "%d\n", bd->channels[i]->ch_portnum);
263 }
264 }
265 return count;
266}
267static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL);
268
269
270static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
271{
272 struct board_t *bd;
273 int count = 0;
274 int i = 0;
275
276 DGNC_VERIFY_BOARD(p, bd);
277
278 for (i = 0; i < bd->nasync; i++) {
279 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
280 bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
281 }
282 return count;
283}
284static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL);
285
286
287static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
288{
289 struct board_t *bd;
290 int count = 0;
291 int i = 0;
292
293 DGNC_VERIFY_BOARD(p, bd);
294
295 for (i = 0; i < bd->nasync; i++) {
296 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
297 bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
298 }
299 return count;
300}
301static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL);
302
303
304static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
305{
306 struct board_t *bd;
307 int count = 0;
308 int i = 0;
309
310 DGNC_VERIFY_BOARD(p, bd);
311
312 for (i = 0; i < bd->nasync; i++) {
313 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
314 bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
315 }
316 return count;
317}
318static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL);
319
320
321static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
322{
323 struct board_t *bd;
324 int count = 0;
325 int i = 0;
326
327 DGNC_VERIFY_BOARD(p, bd);
328
329 for (i = 0; i < bd->nasync; i++) {
330 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
331 bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
332 }
333 return count;
334}
335static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL);
336
337
338static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
339{
340 struct board_t *bd;
341 int count = 0;
342 int i = 0;
343
344 DGNC_VERIFY_BOARD(p, bd);
345
346 for (i = 0; i < bd->nasync; i++) {
347 count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
348 bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
349 }
350 return count;
351}
352static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL);
353
354
355static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
356{
357 struct board_t *bd;
358 int count = 0;
359 int i = 0;
360
361 DGNC_VERIFY_BOARD(p, bd);
362
363 for (i = 0; i < bd->nasync; i++) {
364 count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
365 bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
366 }
367 return count;
368}
369static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL);
370
371
372static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
373{
374 struct board_t *bd;
375 int count = 0;
376 int i = 0;
377
378 DGNC_VERIFY_BOARD(p, bd);
379
380 for (i = 0; i < bd->nasync; i++) {
381 count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
382 bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
383 }
384 return count;
385}
386static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL);
387
388
389/* this function creates the sys files that will export each signal status
390 * to sysfs each value will be put in a separate filename
391 */
392void dgnc_create_ports_sysfiles(struct board_t *bd)
393{
394 int rc = 0;
395
396 dev_set_drvdata(&bd->pdev->dev, bd);
397 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
398 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
399 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
400 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
401 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
402 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
403 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
404 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
405 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
406 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
407 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_vpd);
408 rc |= device_create_file(&(bd->pdev->dev), &dev_attr_serial_number);
409 if (rc) {
410 printk(KERN_ERR "DGNC: sysfs device_create_file failed!\n");
411 }
412}
413
414
415/* removes all the sys files created for that port */
416void dgnc_remove_ports_sysfiles(struct board_t *bd)
417{
418 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
419 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
420 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
421 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
422 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
423 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
424 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
425 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
426 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
427 device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
428 device_remove_file(&(bd->pdev->dev), &dev_attr_vpd);
429 device_remove_file(&(bd->pdev->dev), &dev_attr_serial_number);
430}
431
432
433static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
434{
435 struct board_t *bd;
436 struct channel_t *ch;
437 struct un_t *un;
438
439 if (!d)
440 return (0);
441 un = (struct un_t *) dev_get_drvdata(d);
442 if (!un || un->magic != DGNC_UNIT_MAGIC)
443 return (0);
444 ch = un->un_ch;
445 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
446 return (0);
447 bd = ch->ch_bd;
448 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
449 return (0);
450 if (bd->state != BOARD_READY)
451 return (0);
452
453 return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
454}
455static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL);
456
457
458static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
459{
460 struct board_t *bd;
461 struct channel_t *ch;
462 struct un_t *un;
463
464 if (!d)
465 return (0);
466 un = (struct un_t *) dev_get_drvdata(d);
467 if (!un || un->magic != DGNC_UNIT_MAGIC)
468 return (0);
469 ch = un->un_ch;
470 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
471 return (0);
472 bd = ch->ch_bd;
473 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
474 return (0);
475 if (bd->state != BOARD_READY)
476 return (0);
477
478 return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
479}
480static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL);
481
482
483static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
484{
485 struct board_t *bd;
486 struct channel_t *ch;
487 struct un_t *un;
488
489 if (!d)
490 return (0);
491 un = (struct un_t *) dev_get_drvdata(d);
492 if (!un || un->magic != DGNC_UNIT_MAGIC)
493 return (0);
494 ch = un->un_ch;
495 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
496 return (0);
497 bd = ch->ch_bd;
498 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
499 return (0);
500 if (bd->state != BOARD_READY)
501 return (0);
502
503 if (ch->ch_open_count) {
504 return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
505 (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
506 (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
507 (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
508 (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
509 (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
510 (ch->ch_mistat & UART_MSR_RI) ? "RI" : "");
511 }
512 return 0;
513}
514static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL);
515
516
517static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
518{
519 struct board_t *bd;
520 struct channel_t *ch;
521 struct un_t *un;
522
523 if (!d)
524 return (0);
525 un = (struct un_t *) dev_get_drvdata(d);
526 if (!un || un->magic != DGNC_UNIT_MAGIC)
527 return (0);
528 ch = un->un_ch;
529 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
530 return (0);
531 bd = ch->ch_bd;
532 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
533 return (0);
534 if (bd->state != BOARD_READY)
535 return (0);
536
537 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
538}
539static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL);
540
541
542static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
543{
544 struct board_t *bd;
545 struct channel_t *ch;
546 struct un_t *un;
547
548 if (!d)
549 return (0);
550 un = (struct un_t *) dev_get_drvdata(d);
551 if (!un || un->magic != DGNC_UNIT_MAGIC)
552 return (0);
553 ch = un->un_ch;
554 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
555 return (0);
556 bd = ch->ch_bd;
557 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
558 return (0);
559 if (bd->state != BOARD_READY)
560 return (0);
561
562 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
563}
564static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL);
565
566
567static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
568{
569 struct board_t *bd;
570 struct channel_t *ch;
571 struct un_t *un;
572
573 if (!d)
574 return (0);
575 un = (struct un_t *) dev_get_drvdata(d);
576 if (!un || un->magic != DGNC_UNIT_MAGIC)
577 return (0);
578 ch = un->un_ch;
579 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
580 return (0);
581 bd = ch->ch_bd;
582 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
583 return (0);
584 if (bd->state != BOARD_READY)
585 return (0);
586
587 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
588}
589static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL);
590
591
592static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
593{
594 struct board_t *bd;
595 struct channel_t *ch;
596 struct un_t *un;
597
598 if (!d)
599 return (0);
600 un = (struct un_t *) dev_get_drvdata(d);
601 if (!un || un->magic != DGNC_UNIT_MAGIC)
602 return (0);
603 ch = un->un_ch;
604 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
605 return (0);
606 bd = ch->ch_bd;
607 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
608 return (0);
609 if (bd->state != BOARD_READY)
610 return (0);
611
612 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
613}
614static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL);
615
616
617static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
618{
619 struct board_t *bd;
620 struct channel_t *ch;
621 struct un_t *un;
622
623 if (!d)
624 return (0);
625 un = (struct un_t *) dev_get_drvdata(d);
626 if (!un || un->magic != DGNC_UNIT_MAGIC)
627 return (0);
628 ch = un->un_ch;
629 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
630 return (0);
631 bd = ch->ch_bd;
632 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
633 return (0);
634 if (bd->state != BOARD_READY)
635 return (0);
636
637 return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
638}
639static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL);
640
641
642static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
643{
644 struct board_t *bd;
645 struct channel_t *ch;
646 struct un_t *un;
647
648 if (!d)
649 return (0);
650 un = (struct un_t *) dev_get_drvdata(d);
651 if (!un || un->magic != DGNC_UNIT_MAGIC)
652 return (0);
653 ch = un->un_ch;
654 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
655 return (0);
656 bd = ch->ch_bd;
657 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
658 return (0);
659 if (bd->state != BOARD_READY)
660 return (0);
661
662 return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
663}
664static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL);
665
666
667static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
668{
669 struct board_t *bd;
670 struct channel_t *ch;
671 struct un_t *un;
672
673 if (!d)
674 return (0);
675 un = (struct un_t *) dev_get_drvdata(d);
676 if (!un || un->magic != DGNC_UNIT_MAGIC)
677 return (0);
678 ch = un->un_ch;
679 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
680 return (0);
681 bd = ch->ch_bd;
682 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
683 return (0);
684 if (bd->state != BOARD_READY)
685 return (0);
686
687 return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
688}
689static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL);
690
691
692static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
693{
694 struct board_t *bd;
695 struct channel_t *ch;
696 struct un_t *un;
697
698 if (!d)
699 return (0);
700 un = (struct un_t *) dev_get_drvdata(d);
701 if (!un || un->magic != DGNC_UNIT_MAGIC)
702 return (0);
703 ch = un->un_ch;
704 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
705 return (0);
706 bd = ch->ch_bd;
707 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
708 return (0);
709 if (bd->state != BOARD_READY)
710 return (0);
711
712 return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
713 (un->un_type == DGNC_PRINT) ? "pr" : "tty",
714 bd->boardnum + 1, 'a' + ch->ch_portnum);
715}
716static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL);
717
718
719static struct attribute *dgnc_sysfs_tty_entries[] = {
720 &dev_attr_state.attr,
721 &dev_attr_baud.attr,
722 &dev_attr_msignals.attr,
723 &dev_attr_iflag.attr,
724 &dev_attr_cflag.attr,
725 &dev_attr_oflag.attr,
726 &dev_attr_lflag.attr,
727 &dev_attr_digi_flag.attr,
728 &dev_attr_rxcount.attr,
729 &dev_attr_txcount.attr,
730 &dev_attr_custom_name.attr,
731 NULL
732};
733
734
735static struct attribute_group dgnc_tty_attribute_group = {
736 .name = NULL,
737 .attrs = dgnc_sysfs_tty_entries,
738};
739
740
741void dgnc_create_tty_sysfs(struct un_t *un, struct device *c)
742{
743 int ret;
744
745 ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group);
746 if (ret) {
747 printk(KERN_ERR "dgnc: failed to create sysfs tty device attributes.\n");
748 sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
749 return;
750 }
751
752 dev_set_drvdata(c, un);
753
754}
755
756
757void dgnc_remove_tty_sysfs(struct device *c)
758{
759 sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
760}
761
diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h
new file mode 100644
index 000000000000..fe991103668c
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_sysfs.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 */
21
22#ifndef __DGNC_SYSFS_H
23#define __DGNC_SYSFS_H
24
25#include "dgnc_driver.h"
26
27#include <linux/device.h>
28
29struct board_t;
30struct channel_t;
31struct un_t;
32struct pci_driver;
33struct class_device;
34
35extern void dgnc_create_ports_sysfiles(struct board_t *bd);
36extern void dgnc_remove_ports_sysfiles(struct board_t *bd);
37
38extern void dgnc_create_driver_sysfiles(struct pci_driver *);
39extern void dgnc_remove_driver_sysfiles(struct pci_driver *);
40
41extern int dgnc_tty_class_init(void);
42extern int dgnc_tty_class_destroy(void);
43
44extern void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
45extern void dgnc_remove_tty_sysfs(struct device *c);
46
47
48
49#endif
diff --git a/drivers/staging/dgnc/dgnc_trace.c b/drivers/staging/dgnc/dgnc_trace.c
new file mode 100644
index 000000000000..ea710e565798
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_trace.c
@@ -0,0 +1,187 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 *
30 */
31
32/* $Id: dgnc_trace.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ */
33
34#include <linux/kernel.h>
35#include <linux/version.h>
36#include <linux/sched.h> /* For jiffies, task states */
37#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
38#include <linux/vmalloc.h>
39
40#include "dgnc_driver.h"
41
42#define TRC_TO_CONSOLE 1
43
44/* file level globals */
45static char *dgnc_trcbuf; /* the ringbuffer */
46
47#if defined(TRC_TO_KMEM)
48static int dgnc_trcbufi = 0; /* index of the tilde at the end of */
49#endif
50
51#if defined(TRC_TO_KMEM)
52static DEFINE_SPINLOCK(dgnc_tracef_lock);
53#endif
54
55
56#if 0
57
58#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
59
60void dgnc_tracef(const char *fmt, ...)
61{
62 return;
63}
64
65#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
66
67void dgnc_tracef(const char *fmt, ...)
68{
69 va_list ap;
70 char buf[TRC_MAXMSG+1];
71 size_t lenbuf;
72 int i;
73 static int failed = FALSE;
74# if defined(TRC_TO_KMEM)
75 unsigned long flags;
76#endif
77
78 if(failed)
79 return;
80# if defined(TRC_TO_KMEM)
81 DGNC_LOCK(dgnc_tracef_lock, flags);
82#endif
83
84 /* Format buf using fmt and arguments contained in ap. */
85 va_start(ap, fmt);
86 i = vsprintf(buf, fmt, ap);
87 va_end(ap);
88 lenbuf = strlen(buf);
89
90# if defined(TRC_TO_KMEM)
91 {
92 static int initd=0;
93
94 /*
95 * Now, in addition to (or instead of) printing this stuff out
96 * (which is a buffered operation), also tuck it away into a
97 * corner of memory which can be examined post-crash in kdb.
98 */
99 if (!initd) {
100 dgnc_trcbuf = (char *) vmalloc(dgnc_trcbuf_size);
101 if(!dgnc_trcbuf) {
102 failed = TRUE;
103 printk("dgnc: tracing init failed!\n");
104 return;
105 }
106
107 memset(dgnc_trcbuf, '\0', dgnc_trcbuf_size);
108 dgnc_trcbufi = 0;
109 initd++;
110
111 printk("dgnc: tracing enabled - " TRC_DTRC
112 " 0x%lx 0x%x\n",
113 (unsigned long)dgnc_trcbuf,
114 dgnc_trcbuf_size);
115 }
116
117# if defined(TRC_ON_OVERFLOW_WRAP_AROUND)
118 /*
119 * This is the less CPU-intensive way to do things. We simply
120 * wrap around before we fall off the end of the buffer. A
121 * tilde (~) demarcates the current end of the trace.
122 *
123 * This method should be used if you are concerned about race
124 * conditions as it is less likely to affect the timing of
125 * things.
126 */
127
128 if (dgnc_trcbufi + lenbuf >= dgnc_trcbuf_size) {
129 /* We are wrapping, so wipe out the last tilde. */
130 dgnc_trcbuf[dgnc_trcbufi] = '\0';
131 /* put the new string at the beginning of the buffer */
132 dgnc_trcbufi = 0;
133 }
134
135 strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
136 dgnc_trcbufi += lenbuf;
137 dgnc_trcbuf[dgnc_trcbufi] = '~';
138
139# elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER)
140 /*
141 * This is the more CPU-intensive way to do things. If we
142 * venture into the last 1/8 of the buffer, we shift the
143 * last 7/8 of the buffer forward, wiping out the first 1/8.
144 * Advantage: No wrap-around, only truncation from the
145 * beginning.
146 *
147 * This method should not be used if you are concerned about
148 * timing changes affecting the behaviour of the driver (ie,
149 * race conditions).
150 */
151 strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf);
152 dgnc_trcbufi += lenbuf;
153 dgnc_trcbuf[dgnc_trcbufi] = '~';
154 dgnc_trcbuf[dgnc_trcbufi+1] = '\0';
155
156 /* If we're near the end of the trace buffer... */
157 if (dgnc_trcbufi > (dgnc_trcbuf_size/8)*7) {
158 /* Wipe out the first eighth to make some more room. */
159 strcpy(dgnc_trcbuf, &dgnc_trcbuf[dgnc_trcbuf_size/8]);
160 dgnc_trcbufi = strlen(dgnc_trcbuf)-1;
161 /* Plop overflow message at the top of the buffer. */
162 bcopy(TRC_OVERFLOW, dgnc_trcbuf, strlen(TRC_OVERFLOW));
163 }
164# else
165# error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?"
166# endif
167 }
168 DGNC_UNLOCK(dgnc_tracef_lock, flags);
169
170# endif /* defined(TRC_TO_KMEM) */
171}
172
173#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */
174
175#endif
176
177
178/*
179 * dgnc_tracer_free()
180 *
181 *
182 */
183void dgnc_tracer_free(void)
184{
185 if(dgnc_trcbuf)
186 vfree(dgnc_trcbuf);
187}
diff --git a/drivers/staging/dgnc/dgnc_trace.h b/drivers/staging/dgnc/dgnc_trace.h
new file mode 100644
index 000000000000..1e8870bf8eee
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_trace.h
@@ -0,0 +1,45 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 *
21 *****************************************************************************
22 * Header file for dgnc_trace.c
23 *
24 * $Id: dgnc_trace.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
25 */
26
27#ifndef __DGNC_TRACE_H
28#define __DGNC_TRACE_H
29
30#include "dgnc_driver.h"
31
32#if 0
33
34# if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE)
35 void dgnc_tracef(const char *fmt, ...);
36# else
37 void dgnc_tracef(const char *fmt, ...);
38# endif
39
40#endif
41
42void dgnc_tracer_free(void);
43
44#endif
45
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c
new file mode 100644
index 000000000000..461e88161808
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_tty.c
@@ -0,0 +1,3648 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
21 *
22 * This is shared code between Digi's CVS archive and the
23 * Linux Kernel sources.
24 * Changing the source just for reformatting needlessly breaks
25 * our CVS diff history.
26 *
27 * Send any bug fixes/changes to: Eng.Linux at digi dot com.
28 * Thank you.
29 */
30
31/************************************************************************
32 *
33 * This file implements the tty driver functionality for the
34 * Neo and ClassicBoard PCI based product lines.
35 *
36 ************************************************************************
37 *
38 * $Id: dgnc_tty.c,v 1.5 2013/04/30 19:18:30 markh Exp $
39 */
40
41#include <linux/kernel.h>
42#include <linux/version.h>
43#include <linux/sched.h> /* For jiffies, task states */
44#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
45#include <linux/module.h>
46#include <linux/ctype.h>
47#include <linux/tty.h>
48#include <linux/tty_flip.h>
49#include <linux/serial_reg.h>
50#include <linux/slab.h>
51#include <linux/delay.h> /* For udelay */
52#include <asm/uaccess.h> /* For copy_from_user/copy_to_user */
53#include <linux/pci.h>
54
55#include "dgnc_driver.h"
56#include "dgnc_tty.h"
57#include "dgnc_types.h"
58#include "dgnc_trace.h"
59#include "dgnc_neo.h"
60#include "dgnc_cls.h"
61#include "dpacompat.h"
62#include "dgnc_sysfs.h"
63
64#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
65#define init_MUTEX(sem) sema_init(sem, 1)
66#define DECLARE_MUTEX(name) \
67 struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
68#endif
69
70/*
71 * internal variables
72 */
73static struct board_t *dgnc_BoardsByMajor[256];
74static uchar *dgnc_TmpWriteBuf = NULL;
75static DECLARE_MUTEX(dgnc_TmpWriteSem);
76
77/*
78 * Default transparent print information.
79 */
80static struct digi_t dgnc_digi_init = {
81 .digi_flags = DIGI_COOK, /* Flags */
82 .digi_maxcps = 100, /* Max CPS */
83 .digi_maxchar = 50, /* Max chars in print queue */
84 .digi_bufsize = 100, /* Printer buffer size */
85 .digi_onlen = 4, /* size of printer on string */
86 .digi_offlen = 4, /* size of printer off string */
87 .digi_onstr = "\033[5i", /* ANSI printer on string ] */
88 .digi_offstr = "\033[4i", /* ANSI printer off string ] */
89 .digi_term = "ansi" /* default terminal type */
90};
91
92
93/*
94 * Define a local default termios struct. All ports will be created
95 * with this termios initially.
96 *
97 * This defines a raw port at 9600 baud, 8 data bits, no parity,
98 * 1 stop bit.
99 */
100static struct ktermios DgncDefaultTermios =
101{
102 .c_iflag = (DEFAULT_IFLAGS), /* iflags */
103 .c_oflag = (DEFAULT_OFLAGS), /* oflags */
104 .c_cflag = (DEFAULT_CFLAGS), /* cflags */
105 .c_lflag = (DEFAULT_LFLAGS), /* lflags */
106 .c_cc = INIT_C_CC,
107 .c_line = 0,
108};
109
110
111/* Our function prototypes */
112static int dgnc_tty_open(struct tty_struct *tty, struct file *file);
113static void dgnc_tty_close(struct tty_struct *tty, struct file *file);
114static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch);
115static int dgnc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
116static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo);
117static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info);
118static int dgnc_tty_write_room(struct tty_struct* tty);
119static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c);
120static int dgnc_tty_chars_in_buffer(struct tty_struct* tty);
121static void dgnc_tty_start(struct tty_struct *tty);
122static void dgnc_tty_stop(struct tty_struct *tty);
123static void dgnc_tty_throttle(struct tty_struct *tty);
124static void dgnc_tty_unthrottle(struct tty_struct *tty);
125static void dgnc_tty_flush_chars(struct tty_struct *tty);
126static void dgnc_tty_flush_buffer(struct tty_struct *tty);
127static void dgnc_tty_hangup(struct tty_struct *tty);
128static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
129static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value);
130#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
131static int dgnc_tty_tiocmget(struct tty_struct *tty);
132static int dgnc_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
133#else
134static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file);
135static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
136#endif
137static int dgnc_tty_send_break(struct tty_struct *tty, int msec);
138static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout);
139static int dgnc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
140static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios);
141static void dgnc_tty_send_xchar(struct tty_struct *tty, char ch);
142
143
144static const struct tty_operations dgnc_tty_ops = {
145 .open = dgnc_tty_open,
146 .close = dgnc_tty_close,
147 .write = dgnc_tty_write,
148 .write_room = dgnc_tty_write_room,
149 .flush_buffer = dgnc_tty_flush_buffer,
150 .chars_in_buffer = dgnc_tty_chars_in_buffer,
151 .flush_chars = dgnc_tty_flush_chars,
152 .ioctl = dgnc_tty_ioctl,
153 .set_termios = dgnc_tty_set_termios,
154 .stop = dgnc_tty_stop,
155 .start = dgnc_tty_start,
156 .throttle = dgnc_tty_throttle,
157 .unthrottle = dgnc_tty_unthrottle,
158 .hangup = dgnc_tty_hangup,
159 .put_char = dgnc_tty_put_char,
160 .tiocmget = dgnc_tty_tiocmget,
161 .tiocmset = dgnc_tty_tiocmset,
162 .break_ctl = dgnc_tty_send_break,
163 .wait_until_sent = dgnc_tty_wait_until_sent,
164 .send_xchar = dgnc_tty_send_xchar
165};
166
167/************************************************************************
168 *
169 * TTY Initialization/Cleanup Functions
170 *
171 ************************************************************************/
172
173/*
174 * dgnc_tty_preinit()
175 *
176 * Initialize any global tty related data before we download any boards.
177 */
178int dgnc_tty_preinit(void)
179{
180 /*
181 * Allocate a buffer for doing the copy from user space to
182 * kernel space in dgnc_write(). We only use one buffer and
183 * control access to it with a semaphore. If we are paging, we
184 * are already in trouble so one buffer won't hurt much anyway.
185 *
186 * We are okay to sleep in the malloc, as this routine
187 * is only called during module load, (not in interrupt context),
188 * and with no locks held.
189 */
190 dgnc_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_KERNEL);
191
192 if (!dgnc_TmpWriteBuf) {
193 DPR_INIT(("unable to allocate tmp write buf"));
194 return (-ENOMEM);
195 }
196
197 return(0);
198}
199
200
201/*
202 * dgnc_tty_register()
203 *
204 * Init the tty subsystem for this board.
205 */
206int dgnc_tty_register(struct board_t *brd)
207{
208 int rc = 0;
209
210 DPR_INIT(("tty_register start\n"));
211
212 memset(&brd->SerialDriver, 0, sizeof(struct tty_driver));
213 memset(&brd->PrintDriver, 0, sizeof(struct tty_driver));
214
215 brd->SerialDriver.magic = TTY_DRIVER_MAGIC;
216
217 snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum);
218
219 brd->SerialDriver.name = brd->SerialName;
220 brd->SerialDriver.name_base = 0;
221 brd->SerialDriver.major = 0;
222 brd->SerialDriver.minor_start = 0;
223 brd->SerialDriver.num = brd->maxports;
224 brd->SerialDriver.type = TTY_DRIVER_TYPE_SERIAL;
225 brd->SerialDriver.subtype = SERIAL_TYPE_NORMAL;
226 brd->SerialDriver.init_termios = DgncDefaultTermios;
227 brd->SerialDriver.driver_name = DRVSTR;
228 brd->SerialDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
229
230 /*
231 * The kernel wants space to store pointers to
232 * tty_struct's and termios's.
233 */
234 brd->SerialDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
235 if (!brd->SerialDriver.ttys)
236 return(-ENOMEM);
237
238#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
239 brd->SerialDriver.refcount = brd->TtyRefCnt;
240#else
241 kref_init(&brd->SerialDriver.kref);
242#endif
243
244 brd->SerialDriver.termios = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
245 if (!brd->SerialDriver.termios)
246 return(-ENOMEM);
247
248#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
249 brd->SerialDriver.termios_locked = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
250 if (!brd->SerialDriver.termios_locked)
251 return(-ENOMEM);
252#endif
253 /*
254 * Entry points for driver. Called by the kernel from
255 * tty_io.c and n_tty.c.
256 */
257 tty_set_operations(&brd->SerialDriver, &dgnc_tty_ops);
258
259 if (!brd->dgnc_Major_Serial_Registered) {
260 /* Register tty devices */
261 rc = tty_register_driver(&brd->SerialDriver);
262 if (rc < 0) {
263 APR(("Can't register tty device (%d)\n", rc));
264 return(rc);
265 }
266 brd->dgnc_Major_Serial_Registered = TRUE;
267 }
268
269 /*
270 * If we're doing transparent print, we have to do all of the above
271 * again, seperately so we don't get the LD confused about what major
272 * we are when we get into the dgnc_tty_open() routine.
273 */
274 brd->PrintDriver.magic = TTY_DRIVER_MAGIC;
275 snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum);
276
277 brd->PrintDriver.name = brd->PrintName;
278 brd->PrintDriver.name_base = 0;
279 brd->PrintDriver.major = brd->SerialDriver.major;
280 brd->PrintDriver.minor_start = 0x80;
281 brd->PrintDriver.num = brd->maxports;
282 brd->PrintDriver.type = TTY_DRIVER_TYPE_SERIAL;
283 brd->PrintDriver.subtype = SERIAL_TYPE_NORMAL;
284 brd->PrintDriver.init_termios = DgncDefaultTermios;
285 brd->PrintDriver.driver_name = DRVSTR;
286 brd->PrintDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK);
287
288 /*
289 * The kernel wants space to store pointers to
290 * tty_struct's and termios's. Must be seperate from
291 * the Serial Driver so we don't get confused
292 */
293 brd->PrintDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
294 if (!brd->PrintDriver.ttys)
295 return(-ENOMEM);
296
297#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
298 brd->PrintDriver.refcount = brd->TtyRefCnt;
299#else
300 kref_init(&brd->PrintDriver.kref);
301#endif
302
303 brd->PrintDriver.termios = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
304 if (!brd->PrintDriver.termios)
305 return(-ENOMEM);
306
307#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
308 brd->PrintDriver.termios_locked = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
309 if (!brd->PrintDriver.termios_locked)
310 return(-ENOMEM);
311#endif
312
313 /*
314 * Entry points for driver. Called by the kernel from
315 * tty_io.c and n_tty.c.
316 */
317 tty_set_operations(&brd->PrintDriver, &dgnc_tty_ops);
318
319 if (!brd->dgnc_Major_TransparentPrint_Registered) {
320 /* Register Transparent Print devices */
321 rc = tty_register_driver(&brd->PrintDriver);
322 if (rc < 0) {
323 APR(("Can't register Transparent Print device (%d)\n", rc));
324 return(rc);
325 }
326 brd->dgnc_Major_TransparentPrint_Registered = TRUE;
327 }
328
329 dgnc_BoardsByMajor[brd->SerialDriver.major] = brd;
330 brd->dgnc_Serial_Major = brd->SerialDriver.major;
331 brd->dgnc_TransparentPrint_Major = brd->PrintDriver.major;
332
333 DPR_INIT(("DGNC REGISTER TTY: MAJOR: %d\n", brd->SerialDriver.major));
334
335 return (rc);
336}
337
338
339/*
340 * dgnc_tty_init()
341 *
342 * Init the tty subsystem. Called once per board after board has been
343 * downloaded and init'ed.
344 */
345int dgnc_tty_init(struct board_t *brd)
346{
347 int i;
348 uchar *vaddr;
349 struct channel_t *ch;
350
351 if (!brd)
352 return (-ENXIO);
353
354 DPR_INIT(("dgnc_tty_init start\n"));
355
356 /*
357 * Initialize board structure elements.
358 */
359
360 vaddr = brd->re_map_membase;
361
362 brd->nasync = brd->maxports;
363
364 /*
365 * Allocate channel memory that might not have been allocated
366 * when the driver was first loaded.
367 */
368 for (i = 0; i < brd->nasync; i++) {
369 if (!brd->channels[i]) {
370
371 /*
372 * Okay to malloc with GFP_KERNEL, we are not at
373 * interrupt context, and there are no locks held.
374 */
375 brd->channels[i] = dgnc_driver_kzmalloc(sizeof(struct channel_t), GFP_KERNEL);
376 if (!brd->channels[i]) {
377 DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
378 __FILE__, __LINE__));
379 }
380 }
381 }
382
383 ch = brd->channels[0];
384 vaddr = brd->re_map_membase;
385
386 /* Set up channel variables */
387 for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
388
389 if (!brd->channels[i])
390 continue;
391
392 DGNC_SPINLOCK_INIT(ch->ch_lock);
393
394 /* Store all our magic numbers */
395 ch->magic = DGNC_CHANNEL_MAGIC;
396 ch->ch_tun.magic = DGNC_UNIT_MAGIC;
397 ch->ch_tun.un_ch = ch;
398 ch->ch_tun.un_type = DGNC_SERIAL;
399 ch->ch_tun.un_dev = i;
400
401 ch->ch_pun.magic = DGNC_UNIT_MAGIC;
402 ch->ch_pun.un_ch = ch;
403 ch->ch_pun.un_type = DGNC_PRINT;
404 ch->ch_pun.un_dev = i + 128;
405
406 if (brd->bd_uart_offset == 0x200)
407 ch->ch_neo_uart = (struct neo_uart_struct *) ((ulong) vaddr + (brd->bd_uart_offset * i));
408 else
409 ch->ch_cls_uart = (struct cls_uart_struct *) ((ulong) vaddr + (brd->bd_uart_offset * i));
410
411 ch->ch_bd = brd;
412 ch->ch_portnum = i;
413 ch->ch_digi = dgnc_digi_init;
414
415 /* .25 second delay */
416 ch->ch_close_delay = 250;
417
418 init_waitqueue_head(&ch->ch_flags_wait);
419 init_waitqueue_head(&ch->ch_tun.un_flags_wait);
420 init_waitqueue_head(&ch->ch_pun.un_flags_wait);
421 init_waitqueue_head(&ch->ch_sniff_wait);
422
423 {
424 struct device *classp;
425 classp = tty_register_device(&brd->SerialDriver, i,
426 &(ch->ch_bd->pdev->dev));
427 ch->ch_tun.un_sysfs = classp;
428 dgnc_create_tty_sysfs(&ch->ch_tun, classp);
429
430 classp = tty_register_device(&brd->PrintDriver, i,
431 &(ch->ch_bd->pdev->dev));
432 ch->ch_pun.un_sysfs = classp;
433 dgnc_create_tty_sysfs(&ch->ch_pun, classp);
434 }
435
436 }
437
438 DPR_INIT(("dgnc_tty_init finish\n"));
439
440 return (0);
441}
442
443
444/*
445 * dgnc_tty_post_uninit()
446 *
447 * UnInitialize any global tty related data.
448 */
449void dgnc_tty_post_uninit(void)
450{
451 if (dgnc_TmpWriteBuf) {
452 kfree(dgnc_TmpWriteBuf);
453 dgnc_TmpWriteBuf = NULL;
454 }
455}
456
457
458/*
459 * dgnc_tty_uninit()
460 *
461 * Uninitialize the TTY portion of this driver. Free all memory and
462 * resources.
463 */
464void dgnc_tty_uninit(struct board_t *brd)
465{
466 int i = 0;
467
468 if (brd->dgnc_Major_Serial_Registered) {
469 dgnc_BoardsByMajor[brd->SerialDriver.major] = NULL;
470 brd->dgnc_Serial_Major = 0;
471 for (i = 0; i < brd->nasync; i++) {
472 dgnc_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs);
473 tty_unregister_device(&brd->SerialDriver, i);
474 }
475 tty_unregister_driver(&brd->SerialDriver);
476 brd->dgnc_Major_Serial_Registered = FALSE;
477 }
478
479 if (brd->dgnc_Major_TransparentPrint_Registered) {
480 dgnc_BoardsByMajor[brd->PrintDriver.major] = NULL;
481 brd->dgnc_TransparentPrint_Major = 0;
482 for (i = 0; i < brd->nasync; i++) {
483 dgnc_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs);
484 tty_unregister_device(&brd->PrintDriver, i);
485 }
486 tty_unregister_driver(&brd->PrintDriver);
487 brd->dgnc_Major_TransparentPrint_Registered = FALSE;
488 }
489
490 if (brd->SerialDriver.ttys) {
491 kfree(brd->SerialDriver.ttys);
492 brd->SerialDriver.ttys = NULL;
493 }
494 if (brd->PrintDriver.ttys) {
495 kfree(brd->PrintDriver.ttys);
496 brd->PrintDriver.ttys = NULL;
497 }
498}
499
500
501#define TMPBUFLEN (1024)
502
503/*
504 * dgnc_sniff - Dump data out to the "sniff" buffer if the
505 * proc sniff file is opened...
506 */
507void dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len)
508{
509 struct timeval tv;
510 int n;
511 int r;
512 int nbuf;
513 int i;
514 int tmpbuflen;
515 char tmpbuf[TMPBUFLEN];
516 char *p = tmpbuf;
517 int too_much_data;
518
519 /* Leave if sniff not open */
520 if (!(ch->ch_sniff_flags & SNIFF_OPEN))
521 return;
522
523 do_gettimeofday(&tv);
524
525 /* Create our header for data dump */
526 p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text);
527 tmpbuflen = p - tmpbuf;
528
529 do {
530 too_much_data = 0;
531
532 for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) {
533 p += sprintf(p, "%02x ", *buf);
534 buf++;
535 tmpbuflen = p - tmpbuf;
536 }
537
538 if (tmpbuflen < (TMPBUFLEN - 4)) {
539 if (i > 0)
540 p += sprintf(p - 1, "%s\n", ">");
541 else
542 p += sprintf(p, "%s\n", ">");
543 } else {
544 too_much_data = 1;
545 len -= i;
546 }
547
548 nbuf = strlen(tmpbuf);
549 p = tmpbuf;
550
551 /*
552 * Loop while data remains.
553 */
554 while (nbuf > 0 && ch->ch_sniff_buf != 0) {
555 /*
556 * Determine the amount of available space left in the
557 * buffer. If there's none, wait until some appears.
558 */
559 n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK;
560
561 /*
562 * If there is no space left to write to in our sniff buffer,
563 * we have no choice but to drop the data.
564 * We *cannot* sleep here waiting for space, because this
565 * function was probably called by the interrupt/timer routines!
566 */
567 if (n == 0) {
568 return;
569 }
570
571 /*
572 * Copy as much data as will fit.
573 */
574
575 if (n > nbuf)
576 n = nbuf;
577
578 r = SNIFF_MAX - ch->ch_sniff_in;
579
580 if (r <= n) {
581 memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r);
582
583 n -= r;
584 ch->ch_sniff_in = 0;
585 p += r;
586 nbuf -= r;
587 }
588
589 memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n);
590
591 ch->ch_sniff_in += n;
592 p += n;
593 nbuf -= n;
594
595 /*
596 * Wakeup any thread waiting for data
597 */
598 if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) {
599 ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA;
600 wake_up_interruptible(&ch->ch_sniff_wait);
601 }
602 }
603
604 /*
605 * If the user sent us too much data to push into our tmpbuf,
606 * we need to keep looping around on all the data.
607 */
608 if (too_much_data) {
609 p = tmpbuf;
610 tmpbuflen = 0;
611 }
612
613 } while (too_much_data);
614}
615
616
617/*=======================================================================
618 *
619 * dgnc_wmove - Write data to transmit queue.
620 *
621 * ch - Pointer to channel structure.
622 * buf - Poiter to characters to be moved.
623 * n - Number of characters to move.
624 *
625 *=======================================================================*/
626static void dgnc_wmove(struct channel_t *ch, char *buf, uint n)
627{
628 int remain;
629 uint head;
630
631 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
632 return;
633
634 head = ch->ch_w_head & WQUEUEMASK;
635
636 /*
637 * If the write wraps over the top of the circular buffer,
638 * move the portion up to the wrap point, and reset the
639 * pointers to the bottom.
640 */
641 remain = WQUEUESIZE - head;
642
643 if (n >= remain) {
644 n -= remain;
645 memcpy(ch->ch_wqueue + head, buf, remain);
646 head = 0;
647 buf += remain;
648 }
649
650 if (n > 0) {
651 /*
652 * Move rest of data.
653 */
654 remain = n;
655 memcpy(ch->ch_wqueue + head, buf, remain);
656 head += remain;
657 }
658
659 head &= WQUEUEMASK;
660 ch->ch_w_head = head;
661}
662
663
664
665
666/*=======================================================================
667 *
668 * dgnc_input - Process received data.
669 *
670 * ch - Pointer to channel structure.
671 *
672 *=======================================================================*/
673void dgnc_input(struct channel_t *ch)
674{
675 struct board_t *bd;
676 struct tty_struct *tp;
677 struct tty_ldisc *ld;
678 uint rmask;
679 ushort head;
680 ushort tail;
681 int data_len;
682 ulong lock_flags;
683 int flip_len;
684 int len = 0;
685 int n = 0;
686 char *buf = NULL;
687 int s = 0;
688 int i = 0;
689
690 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
691 return;
692
693 tp = ch->ch_tun.un_tty;
694
695 bd = ch->ch_bd;
696 if(!bd || bd->magic != DGNC_BOARD_MAGIC)
697 return;
698
699 DGNC_LOCK(ch->ch_lock, lock_flags);
700
701 /*
702 * Figure the number of characters in the buffer.
703 * Exit immediately if none.
704 */
705 rmask = RQUEUEMASK;
706 head = ch->ch_r_head & rmask;
707 tail = ch->ch_r_tail & rmask;
708 data_len = (head - tail) & rmask;
709
710 if (data_len == 0) {
711 DGNC_UNLOCK(ch->ch_lock, lock_flags);
712 return;
713 }
714
715 DPR_READ(("dgnc_input start\n"));
716
717 /*
718 * If the device is not open, or CREAD is off,
719 * flush input data and return immediately.
720 */
721 if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) ||
722 !(tp->termios->c_cflag & CREAD) || (ch->ch_tun.un_flags & UN_CLOSING)) {
723
724 DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum));
725 DPR_READ(("input. tp: %p tp->magic: %x MAGIC:%x ch flags: %x\n",
726 tp, tp ? tp->magic : 0, TTY_MAGIC, ch->ch_tun.un_flags));
727
728 ch->ch_r_head = tail;
729
730 /* Force queue flow control to be released, if needed */
731 dgnc_check_queue_flow_control(ch);
732
733 DGNC_UNLOCK(ch->ch_lock, lock_flags);
734 return;
735 }
736
737 /*
738 * If we are throttled, simply don't read any data.
739 */
740 if (ch->ch_flags & CH_FORCED_STOPI) {
741 DGNC_UNLOCK(ch->ch_lock, lock_flags);
742 DPR_READ(("Port %d throttled, not reading any data. head: %x tail: %x\n",
743 ch->ch_portnum, head, tail));
744 return;
745 }
746
747 DPR_READ(("dgnc_input start 2\n"));
748
749 /* Decide how much data we can send into the tty layer */
750 if (dgnc_rawreadok && tp->real_raw)
751 flip_len = MYFLIPLEN;
752 else
753 flip_len = TTY_FLIPBUF_SIZE;
754
755 /* Chop down the length, if needed */
756 len = min(data_len, flip_len);
757 len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
758
759 ld = tty_ldisc_ref(tp);
760
761#ifdef TTY_DONT_FLIP
762 /*
763 * If the DONT_FLIP flag is on, don't flush our buffer, and act
764 * like the ld doesn't have any space to put the data right now.
765 */
766 if (test_bit(TTY_DONT_FLIP, &tp->flags))
767 len = 0;
768#endif
769
770 /*
771 * If we were unable to get a reference to the ld,
772 * don't flush our buffer, and act like the ld doesn't
773 * have any space to put the data right now.
774 */
775 if (!ld) {
776 len = 0;
777 } else {
778 /*
779 * If ld doesn't have a pointer to a receive_buf function,
780 * flush the data, then act like the ld doesn't have any
781 * space to put the data right now.
782 */
783 if (!ld->ops->receive_buf) {
784 ch->ch_r_head = ch->ch_r_tail;
785 len = 0;
786 }
787 }
788
789 if (len <= 0) {
790 DGNC_UNLOCK(ch->ch_lock, lock_flags);
791 if (ld)
792 tty_ldisc_deref(ld);
793 return;
794 }
795
796 /*
797 * The tty layer in the kernel has changed in 2.6.16+.
798 *
799 * The flip buffers in the tty structure are no longer exposed,
800 * and probably will be going away eventually.
801 *
802 * If we are completely raw, we don't need to go through a lot
803 * of the tty layers that exist.
804 * In this case, we take the shortest and fastest route we
805 * can to relay the data to the user.
806 *
807 * On the other hand, if we are not raw, we need to go through
808 * the new 2.6.16+ tty layer, which has its API more well defined.
809 */
810 if (dgnc_rawreadok && tp->real_raw) {
811
812 if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
813 DPR_READ(("DGNC - FLIPBUF in use. delaying input\n"));
814 DGNC_UNLOCK(ch->ch_lock, lock_flags);
815 if (ld)
816 tty_ldisc_deref(ld);
817 return;
818 }
819
820 ch->ch_flags |= CH_FLIPBUF_IN_USE;
821 buf = ch->ch_bd->flipbuf;
822
823 n = len;
824
825 /*
826 * n now contains the most amount of data we can copy,
827 * bounded either by the flip buffer size or the amount
828 * of data the card actually has pending...
829 */
830 while (n) {
831 s = ((head >= tail) ? head : RQUEUESIZE) - tail;
832 s = min(s, n);
833
834 if (s <= 0)
835 break;
836
837 memcpy(buf, ch->ch_rqueue + tail, s);
838 dgnc_sniff_nowait_nolock(ch, "USER READ", ch->ch_rqueue + tail, s);
839
840 tail += s;
841 buf += s;
842
843 n -= s;
844 /* Flip queue if needed */
845 tail &= rmask;
846 }
847
848 ch->ch_r_tail = tail & rmask;
849 ch->ch_e_tail = tail & rmask;
850
851 dgnc_check_queue_flow_control(ch);
852
853 /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
854
855 DGNC_UNLOCK(ch->ch_lock, lock_flags);
856
857 DPR_READ(("dgnc_input. %d real_raw len:%d calling receive_buf for buffer for board %d\n",
858 __LINE__, len, ch->ch_bd->boardnum));
859
860#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
861 tp->ldisc->ops->receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
862#else
863 tp->ldisc.ops->receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
864#endif
865
866 /* Allow use of channel flip buffer again */
867 DGNC_LOCK(ch->ch_lock, lock_flags);
868 ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
869 DGNC_UNLOCK(ch->ch_lock, lock_flags);
870
871 }
872 else {
873 len = tty_buffer_request_room(tp, len);
874 n = len;
875
876 /*
877 * n now contains the most amount of data we can copy,
878 * bounded either by how much the Linux tty layer can handle,
879 * or the amount of data the card actually has pending...
880 */
881 while (n) {
882 s = ((head >= tail) ? head : RQUEUESIZE) - tail;
883 s = min(s, n);
884
885 if (s <= 0)
886 break;
887
888 /*
889 * If conditions are such that ld needs to see all
890 * UART errors, we will have to walk each character
891 * and error byte and send them to the buffer one at
892 * a time.
893 */
894 if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
895 for (i = 0; i < s; i++) {
896 if (*(ch->ch_equeue + tail + i) & UART_LSR_BI)
897 tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_BREAK);
898 else if (*(ch->ch_equeue + tail + i) & UART_LSR_PE)
899 tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_PARITY);
900 else if (*(ch->ch_equeue + tail + i) & UART_LSR_FE)
901 tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_FRAME);
902 else
903 tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_NORMAL);
904 }
905 }
906 else {
907 tty_insert_flip_string(tp, ch->ch_rqueue + tail, s);
908 }
909
910 dgnc_sniff_nowait_nolock(ch, "USER READ", ch->ch_rqueue + tail, s);
911
912 tail += s;
913 n -= s;
914 /* Flip queue if needed */
915 tail &= rmask;
916 }
917
918 ch->ch_r_tail = tail & rmask;
919 ch->ch_e_tail = tail & rmask;
920 dgnc_check_queue_flow_control(ch);
921 DGNC_UNLOCK(ch->ch_lock, lock_flags);
922
923 /* Tell the tty layer its okay to "eat" the data now */
924 tty_flip_buffer_push(tp);
925 }
926
927 if (ld)
928 tty_ldisc_deref(ld);
929
930 DPR_READ(("dgnc_input - finish\n"));
931}
932
933
934/************************************************************************
935 * Determines when CARRIER changes state and takes appropriate
936 * action.
937 ************************************************************************/
938void dgnc_carrier(struct channel_t *ch)
939{
940 struct board_t *bd;
941
942 int virt_carrier = 0;
943 int phys_carrier = 0;
944
945 DPR_CARR(("dgnc_carrier called...\n"));
946
947 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
948 return;
949
950 bd = ch->ch_bd;
951
952 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
953 return;
954
955 if (ch->ch_mistat & UART_MSR_DCD) {
956 DPR_CARR(("mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD));
957 phys_carrier = 1;
958 }
959
960 if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) {
961 virt_carrier = 1;
962 }
963
964 if (ch->ch_c_cflag & CLOCAL) {
965 virt_carrier = 1;
966 }
967
968
969 DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier));
970
971 /*
972 * Test for a VIRTUAL carrier transition to HIGH.
973 */
974 if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
975
976 /*
977 * When carrier rises, wake any threads waiting
978 * for carrier in the open routine.
979 */
980
981 DPR_CARR(("carrier: virt DCD rose\n"));
982
983 if (waitqueue_active(&(ch->ch_flags_wait)))
984 wake_up_interruptible(&ch->ch_flags_wait);
985 }
986
987 /*
988 * Test for a PHYSICAL carrier transition to HIGH.
989 */
990 if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
991
992 /*
993 * When carrier rises, wake any threads waiting
994 * for carrier in the open routine.
995 */
996
997 DPR_CARR(("carrier: physical DCD rose\n"));
998
999 if (waitqueue_active(&(ch->ch_flags_wait)))
1000 wake_up_interruptible(&ch->ch_flags_wait);
1001 }
1002
1003 /*
1004 * Test for a PHYSICAL transition to low, so long as we aren't
1005 * currently ignoring physical transitions (which is what "virtual
1006 * carrier" indicates).
1007 *
1008 * The transition of the virtual carrier to low really doesn't
1009 * matter... it really only means "ignore carrier state", not
1010 * "make pretend that carrier is there".
1011 */
1012 if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) &&
1013 (phys_carrier == 0))
1014 {
1015
1016 /*
1017 * When carrier drops:
1018 *
1019 * Drop carrier on all open units.
1020 *
1021 * Flush queues, waking up any task waiting in the
1022 * line discipline.
1023 *
1024 * Send a hangup to the control terminal.
1025 *
1026 * Enable all select calls.
1027 */
1028 if (waitqueue_active(&(ch->ch_flags_wait)))
1029 wake_up_interruptible(&ch->ch_flags_wait);
1030
1031 if (ch->ch_tun.un_open_count > 0) {
1032 DPR_CARR(("Sending tty hangup\n"));
1033 tty_hangup(ch->ch_tun.un_tty);
1034 }
1035
1036 if (ch->ch_pun.un_open_count > 0) {
1037 DPR_CARR(("Sending pr hangup\n"));
1038 tty_hangup(ch->ch_pun.un_tty);
1039 }
1040 }
1041
1042 /*
1043 * Make sure that our cached values reflect the current reality.
1044 */
1045 if (virt_carrier == 1)
1046 ch->ch_flags |= CH_FCAR;
1047 else
1048 ch->ch_flags &= ~CH_FCAR;
1049
1050 if (phys_carrier == 1)
1051 ch->ch_flags |= CH_CD;
1052 else
1053 ch->ch_flags &= ~CH_CD;
1054}
1055
1056/*
1057 * Assign the custom baud rate to the channel structure
1058 */
1059static void dgnc_set_custom_speed(struct channel_t *ch, uint newrate)
1060{
1061 int testdiv;
1062 int testrate_high;
1063 int testrate_low;
1064 int deltahigh;
1065 int deltalow;
1066
1067 if (newrate < 0)
1068 newrate = 0;
1069
1070 /*
1071 * Since the divisor is stored in a 16-bit integer, we make sure
1072 * we don't allow any rates smaller than a 16-bit integer would allow.
1073 * And of course, rates above the dividend won't fly.
1074 */
1075 if (newrate && newrate < ((ch->ch_bd->bd_dividend / 0xFFFF) + 1))
1076 newrate = ((ch->ch_bd->bd_dividend / 0xFFFF) + 1);
1077
1078 if (newrate && newrate > ch->ch_bd->bd_dividend)
1079 newrate = ch->ch_bd->bd_dividend;
1080
1081 while (newrate > 0) {
1082 testdiv = ch->ch_bd->bd_dividend / newrate;
1083
1084 /*
1085 * If we try to figure out what rate the board would use
1086 * with the test divisor, it will be either equal or higher
1087 * than the requested baud rate. If we then determine the
1088 * rate with a divisor one higher, we will get the next lower
1089 * supported rate below the requested.
1090 */
1091 testrate_high = ch->ch_bd->bd_dividend / testdiv;
1092 testrate_low = ch->ch_bd->bd_dividend / (testdiv + 1);
1093
1094 /*
1095 * If the rate for the requested divisor is correct, just
1096 * use it and be done.
1097 */
1098 if (testrate_high == newrate )
1099 break;
1100
1101 /*
1102 * Otherwise, pick the rate that is closer (i.e. whichever rate
1103 * has a smaller delta).
1104 */
1105 deltahigh = testrate_high - newrate;
1106 deltalow = newrate - testrate_low;
1107
1108 if (deltahigh < deltalow) {
1109 newrate = testrate_high;
1110 } else {
1111 newrate = testrate_low;
1112 }
1113
1114 break;
1115 }
1116
1117 ch->ch_custom_speed = newrate;
1118
1119 return;
1120}
1121
1122
1123void dgnc_check_queue_flow_control(struct channel_t *ch)
1124{
1125 int qleft = 0;
1126
1127 /* Store how much space we have left in the queue */
1128 if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0)
1129 qleft += RQUEUEMASK + 1;
1130
1131 /*
1132 * Check to see if we should enforce flow control on our queue because
1133 * the ld (or user) isn't reading data out of our queue fast enuf.
1134 *
1135 * NOTE: This is done based on what the current flow control of the
1136 * port is set for.
1137 *
1138 * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt.
1139 * This will cause the UART's FIFO to back up, and force
1140 * the RTS signal to be dropped.
1141 * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to
1142 * the other side, in hopes it will stop sending data to us.
1143 * 3) NONE - Nothing we can do. We will simply drop any extra data
1144 * that gets sent into us when the queue fills up.
1145 */
1146 if (qleft < 256) {
1147 /* HWFLOW */
1148 if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) {
1149 if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
1150 ch->ch_bd->bd_ops->disable_receiver(ch);
1151 ch->ch_flags |= (CH_RECEIVER_OFF);
1152 DPR_READ(("Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
1153 qleft));
1154 }
1155 }
1156 /* SWFLOW */
1157 else if (ch->ch_c_iflag & IXOFF) {
1158 if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
1159 ch->ch_bd->bd_ops->send_stop_character(ch);
1160 ch->ch_stops_sent++;
1161 DPR_READ(("Sending stop char! Times sent: %x\n", ch->ch_stops_sent));
1162 }
1163 }
1164 /* No FLOW */
1165 else {
1166 /* Empty... Can't do anything about the impending overflow... */
1167 }
1168 }
1169
1170 /*
1171 * Check to see if we should unenforce flow control because
1172 * ld (or user) finally read enuf data out of our queue.
1173 *
1174 * NOTE: This is done based on what the current flow control of the
1175 * port is set for.
1176 *
1177 * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt.
1178 * This will cause the UART's FIFO to raise RTS back up,
1179 * which will allow the other side to start sending data again.
1180 * 2) SWFLOW (IXOFF) - Send a start character to
1181 * the other side, so it will start sending data to us again.
1182 * 3) NONE - Do nothing. Since we didn't do anything to turn off the
1183 * other side, we don't need to do anything now.
1184 */
1185 if (qleft > (RQUEUESIZE / 2)) {
1186 /* HWFLOW */
1187 if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) {
1188 if (ch->ch_flags & CH_RECEIVER_OFF) {
1189 ch->ch_bd->bd_ops->enable_receiver(ch);
1190 ch->ch_flags &= ~(CH_RECEIVER_OFF);
1191 DPR_READ(("Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
1192 qleft));
1193 }
1194 }
1195 /* SWFLOW */
1196 else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
1197 ch->ch_stops_sent = 0;
1198 ch->ch_bd->bd_ops->send_start_character(ch);
1199 DPR_READ(("Sending start char!\n"));
1200 }
1201 /* No FLOW */
1202 else {
1203 /* Nothing needed. */
1204 }
1205 }
1206}
1207
1208
1209void dgnc_wakeup_writes(struct channel_t *ch)
1210{
1211 int qlen = 0;
1212 ulong lock_flags;
1213
1214 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1215 return;
1216
1217 DGNC_LOCK(ch->ch_lock, lock_flags);
1218
1219 /*
1220 * If channel now has space, wake up anyone waiting on the condition.
1221 */
1222 if ((qlen = ch->ch_w_head - ch->ch_w_tail) < 0)
1223 qlen += WQUEUESIZE;
1224
1225 if (qlen >= (WQUEUESIZE - 256)) {
1226 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1227 return;
1228 }
1229
1230 if (ch->ch_tun.un_flags & UN_ISOPEN) {
1231#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
1232 if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1233 ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
1234 {
1235 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1236 (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
1237 DGNC_LOCK(ch->ch_lock, lock_flags);
1238 }
1239#else
1240 if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1241 ch->ch_tun.un_tty->ldisc.ops->write_wakeup)
1242 {
1243 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1244 (ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty);
1245 DGNC_LOCK(ch->ch_lock, lock_flags);
1246 }
1247#endif
1248
1249 wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
1250
1251 /*
1252 * If unit is set to wait until empty, check to make sure
1253 * the queue AND FIFO are both empty.
1254 */
1255 if (ch->ch_tun.un_flags & UN_EMPTY) {
1256 if ((qlen == 0) && (ch->ch_bd->bd_ops->get_uart_bytes_left(ch) == 0)) {
1257 ch->ch_tun.un_flags &= ~(UN_EMPTY);
1258
1259 /*
1260 * If RTS Toggle mode is on, whenever
1261 * the queue and UART is empty, keep RTS low.
1262 */
1263 if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) {
1264 ch->ch_mostat &= ~(UART_MCR_RTS);
1265 ch->ch_bd->bd_ops->assert_modem_signals(ch);
1266 }
1267
1268 /*
1269 * If DTR Toggle mode is on, whenever
1270 * the queue and UART is empty, keep DTR low.
1271 */
1272 if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) {
1273 ch->ch_mostat &= ~(UART_MCR_DTR);
1274 ch->ch_bd->bd_ops->assert_modem_signals(ch);
1275 }
1276 }
1277 }
1278
1279 wake_up_interruptible(&ch->ch_tun.un_flags_wait);
1280 }
1281
1282 if (ch->ch_pun.un_flags & UN_ISOPEN) {
1283#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
1284 if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1285 ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
1286 {
1287 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1288 (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
1289 DGNC_LOCK(ch->ch_lock, lock_flags);
1290 }
1291#else
1292 if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
1293 ch->ch_pun.un_tty->ldisc.ops->write_wakeup)
1294 {
1295 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1296 (ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty);
1297 DGNC_LOCK(ch->ch_lock, lock_flags);
1298 }
1299#endif
1300
1301 wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
1302
1303 /*
1304 * If unit is set to wait until empty, check to make sure
1305 * the queue AND FIFO are both empty.
1306 */
1307 if (ch->ch_pun.un_flags & UN_EMPTY) {
1308 if ((qlen == 0) && (ch->ch_bd->bd_ops->get_uart_bytes_left(ch) == 0)) {
1309 ch->ch_pun.un_flags &= ~(UN_EMPTY);
1310 }
1311 }
1312
1313 wake_up_interruptible(&ch->ch_pun.un_flags_wait);
1314 }
1315
1316 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1317}
1318
1319
1320
1321/************************************************************************
1322 *
1323 * TTY Entry points and helper functions
1324 *
1325 ************************************************************************/
1326
1327/*
1328 * dgnc_tty_open()
1329 *
1330 */
1331static int dgnc_tty_open(struct tty_struct *tty, struct file *file)
1332{
1333 struct board_t *brd;
1334 struct channel_t *ch;
1335 struct un_t *un;
1336 uint major = 0;
1337 uint minor = 0;
1338 int rc = 0;
1339 ulong lock_flags;
1340
1341 rc = 0;
1342
1343 major = MAJOR(tty_devnum(tty));
1344 minor = MINOR(tty_devnum(tty));
1345
1346 if (major > 255) {
1347 return -ENXIO;
1348 }
1349
1350 /* Get board pointer from our array of majors we have allocated */
1351 brd = dgnc_BoardsByMajor[major];
1352 if (!brd) {
1353 return -ENXIO;
1354 }
1355
1356 /*
1357 * If board is not yet up to a state of READY, go to
1358 * sleep waiting for it to happen or they cancel the open.
1359 */
1360 rc = wait_event_interruptible(brd->state_wait,
1361 (brd->state & BOARD_READY));
1362
1363 if (rc) {
1364 return rc;
1365 }
1366
1367 DGNC_LOCK(brd->bd_lock, lock_flags);
1368
1369 /* If opened device is greater than our number of ports, bail. */
1370 if (PORT_NUM(minor) > brd->nasync) {
1371 DGNC_UNLOCK(brd->bd_lock, lock_flags);
1372 return -ENXIO;
1373 }
1374
1375 ch = brd->channels[PORT_NUM(minor)];
1376 if (!ch) {
1377 DGNC_UNLOCK(brd->bd_lock, lock_flags);
1378 return -ENXIO;
1379 }
1380
1381 /* Drop board lock */
1382 DGNC_UNLOCK(brd->bd_lock, lock_flags);
1383
1384 /* Grab channel lock */
1385 DGNC_LOCK(ch->ch_lock, lock_flags);
1386
1387 /* Figure out our type */
1388 if (!IS_PRINT(minor)) {
1389 un = &brd->channels[PORT_NUM(minor)]->ch_tun;
1390 un->un_type = DGNC_SERIAL;
1391 }
1392 else if (IS_PRINT(minor)) {
1393 un = &brd->channels[PORT_NUM(minor)]->ch_pun;
1394 un->un_type = DGNC_PRINT;
1395 }
1396 else {
1397 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1398 DPR_OPEN(("%d Unknown TYPE!\n", __LINE__));
1399 return -ENXIO;
1400 }
1401
1402 /*
1403 * If the port is still in a previous open, and in a state
1404 * where we simply cannot safely keep going, wait until the
1405 * state clears.
1406 */
1407 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1408
1409 rc = wait_event_interruptible(ch->ch_flags_wait, ((ch->ch_flags & CH_OPENING) == 0));
1410
1411 /* If ret is non-zero, user ctrl-c'ed us */
1412 if (rc) {
1413 DPR_OPEN(("%d User ctrl c'ed\n", __LINE__));
1414 return -EINTR;
1415 }
1416
1417 /*
1418 * If either unit is in the middle of the fragile part of close,
1419 * we just cannot touch the channel safely.
1420 * Go to sleep, knowing that when the channel can be
1421 * touched safely, the close routine will signal the
1422 * ch_flags_wait to wake us back up.
1423 */
1424 rc = wait_event_interruptible(ch->ch_flags_wait,
1425 (((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING) == 0));
1426
1427 /* If ret is non-zero, user ctrl-c'ed us */
1428 if (rc) {
1429 DPR_OPEN(("%d User ctrl c'ed\n", __LINE__));
1430 return -EINTR;
1431 }
1432
1433 DGNC_LOCK(ch->ch_lock, lock_flags);
1434
1435
1436 /* Store our unit into driver_data, so we always have it available. */
1437 tty->driver_data = un;
1438
1439 DPR_OPEN(("Open called. MAJOR: %d MINOR:%d PORT_NUM: %x unit: %p NAME: %s\n",
1440 MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), PORT_NUM(minor), un, brd->name));
1441
1442 DPR_OPEN(("%d: tflag=%x pflag=%x\n", __LINE__, ch->ch_tun.un_flags, ch->ch_pun.un_flags));
1443
1444 /*
1445 * Initialize tty's
1446 */
1447 if (!(un->un_flags & UN_ISOPEN)) {
1448 /* Store important variables. */
1449 un->un_tty = tty;
1450
1451 /* Maybe do something here to the TTY struct as well? */
1452 }
1453
1454
1455 /*
1456 * Allocate channel buffers for read/write/error.
1457 * Set flag, so we don't get trounced on.
1458 */
1459 ch->ch_flags |= (CH_OPENING);
1460
1461 /* Drop locks, as malloc with GFP_KERNEL can sleep */
1462 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1463
1464 if (!ch->ch_rqueue)
1465 ch->ch_rqueue = dgnc_driver_kzmalloc(RQUEUESIZE, GFP_KERNEL);
1466 if (!ch->ch_equeue)
1467 ch->ch_equeue = dgnc_driver_kzmalloc(EQUEUESIZE, GFP_KERNEL);
1468 if (!ch->ch_wqueue)
1469 ch->ch_wqueue = dgnc_driver_kzmalloc(WQUEUESIZE, GFP_KERNEL);
1470
1471 DGNC_LOCK(ch->ch_lock, lock_flags);
1472
1473 ch->ch_flags &= ~(CH_OPENING);
1474 wake_up_interruptible(&ch->ch_flags_wait);
1475
1476 /*
1477 * Initialize if neither terminal or printer is open.
1478 */
1479 if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
1480
1481 DPR_OPEN(("dgnc_open: initializing channel in open...\n"));
1482
1483 /*
1484 * Flush input queues.
1485 */
1486 ch->ch_r_head = ch->ch_r_tail = 0;
1487 ch->ch_e_head = ch->ch_e_tail = 0;
1488 ch->ch_w_head = ch->ch_w_tail = 0;
1489
1490 brd->bd_ops->flush_uart_write(ch);
1491 brd->bd_ops->flush_uart_read(ch);
1492
1493 ch->ch_flags = 0;
1494 ch->ch_cached_lsr = 0;
1495 ch->ch_stop_sending_break = 0;
1496 ch->ch_stops_sent = 0;
1497
1498 ch->ch_c_cflag = tty->termios->c_cflag;
1499 ch->ch_c_iflag = tty->termios->c_iflag;
1500 ch->ch_c_oflag = tty->termios->c_oflag;
1501 ch->ch_c_lflag = tty->termios->c_lflag;
1502 ch->ch_startc = tty->termios->c_cc[VSTART];
1503 ch->ch_stopc = tty->termios->c_cc[VSTOP];
1504
1505 /*
1506 * Bring up RTS and DTR...
1507 * Also handle RTS or DTR toggle if set.
1508 */
1509 if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE))
1510 ch->ch_mostat |= (UART_MCR_RTS);
1511 if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE))
1512 ch->ch_mostat |= (UART_MCR_DTR);
1513
1514 /* Tell UART to init itself */
1515 brd->bd_ops->uart_init(ch);
1516 }
1517
1518 /*
1519 * Run param in case we changed anything
1520 */
1521 brd->bd_ops->param(tty);
1522
1523 dgnc_carrier(ch);
1524
1525 /*
1526 * follow protocol for opening port
1527 */
1528
1529 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1530
1531 rc = dgnc_block_til_ready(tty, file, ch);
1532
1533 if (rc) {
1534 DPR_OPEN(("dgnc_tty_open returning after dgnc_block_til_ready "
1535 "with %d\n", rc));
1536 }
1537
1538 /* No going back now, increment our unit and channel counters */
1539 DGNC_LOCK(ch->ch_lock, lock_flags);
1540 ch->ch_open_count++;
1541 un->un_open_count++;
1542 un->un_flags |= (UN_ISOPEN);
1543 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1544
1545 DPR_OPEN(("dgnc_tty_open finished\n"));
1546 return (rc);
1547}
1548
1549
1550/*
1551 * dgnc_block_til_ready()
1552 *
1553 * Wait for DCD, if needed.
1554 */
1555static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch)
1556{
1557 int retval = 0;
1558 struct un_t *un = NULL;
1559 ulong lock_flags;
1560 uint old_flags = 0;
1561 int sleep_on_un_flags = 0;
1562
1563 if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGNC_CHANNEL_MAGIC) {
1564 return (-ENXIO);
1565 }
1566
1567 un = tty->driver_data;
1568 if (!un || un->magic != DGNC_UNIT_MAGIC) {
1569 return (-ENXIO);
1570 }
1571
1572 DPR_OPEN(("dgnc_block_til_ready - before block.\n"));
1573
1574 DGNC_LOCK(ch->ch_lock, lock_flags);
1575
1576 ch->ch_wopen++;
1577
1578 /* Loop forever */
1579 while (1) {
1580
1581 sleep_on_un_flags = 0;
1582
1583 /*
1584 * If board has failed somehow during our sleep, bail with error.
1585 */
1586 if (ch->ch_bd->state == BOARD_FAILED) {
1587 retval = -ENXIO;
1588 break;
1589 }
1590
1591 /* If tty was hung up, break out of loop and set error. */
1592 if (tty_hung_up_p(file)) {
1593 retval = -EAGAIN;
1594 break;
1595 }
1596
1597 /*
1598 * If either unit is in the middle of the fragile part of close,
1599 * we just cannot touch the channel safely.
1600 * Go back to sleep, knowing that when the channel can be
1601 * touched safely, the close routine will signal the
1602 * ch_wait_flags to wake us back up.
1603 */
1604 if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) {
1605
1606 /*
1607 * Our conditions to leave cleanly and happily:
1608 * 1) NONBLOCKING on the tty is set.
1609 * 2) CLOCAL is set.
1610 * 3) DCD (fake or real) is active.
1611 */
1612
1613 if (file->f_flags & O_NONBLOCK) {
1614 break;
1615 }
1616
1617 if (tty->flags & (1 << TTY_IO_ERROR)) {
1618 retval = -EIO;
1619 break;
1620 }
1621
1622 if (ch->ch_flags & CH_CD) {
1623 DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
1624 break;
1625 }
1626
1627 if (ch->ch_flags & CH_FCAR) {
1628 DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags));
1629 break;
1630 }
1631 }
1632 else {
1633 sleep_on_un_flags = 1;
1634 }
1635
1636 /*
1637 * If there is a signal pending, the user probably
1638 * interrupted (ctrl-c) us.
1639 * Leave loop with error set.
1640 */
1641 if (signal_pending(current)) {
1642 DPR_OPEN(("%d: signal pending...\n", __LINE__));
1643 retval = -ERESTARTSYS;
1644 break;
1645 }
1646
1647 DPR_OPEN(("dgnc_block_til_ready - blocking.\n"));
1648
1649 /*
1650 * Store the flags before we let go of channel lock
1651 */
1652 if (sleep_on_un_flags)
1653 old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
1654 else
1655 old_flags = ch->ch_flags;
1656
1657 /*
1658 * Let go of channel lock before calling schedule.
1659 * Our poller will get any FEP events and wake us up when DCD
1660 * eventually goes active.
1661 */
1662
1663 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1664
1665 DPR_OPEN(("Going to sleep on %s flags...\n",
1666 (sleep_on_un_flags ? "un" : "ch")));
1667
1668 /*
1669 * Wait for something in the flags to change from the current value.
1670 */
1671 if (sleep_on_un_flags) {
1672 retval = wait_event_interruptible(un->un_flags_wait,
1673 (old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags)));
1674 }
1675 else {
1676 retval = wait_event_interruptible(ch->ch_flags_wait,
1677 (old_flags != ch->ch_flags));
1678 }
1679
1680 DPR_OPEN(("After sleep... retval: %x\n", retval));
1681
1682 /*
1683 * We got woken up for some reason.
1684 * Before looping around, grab our channel lock.
1685 */
1686 DGNC_LOCK(ch->ch_lock, lock_flags);
1687 }
1688
1689 ch->ch_wopen--;
1690
1691 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1692
1693 DPR_OPEN(("dgnc_block_til_ready - after blocking.\n"));
1694
1695 if (retval) {
1696 DPR_OPEN(("dgnc_block_til_ready - done. error. retval: %x\n", retval));
1697 return(retval);
1698 }
1699
1700 DPR_OPEN(("dgnc_block_til_ready - done no error. jiffies: %lu\n", jiffies));
1701
1702 return(0);
1703}
1704
1705
1706/*
1707 * dgnc_tty_hangup()
1708 *
1709 * Hangup the port. Like a close, but don't wait for output to drain.
1710 */
1711static void dgnc_tty_hangup(struct tty_struct *tty)
1712{
1713 struct un_t *un;
1714
1715 if (!tty || tty->magic != TTY_MAGIC)
1716 return;
1717
1718 un = tty->driver_data;
1719 if (!un || un->magic != DGNC_UNIT_MAGIC)
1720 return;
1721
1722 DPR_CLOSE(("dgnc_hangup called. ch->ch_open_count: %d un->un_open_count: %d\n",
1723 un->un_ch->ch_open_count, un->un_open_count));
1724
1725 /* flush the transmit queues */
1726 dgnc_tty_flush_buffer(tty);
1727
1728 DPR_CLOSE(("dgnc_hangup finished. ch->ch_open_count: %d un->un_open_count: %d\n",
1729 un->un_ch->ch_open_count, un->un_open_count));
1730}
1731
1732
1733/*
1734 * dgnc_tty_close()
1735 *
1736 */
1737static void dgnc_tty_close(struct tty_struct *tty, struct file *file)
1738{
1739 struct ktermios *ts;
1740 struct board_t *bd;
1741 struct channel_t *ch;
1742 struct un_t *un;
1743 ulong lock_flags;
1744 int rc = 0;
1745
1746 if (!tty || tty->magic != TTY_MAGIC)
1747 return;
1748
1749 un = tty->driver_data;
1750 if (!un || un->magic != DGNC_UNIT_MAGIC)
1751 return;
1752
1753 ch = un->un_ch;
1754 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1755 return;
1756
1757 bd = ch->ch_bd;
1758 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
1759 return;
1760
1761 ts = tty->termios;
1762
1763 DPR_CLOSE(("Close called\n"));
1764
1765 DGNC_LOCK(ch->ch_lock, lock_flags);
1766
1767 /*
1768 * Determine if this is the last close or not - and if we agree about
1769 * which type of close it is with the Line Discipline
1770 */
1771 if ((tty->count == 1) && (un->un_open_count != 1)) {
1772 /*
1773 * Uh, oh. tty->count is 1, which means that the tty
1774 * structure will be freed. un_open_count should always
1775 * be one in these conditions. If it's greater than
1776 * one, we've got real problems, since it means the
1777 * serial port won't be shutdown.
1778 */
1779 APR(("tty->count is 1, un open count is %d\n", un->un_open_count));
1780 un->un_open_count = 1;
1781 }
1782
1783 if (--un->un_open_count < 0) {
1784 APR(("bad serial port open count of %d\n", un->un_open_count));
1785 un->un_open_count = 0;
1786 }
1787
1788 ch->ch_open_count--;
1789
1790 if (ch->ch_open_count && un->un_open_count) {
1791 DPR_CLOSE(("dgnc_tty_close: not last close ch: %d un:%d\n",
1792 ch->ch_open_count, un->un_open_count));
1793
1794 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1795 return;
1796 }
1797
1798 /* OK, its the last close on the unit */
1799 DPR_CLOSE(("dgnc_tty_close - last close on unit procedures\n"));
1800
1801 un->un_flags |= UN_CLOSING;
1802
1803 tty->closing = 1;
1804
1805
1806 /*
1807 * Only officially close channel if count is 0 and
1808 * DIGI_PRINTER bit is not set.
1809 */
1810 if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
1811
1812 ch->ch_flags &= ~(CH_STOPI | CH_FORCED_STOPI);
1813
1814 /*
1815 * turn off print device when closing print device.
1816 */
1817 if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON) ) {
1818 dgnc_wmove(ch, ch->ch_digi.digi_offstr,
1819 (int) ch->ch_digi.digi_offlen);
1820 ch->ch_flags &= ~CH_PRON;
1821 }
1822
1823 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1824 /* wait for output to drain */
1825 /* This will also return if we take an interrupt */
1826
1827 DPR_CLOSE(("Calling wait_for_drain\n"));
1828 rc = bd->bd_ops->drain(tty, 0);
1829
1830 DPR_CLOSE(("After calling wait_for_drain\n"));
1831
1832 if (rc) {
1833 DPR_BASIC(("dgnc_tty_close - bad return: %d ", rc));
1834 }
1835
1836 dgnc_tty_flush_buffer(tty);
1837 tty_ldisc_flush(tty);
1838
1839 DGNC_LOCK(ch->ch_lock, lock_flags);
1840
1841 tty->closing = 0;
1842
1843 /*
1844 * If we have HUPCL set, lower DTR and RTS
1845 */
1846 if (ch->ch_c_cflag & HUPCL) {
1847 DPR_CLOSE(("Close. HUPCL set, dropping DTR/RTS\n"));
1848
1849 /* Drop RTS/DTR */
1850 ch->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS);
1851 bd->bd_ops->assert_modem_signals(ch);
1852
1853 /*
1854 * Go to sleep to ensure RTS/DTR
1855 * have been dropped for modems to see it.
1856 */
1857 if (ch->ch_close_delay) {
1858 DPR_CLOSE(("Close. Sleeping for RTS/DTR drop\n"));
1859
1860 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1861 dgnc_ms_sleep(ch->ch_close_delay);
1862 DGNC_LOCK(ch->ch_lock, lock_flags);
1863
1864 DPR_CLOSE(("Close. After sleeping for RTS/DTR drop\n"));
1865 }
1866 }
1867
1868 ch->ch_old_baud = 0;
1869
1870 /* Turn off UART interrupts for this port */
1871 ch->ch_bd->bd_ops->uart_off(ch);
1872 }
1873 else {
1874 /*
1875 * turn off print device when closing print device.
1876 */
1877 if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON) ) {
1878 dgnc_wmove(ch, ch->ch_digi.digi_offstr,
1879 (int) ch->ch_digi.digi_offlen);
1880 ch->ch_flags &= ~CH_PRON;
1881 }
1882 }
1883
1884 un->un_tty = NULL;
1885 un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
1886
1887 DPR_CLOSE(("Close. Doing wakeups\n"));
1888 wake_up_interruptible(&ch->ch_flags_wait);
1889 wake_up_interruptible(&un->un_flags_wait);
1890
1891 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1892
1893 DPR_BASIC(("dgnc_tty_close - complete\n"));
1894}
1895
1896
1897/*
1898 * dgnc_tty_chars_in_buffer()
1899 *
1900 * Return number of characters that have not been transmitted yet.
1901 *
1902 * This routine is used by the line discipline to determine if there
1903 * is data waiting to be transmitted/drained/flushed or not.
1904 */
1905static int dgnc_tty_chars_in_buffer(struct tty_struct *tty)
1906{
1907 struct channel_t *ch = NULL;
1908 struct un_t *un = NULL;
1909 ushort thead;
1910 ushort ttail;
1911 uint tmask;
1912 uint chars = 0;
1913 ulong lock_flags = 0;
1914
1915 if (tty == NULL)
1916 return(0);
1917
1918 un = tty->driver_data;
1919 if (!un || un->magic != DGNC_UNIT_MAGIC)
1920 return (0);
1921
1922 ch = un->un_ch;
1923 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1924 return (0);
1925
1926 DGNC_LOCK(ch->ch_lock, lock_flags);
1927
1928 tmask = WQUEUEMASK;
1929 thead = ch->ch_w_head & tmask;
1930 ttail = ch->ch_w_tail & tmask;
1931
1932 DGNC_UNLOCK(ch->ch_lock, lock_flags);
1933
1934 if (ttail == thead) {
1935 chars = 0;
1936 } else {
1937 if (thead >= ttail)
1938 chars = thead - ttail;
1939 else
1940 chars = thead - ttail + WQUEUESIZE;
1941 }
1942
1943 DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n",
1944 ch->ch_portnum, chars, thead, ttail));
1945
1946 return(chars);
1947}
1948
1949
1950/*
1951 * dgnc_maxcps_room
1952 *
1953 * Reduces bytes_available to the max number of characters
1954 * that can be sent currently given the maxcps value, and
1955 * returns the new bytes_available. This only affects printer
1956 * output.
1957 */
1958static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available)
1959{
1960 struct channel_t *ch = NULL;
1961 struct un_t *un = NULL;
1962
1963 if (!tty)
1964 return (bytes_available);
1965
1966 un = tty->driver_data;
1967 if (!un || un->magic != DGNC_UNIT_MAGIC)
1968 return (bytes_available);
1969
1970 ch = un->un_ch;
1971 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
1972 return (bytes_available);
1973
1974 /*
1975 * If its not the Transparent print device, return
1976 * the full data amount.
1977 */
1978 if (un->un_type != DGNC_PRINT)
1979 return (bytes_available);
1980
1981 if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
1982 int cps_limit = 0;
1983 unsigned long current_time = jiffies;
1984 unsigned long buffer_time = current_time +
1985 (HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps;
1986
1987 if (ch->ch_cpstime < current_time) {
1988 /* buffer is empty */
1989 ch->ch_cpstime = current_time; /* reset ch_cpstime */
1990 cps_limit = ch->ch_digi.digi_bufsize;
1991 }
1992 else if (ch->ch_cpstime < buffer_time) {
1993 /* still room in the buffer */
1994 cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ;
1995 }
1996 else {
1997 /* no room in the buffer */
1998 cps_limit = 0;
1999 }
2000
2001 bytes_available = min(cps_limit, bytes_available);
2002 }
2003
2004 return (bytes_available);
2005}
2006
2007
2008/*
2009 * dgnc_tty_write_room()
2010 *
2011 * Return space available in Tx buffer
2012 */
2013static int dgnc_tty_write_room(struct tty_struct *tty)
2014{
2015 struct channel_t *ch = NULL;
2016 struct un_t *un = NULL;
2017 ushort head;
2018 ushort tail;
2019 ushort tmask;
2020 int ret = 0;
2021 ulong lock_flags = 0;
2022
2023 if (tty == NULL || dgnc_TmpWriteBuf == NULL)
2024 return(0);
2025
2026 un = tty->driver_data;
2027 if (!un || un->magic != DGNC_UNIT_MAGIC)
2028 return (0);
2029
2030 ch = un->un_ch;
2031 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2032 return (0);
2033
2034 DGNC_LOCK(ch->ch_lock, lock_flags);
2035
2036 tmask = WQUEUEMASK;
2037 head = (ch->ch_w_head) & tmask;
2038 tail = (ch->ch_w_tail) & tmask;
2039
2040 if ((ret = tail - head - 1) < 0)
2041 ret += WQUEUESIZE;
2042
2043 /* Limit printer to maxcps */
2044 ret = dgnc_maxcps_room(tty, ret);
2045
2046 /*
2047 * If we are printer device, leave space for
2048 * possibly both the on and off strings.
2049 */
2050 if (un->un_type == DGNC_PRINT) {
2051 if (!(ch->ch_flags & CH_PRON))
2052 ret -= ch->ch_digi.digi_onlen;
2053 ret -= ch->ch_digi.digi_offlen;
2054 }
2055 else {
2056 if (ch->ch_flags & CH_PRON)
2057 ret -= ch->ch_digi.digi_offlen;
2058 }
2059
2060 if (ret < 0)
2061 ret = 0;
2062
2063 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2064
2065 DPR_WRITE(("dgnc_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
2066
2067 return(ret);
2068}
2069
2070
2071/*
2072 * dgnc_tty_put_char()
2073 *
2074 * Put a character into ch->ch_buf
2075 *
2076 * - used by the line discipline for OPOST processing
2077 */
2078static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c)
2079{
2080 /*
2081 * Simply call tty_write.
2082 */
2083 DPR_WRITE(("dgnc_tty_put_char called\n"));
2084 dgnc_tty_write(tty, &c, 1);
2085 return 1;
2086}
2087
2088
2089/*
2090 * dgnc_tty_write()
2091 *
2092 * Take data from the user or kernel and send it out to the FEP.
2093 * In here exists all the Transparent Print magic as well.
2094 */
2095static int dgnc_tty_write(struct tty_struct *tty,
2096 const unsigned char *buf, int count)
2097{
2098 struct channel_t *ch = NULL;
2099 struct un_t *un = NULL;
2100 int bufcount = 0, n = 0;
2101 int orig_count = 0;
2102 ulong lock_flags;
2103 ushort head;
2104 ushort tail;
2105 ushort tmask;
2106 uint remain;
2107 int from_user = 0;
2108
2109 if (tty == NULL || dgnc_TmpWriteBuf == NULL)
2110 return(0);
2111
2112 un = tty->driver_data;
2113 if (!un || un->magic != DGNC_UNIT_MAGIC)
2114 return(0);
2115
2116 ch = un->un_ch;
2117 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2118 return(0);
2119
2120 if (!count)
2121 return(0);
2122
2123 DPR_WRITE(("dgnc_tty_write: Port: %x tty=%p user=%d len=%d\n",
2124 ch->ch_portnum, tty, from_user, count));
2125
2126 /*
2127 * Store original amount of characters passed in.
2128 * This helps to figure out if we should ask the FEP
2129 * to send us an event when it has more space available.
2130 */
2131 orig_count = count;
2132
2133 DGNC_LOCK(ch->ch_lock, lock_flags);
2134
2135 /* Get our space available for the channel from the board */
2136 tmask = WQUEUEMASK;
2137 head = (ch->ch_w_head) & tmask;
2138 tail = (ch->ch_w_tail) & tmask;
2139
2140 if ((bufcount = tail - head - 1) < 0)
2141 bufcount += WQUEUESIZE;
2142
2143 DPR_WRITE(("%d: bufcount: %x count: %x tail: %x head: %x tmask: %x\n",
2144 __LINE__, bufcount, count, tail, head, tmask));
2145
2146 /*
2147 * Limit printer output to maxcps overall, with bursts allowed
2148 * up to bufsize characters.
2149 */
2150 bufcount = dgnc_maxcps_room(tty, bufcount);
2151
2152 /*
2153 * Take minimum of what the user wants to send, and the
2154 * space available in the FEP buffer.
2155 */
2156 count = min(count, bufcount);
2157
2158 /*
2159 * Bail if no space left.
2160 */
2161 if (count <= 0) {
2162 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2163 return(0);
2164 }
2165
2166 /*
2167 * Output the printer ON string, if we are in terminal mode, but
2168 * need to be in printer mode.
2169 */
2170 if ((un->un_type == DGNC_PRINT) && !(ch->ch_flags & CH_PRON)) {
2171 dgnc_wmove(ch, ch->ch_digi.digi_onstr,
2172 (int) ch->ch_digi.digi_onlen);
2173 head = (ch->ch_w_head) & tmask;
2174 ch->ch_flags |= CH_PRON;
2175 }
2176
2177 /*
2178 * On the other hand, output the printer OFF string, if we are
2179 * currently in printer mode, but need to output to the terminal.
2180 */
2181 if ((un->un_type != DGNC_PRINT) && (ch->ch_flags & CH_PRON)) {
2182 dgnc_wmove(ch, ch->ch_digi.digi_offstr,
2183 (int) ch->ch_digi.digi_offlen);
2184 head = (ch->ch_w_head) & tmask;
2185 ch->ch_flags &= ~CH_PRON;
2186 }
2187
2188 /*
2189 * If there is nothing left to copy, or I can't handle any more data, leave.
2190 */
2191 if (count <= 0) {
2192 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2193 return(0);
2194 }
2195
2196 if (from_user) {
2197
2198 count = min(count, WRITEBUFLEN);
2199
2200 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2201
2202 /*
2203 * If data is coming from user space, copy it into a temporary
2204 * buffer so we don't get swapped out while doing the copy to
2205 * the board.
2206 */
2207 /* we're allowed to block if it's from_user */
2208 if (down_interruptible(&dgnc_TmpWriteSem)) {
2209 return (-EINTR);
2210 }
2211
2212 /*
2213 * copy_from_user() returns the number
2214 * of bytes that could *NOT* be copied.
2215 */
2216 count -= copy_from_user(dgnc_TmpWriteBuf, (const uchar __user *) buf, count);
2217
2218 if (!count) {
2219 up(&dgnc_TmpWriteSem);
2220 return(-EFAULT);
2221 }
2222
2223 DGNC_LOCK(ch->ch_lock, lock_flags);
2224
2225 buf = dgnc_TmpWriteBuf;
2226
2227 }
2228
2229 n = count;
2230
2231 /*
2232 * If the write wraps over the top of the circular buffer,
2233 * move the portion up to the wrap point, and reset the
2234 * pointers to the bottom.
2235 */
2236 remain = WQUEUESIZE - head;
2237
2238 if (n >= remain) {
2239 n -= remain;
2240 memcpy(ch->ch_wqueue + head, buf, remain);
2241 dgnc_sniff_nowait_nolock(ch, "USER WRITE", ch->ch_wqueue + head, remain);
2242 head = 0;
2243 buf += remain;
2244 }
2245
2246 if (n > 0) {
2247 /*
2248 * Move rest of data.
2249 */
2250 remain = n;
2251 memcpy(ch->ch_wqueue + head, buf, remain);
2252 dgnc_sniff_nowait_nolock(ch, "USER WRITE", ch->ch_wqueue + head, remain);
2253 head += remain;
2254 }
2255
2256 if (count) {
2257 head &= tmask;
2258 ch->ch_w_head = head;
2259 }
2260
2261#if 0
2262 /*
2263 * If this is the print device, and the
2264 * printer is still on, we need to turn it
2265 * off before going idle.
2266 */
2267 if (count == orig_count) {
2268 if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON)) {
2269 head &= tmask;
2270 ch->ch_w_head = head;
2271 dgnc_wmove(ch, ch->ch_digi.digi_offstr,
2272 (int) ch->ch_digi.digi_offlen);
2273 head = (ch->ch_w_head) & tmask;
2274 ch->ch_flags &= ~CH_PRON;
2275 }
2276 }
2277#endif
2278
2279 /* Update printer buffer empty time. */
2280 if ((un->un_type == DGNC_PRINT) && (ch->ch_digi.digi_maxcps > 0)
2281 && (ch->ch_digi.digi_bufsize > 0)) {
2282 ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
2283 }
2284
2285 if (from_user) {
2286 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2287 up(&dgnc_TmpWriteSem);
2288 } else {
2289 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2290 }
2291
2292 DPR_WRITE(("Write finished - Write %d bytes of %d.\n", count, orig_count));
2293
2294 if (count) {
2295 /*
2296 * Channel lock is grabbed and then released
2297 * inside this routine.
2298 */
2299 ch->ch_bd->bd_ops->copy_data_from_queue_to_uart(ch);
2300 }
2301
2302 return (count);
2303}
2304
2305
2306/*
2307 * Return modem signals to ld.
2308 */
2309#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
2310static int dgnc_tty_tiocmget(struct tty_struct *tty)
2311#else
2312static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file)
2313#endif
2314{
2315 struct channel_t *ch;
2316 struct un_t *un;
2317 int result = -EIO;
2318 uchar mstat = 0;
2319 ulong lock_flags;
2320
2321 if (!tty || tty->magic != TTY_MAGIC)
2322 return result;
2323
2324 un = tty->driver_data;
2325 if (!un || un->magic != DGNC_UNIT_MAGIC)
2326 return result;
2327
2328 ch = un->un_ch;
2329 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2330 return result;
2331
2332 DPR_IOCTL(("dgnc_tty_tiocmget start\n"));
2333
2334 DGNC_LOCK(ch->ch_lock, lock_flags);
2335
2336 mstat = (ch->ch_mostat | ch->ch_mistat);
2337
2338 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2339
2340 result = 0;
2341
2342 if (mstat & UART_MCR_DTR)
2343 result |= TIOCM_DTR;
2344 if (mstat & UART_MCR_RTS)
2345 result |= TIOCM_RTS;
2346 if (mstat & UART_MSR_CTS)
2347 result |= TIOCM_CTS;
2348 if (mstat & UART_MSR_DSR)
2349 result |= TIOCM_DSR;
2350 if (mstat & UART_MSR_RI)
2351 result |= TIOCM_RI;
2352 if (mstat & UART_MSR_DCD)
2353 result |= TIOCM_CD;
2354
2355 DPR_IOCTL(("dgnc_tty_tiocmget finish\n"));
2356
2357 return result;
2358}
2359
2360
2361/*
2362 * dgnc_tty_tiocmset()
2363 *
2364 * Set modem signals, called by ld.
2365 */
2366#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
2367static int dgnc_tty_tiocmset(struct tty_struct *tty,
2368 unsigned int set, unsigned int clear)
2369#else
2370static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file,
2371 unsigned int set, unsigned int clear)
2372#endif
2373{
2374 struct board_t *bd;
2375 struct channel_t *ch;
2376 struct un_t *un;
2377 int ret = -EIO;
2378 ulong lock_flags;
2379
2380 if (!tty || tty->magic != TTY_MAGIC)
2381 return ret;
2382
2383 un = tty->driver_data;
2384 if (!un || un->magic != DGNC_UNIT_MAGIC)
2385 return ret;
2386
2387 ch = un->un_ch;
2388 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2389 return ret;
2390
2391 bd = ch->ch_bd;
2392 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2393 return ret;
2394
2395 DPR_IOCTL(("dgnc_tty_tiocmset start\n"));
2396
2397
2398 DGNC_LOCK(ch->ch_lock, lock_flags);
2399
2400 if (set & TIOCM_RTS) {
2401 ch->ch_mostat |= UART_MCR_RTS;
2402 }
2403
2404 if (set & TIOCM_DTR) {
2405 ch->ch_mostat |= UART_MCR_DTR;
2406 }
2407
2408 if (clear & TIOCM_RTS) {
2409 ch->ch_mostat &= ~(UART_MCR_RTS);
2410 }
2411
2412 if (clear & TIOCM_DTR) {
2413 ch->ch_mostat &= ~(UART_MCR_DTR);
2414 }
2415
2416 ch->ch_bd->bd_ops->assert_modem_signals(ch);
2417
2418 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2419
2420 DPR_IOCTL(("dgnc_tty_tiocmset finish\n"));
2421
2422 return (0);
2423}
2424
2425
2426/*
2427 * dgnc_tty_send_break()
2428 *
2429 * Send a Break, called by ld.
2430 */
2431static int dgnc_tty_send_break(struct tty_struct *tty, int msec)
2432{
2433 struct board_t *bd;
2434 struct channel_t *ch;
2435 struct un_t *un;
2436 int ret = -EIO;
2437 ulong lock_flags;
2438
2439 if (!tty || tty->magic != TTY_MAGIC)
2440 return ret;
2441
2442 un = tty->driver_data;
2443 if (!un || un->magic != DGNC_UNIT_MAGIC)
2444 return ret;
2445
2446 ch = un->un_ch;
2447 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2448 return ret;
2449
2450 bd = ch->ch_bd;
2451 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2452 return ret;
2453
2454 switch (msec) {
2455 case -1:
2456 msec = 0xFFFF;
2457 break;
2458 case 0:
2459 msec = 0;
2460 break;
2461 default:
2462 break;
2463 }
2464
2465 DPR_IOCTL(("dgnc_tty_send_break start 1. %lx\n", jiffies));
2466
2467 DGNC_LOCK(ch->ch_lock, lock_flags);
2468
2469 ch->ch_bd->bd_ops->send_break(ch, msec);
2470
2471 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2472
2473 DPR_IOCTL(("dgnc_tty_send_break finish\n"));
2474
2475 return (0);
2476
2477}
2478
2479
2480/*
2481 * dgnc_tty_wait_until_sent()
2482 *
2483 * wait until data has been transmitted, called by ld.
2484 */
2485static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout)
2486{
2487 struct board_t *bd;
2488 struct channel_t *ch;
2489 struct un_t *un;
2490 int rc;
2491
2492 if (!tty || tty->magic != TTY_MAGIC)
2493 return;
2494
2495 un = tty->driver_data;
2496 if (!un || un->magic != DGNC_UNIT_MAGIC)
2497 return;
2498
2499 ch = un->un_ch;
2500 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2501 return;
2502
2503 bd = ch->ch_bd;
2504 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2505 return;
2506
2507 rc = bd->bd_ops->drain(tty, 0);
2508 if (rc) {
2509 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
2510 return;
2511 }
2512 return;
2513}
2514
2515
2516/*
2517 * dgnc_send_xchar()
2518 *
2519 * send a high priority character, called by ld.
2520 */
2521static void dgnc_tty_send_xchar(struct tty_struct *tty, char c)
2522{
2523 struct board_t *bd;
2524 struct channel_t *ch;
2525 struct un_t *un;
2526 ulong lock_flags;
2527
2528 if (!tty || tty->magic != TTY_MAGIC)
2529 return;
2530
2531 un = tty->driver_data;
2532 if (!un || un->magic != DGNC_UNIT_MAGIC)
2533 return;
2534
2535 ch = un->un_ch;
2536 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2537 return;
2538
2539 bd = ch->ch_bd;
2540 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2541 return;
2542
2543 DPR_IOCTL(("dgnc_tty_send_xchar start\n"));
2544 printk("dgnc_tty_send_xchar start\n");
2545
2546 DGNC_LOCK(ch->ch_lock, lock_flags);
2547 bd->bd_ops->send_immediate_char(ch, c);
2548 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2549
2550 DPR_IOCTL(("dgnc_tty_send_xchar finish\n"));
2551 printk("dgnc_tty_send_xchar finish\n");
2552 return;
2553}
2554
2555
2556
2557
2558/*
2559 * Return modem signals to ld.
2560 */
2561static inline int dgnc_get_mstat(struct channel_t *ch)
2562{
2563 unsigned char mstat;
2564 int result = -EIO;
2565 ulong lock_flags;
2566
2567 DPR_IOCTL(("dgnc_getmstat start\n"));
2568
2569 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2570 return(-ENXIO);
2571
2572 DGNC_LOCK(ch->ch_lock, lock_flags);
2573
2574 mstat = (ch->ch_mostat | ch->ch_mistat);
2575
2576 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2577
2578 result = 0;
2579
2580 if (mstat & UART_MCR_DTR)
2581 result |= TIOCM_DTR;
2582 if (mstat & UART_MCR_RTS)
2583 result |= TIOCM_RTS;
2584 if (mstat & UART_MSR_CTS)
2585 result |= TIOCM_CTS;
2586 if (mstat & UART_MSR_DSR)
2587 result |= TIOCM_DSR;
2588 if (mstat & UART_MSR_RI)
2589 result |= TIOCM_RI;
2590 if (mstat & UART_MSR_DCD)
2591 result |= TIOCM_CD;
2592
2593 DPR_IOCTL(("dgnc_getmstat finish\n"));
2594
2595 return(result);
2596}
2597
2598
2599
2600/*
2601 * Return modem signals to ld.
2602 */
2603static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value)
2604{
2605 int result;
2606 int rc;
2607
2608 DPR_IOCTL(("dgnc_get_modem_info start\n"));
2609
2610 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2611 return(-ENXIO);
2612
2613 result = dgnc_get_mstat(ch);
2614
2615 if (result < 0)
2616 return (-ENXIO);
2617
2618 rc = put_user(result, value);
2619
2620 DPR_IOCTL(("dgnc_get_modem_info finish\n"));
2621 return(rc);
2622}
2623
2624
2625/*
2626 * dgnc_set_modem_info()
2627 *
2628 * Set modem signals, called by ld.
2629 */
2630static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
2631{
2632 struct board_t *bd;
2633 struct channel_t *ch;
2634 struct un_t *un;
2635 int ret = -ENXIO;
2636 unsigned int arg = 0;
2637 ulong lock_flags;
2638
2639 if (!tty || tty->magic != TTY_MAGIC)
2640 return ret;
2641
2642 un = tty->driver_data;
2643 if (!un || un->magic != DGNC_UNIT_MAGIC)
2644 return ret;
2645
2646 ch = un->un_ch;
2647 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2648 return ret;
2649
2650 bd = ch->ch_bd;
2651 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2652 return ret;
2653
2654 ret = 0;
2655
2656 DPR_IOCTL(("dgnc_set_modem_info() start\n"));
2657
2658 ret = get_user(arg, value);
2659 if (ret)
2660 return(ret);
2661
2662 switch (command) {
2663 case TIOCMBIS:
2664 if (arg & TIOCM_RTS) {
2665 ch->ch_mostat |= UART_MCR_RTS;
2666 }
2667
2668 if (arg & TIOCM_DTR) {
2669 ch->ch_mostat |= UART_MCR_DTR;
2670 }
2671
2672 break;
2673
2674 case TIOCMBIC:
2675 if (arg & TIOCM_RTS) {
2676 ch->ch_mostat &= ~(UART_MCR_RTS);
2677 }
2678
2679 if (arg & TIOCM_DTR) {
2680 ch->ch_mostat &= ~(UART_MCR_DTR);
2681 }
2682
2683 break;
2684
2685 case TIOCMSET:
2686
2687 if (arg & TIOCM_RTS) {
2688 ch->ch_mostat |= UART_MCR_RTS;
2689 }
2690 else {
2691 ch->ch_mostat &= ~(UART_MCR_RTS);
2692 }
2693
2694 if (arg & TIOCM_DTR) {
2695 ch->ch_mostat |= UART_MCR_DTR;
2696 }
2697 else {
2698 ch->ch_mostat &= ~(UART_MCR_DTR);
2699 }
2700
2701 break;
2702
2703 default:
2704 return(-EINVAL);
2705 }
2706
2707 DGNC_LOCK(ch->ch_lock, lock_flags);
2708
2709 ch->ch_bd->bd_ops->assert_modem_signals(ch);
2710
2711 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2712
2713 DPR_IOCTL(("dgnc_set_modem_info finish\n"));
2714
2715 return (0);
2716}
2717
2718
2719/*
2720 * dgnc_tty_digigeta()
2721 *
2722 * Ioctl to get the information for ditty.
2723 *
2724 *
2725 *
2726 */
2727static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo)
2728{
2729 struct channel_t *ch;
2730 struct un_t *un;
2731 struct digi_t tmp;
2732 ulong lock_flags;
2733
2734 if (!retinfo)
2735 return (-EFAULT);
2736
2737 if (!tty || tty->magic != TTY_MAGIC)
2738 return (-EFAULT);
2739
2740 un = tty->driver_data;
2741 if (!un || un->magic != DGNC_UNIT_MAGIC)
2742 return (-EFAULT);
2743
2744 ch = un->un_ch;
2745 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2746 return (-EFAULT);
2747
2748 memset(&tmp, 0, sizeof(tmp));
2749
2750 DGNC_LOCK(ch->ch_lock, lock_flags);
2751 memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
2752 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2753
2754 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
2755 return (-EFAULT);
2756
2757 return (0);
2758}
2759
2760
2761/*
2762 * dgnc_tty_digiseta()
2763 *
2764 * Ioctl to set the information for ditty.
2765 *
2766 *
2767 *
2768 */
2769static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
2770{
2771 struct board_t *bd;
2772 struct channel_t *ch;
2773 struct un_t *un;
2774 struct digi_t new_digi;
2775 ulong lock_flags;
2776
2777 DPR_IOCTL(("DIGI_SETA start\n"));
2778
2779 if (!tty || tty->magic != TTY_MAGIC)
2780 return (-EFAULT);
2781
2782 un = tty->driver_data;
2783 if (!un || un->magic != DGNC_UNIT_MAGIC)
2784 return (-EFAULT);
2785
2786 ch = un->un_ch;
2787 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2788 return (-EFAULT);
2789
2790 bd = ch->ch_bd;
2791 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2792 return (-EFAULT);
2793
2794 if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
2795 DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
2796 return(-EFAULT);
2797 }
2798
2799 DGNC_LOCK(ch->ch_lock, lock_flags);
2800
2801 /*
2802 * Handle transistions to and from RTS Toggle.
2803 */
2804 if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) && (new_digi.digi_flags & DIGI_RTS_TOGGLE))
2805 ch->ch_mostat &= ~(UART_MCR_RTS);
2806 if ((ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) && !(new_digi.digi_flags & DIGI_RTS_TOGGLE))
2807 ch->ch_mostat |= (UART_MCR_RTS);
2808
2809 /*
2810 * Handle transistions to and from DTR Toggle.
2811 */
2812 if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && (new_digi.digi_flags & DIGI_DTR_TOGGLE))
2813 ch->ch_mostat &= ~(UART_MCR_DTR);
2814 if ((ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && !(new_digi.digi_flags & DIGI_DTR_TOGGLE))
2815 ch->ch_mostat |= (UART_MCR_DTR);
2816
2817 memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
2818
2819 if (ch->ch_digi.digi_maxcps < 1)
2820 ch->ch_digi.digi_maxcps = 1;
2821
2822 if (ch->ch_digi.digi_maxcps > 10000)
2823 ch->ch_digi.digi_maxcps = 10000;
2824
2825 if (ch->ch_digi.digi_bufsize < 10)
2826 ch->ch_digi.digi_bufsize = 10;
2827
2828 if (ch->ch_digi.digi_maxchar < 1)
2829 ch->ch_digi.digi_maxchar = 1;
2830
2831 if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
2832 ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
2833
2834 if (ch->ch_digi.digi_onlen > DIGI_PLEN)
2835 ch->ch_digi.digi_onlen = DIGI_PLEN;
2836
2837 if (ch->ch_digi.digi_offlen > DIGI_PLEN)
2838 ch->ch_digi.digi_offlen = DIGI_PLEN;
2839
2840 ch->ch_bd->bd_ops->param(tty);
2841
2842 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2843
2844 DPR_IOCTL(("DIGI_SETA finish\n"));
2845
2846 return(0);
2847}
2848
2849
2850/*
2851 * dgnc_set_termios()
2852 */
2853static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
2854{
2855 struct board_t *bd;
2856 struct channel_t *ch;
2857 struct un_t *un;
2858 unsigned long lock_flags;
2859
2860 if (!tty || tty->magic != TTY_MAGIC)
2861 return;
2862
2863 un = tty->driver_data;
2864 if (!un || un->magic != DGNC_UNIT_MAGIC)
2865 return;
2866
2867 ch = un->un_ch;
2868 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2869 return;
2870
2871 bd = ch->ch_bd;
2872 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2873 return;
2874
2875 DGNC_LOCK(ch->ch_lock, lock_flags);
2876
2877 ch->ch_c_cflag = tty->termios->c_cflag;
2878 ch->ch_c_iflag = tty->termios->c_iflag;
2879 ch->ch_c_oflag = tty->termios->c_oflag;
2880 ch->ch_c_lflag = tty->termios->c_lflag;
2881 ch->ch_startc = tty->termios->c_cc[VSTART];
2882 ch->ch_stopc = tty->termios->c_cc[VSTOP];
2883
2884 ch->ch_bd->bd_ops->param(tty);
2885 dgnc_carrier(ch);
2886
2887 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2888}
2889
2890
2891static void dgnc_tty_throttle(struct tty_struct *tty)
2892{
2893 struct channel_t *ch;
2894 struct un_t *un;
2895 ulong lock_flags = 0;
2896
2897 if (!tty || tty->magic != TTY_MAGIC)
2898 return;
2899
2900 un = tty->driver_data;
2901 if (!un || un->magic != DGNC_UNIT_MAGIC)
2902 return;
2903
2904 ch = un->un_ch;
2905 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2906 return;
2907
2908 DPR_IOCTL(("dgnc_tty_throttle start\n"));
2909
2910 DGNC_LOCK(ch->ch_lock, lock_flags);
2911
2912 ch->ch_flags |= (CH_FORCED_STOPI);
2913
2914 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2915
2916 DPR_IOCTL(("dgnc_tty_throttle finish\n"));
2917}
2918
2919
2920static void dgnc_tty_unthrottle(struct tty_struct *tty)
2921{
2922 struct channel_t *ch;
2923 struct un_t *un;
2924 ulong lock_flags;
2925
2926 if (!tty || tty->magic != TTY_MAGIC)
2927 return;
2928
2929 un = tty->driver_data;
2930 if (!un || un->magic != DGNC_UNIT_MAGIC)
2931 return;
2932
2933 ch = un->un_ch;
2934 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2935 return;
2936
2937 DPR_IOCTL(("dgnc_tty_unthrottle start\n"));
2938
2939 DGNC_LOCK(ch->ch_lock, lock_flags);
2940
2941 ch->ch_flags &= ~(CH_FORCED_STOPI);
2942
2943 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2944
2945 DPR_IOCTL(("dgnc_tty_unthrottle finish\n"));
2946}
2947
2948
2949static void dgnc_tty_start(struct tty_struct *tty)
2950{
2951 struct board_t *bd;
2952 struct channel_t *ch;
2953 struct un_t *un;
2954 ulong lock_flags;
2955
2956 if (!tty || tty->magic != TTY_MAGIC)
2957 return;
2958
2959 un = tty->driver_data;
2960 if (!un || un->magic != DGNC_UNIT_MAGIC)
2961 return;
2962
2963 ch = un->un_ch;
2964 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2965 return;
2966
2967 bd = ch->ch_bd;
2968 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
2969 return;
2970
2971 DPR_IOCTL(("dgcn_tty_start start\n"));
2972
2973 DGNC_LOCK(ch->ch_lock, lock_flags);
2974
2975 ch->ch_flags &= ~(CH_FORCED_STOP);
2976
2977 DGNC_UNLOCK(ch->ch_lock, lock_flags);
2978
2979 DPR_IOCTL(("dgnc_tty_start finish\n"));
2980}
2981
2982
2983static void dgnc_tty_stop(struct tty_struct *tty)
2984{
2985 struct board_t *bd;
2986 struct channel_t *ch;
2987 struct un_t *un;
2988 ulong lock_flags;
2989
2990 if (!tty || tty->magic != TTY_MAGIC)
2991 return;
2992
2993 un = tty->driver_data;
2994 if (!un || un->magic != DGNC_UNIT_MAGIC)
2995 return;
2996
2997 ch = un->un_ch;
2998 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
2999 return;
3000
3001 bd = ch->ch_bd;
3002 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
3003 return;
3004
3005 DPR_IOCTL(("dgnc_tty_stop start\n"));
3006
3007 DGNC_LOCK(ch->ch_lock, lock_flags);
3008
3009 ch->ch_flags |= (CH_FORCED_STOP);
3010
3011 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3012
3013 DPR_IOCTL(("dgnc_tty_stop finish\n"));
3014}
3015
3016
3017/*
3018 * dgnc_tty_flush_chars()
3019 *
3020 * Flush the cook buffer
3021 *
3022 * Note to self, and any other poor souls who venture here:
3023 *
3024 * flush in this case DOES NOT mean dispose of the data.
3025 * instead, it means "stop buffering and send it if you
3026 * haven't already." Just guess how I figured that out... SRW 2-Jun-98
3027 *
3028 * It is also always called in interrupt context - JAR 8-Sept-99
3029 */
3030static void dgnc_tty_flush_chars(struct tty_struct *tty)
3031{
3032 struct board_t *bd;
3033 struct channel_t *ch;
3034 struct un_t *un;
3035 ulong lock_flags;
3036
3037 if (!tty || tty->magic != TTY_MAGIC)
3038 return;
3039
3040 un = tty->driver_data;
3041 if (!un || un->magic != DGNC_UNIT_MAGIC)
3042 return;
3043
3044 ch = un->un_ch;
3045 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
3046 return;
3047
3048 bd = ch->ch_bd;
3049 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
3050 return;
3051
3052 DPR_IOCTL(("dgnc_tty_flush_chars start\n"));
3053
3054 DGNC_LOCK(ch->ch_lock, lock_flags);
3055
3056 /* Do something maybe here */
3057
3058 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3059
3060 DPR_IOCTL(("dgnc_tty_flush_chars finish\n"));
3061}
3062
3063
3064
3065/*
3066 * dgnc_tty_flush_buffer()
3067 *
3068 * Flush Tx buffer (make in == out)
3069 */
3070static void dgnc_tty_flush_buffer(struct tty_struct *tty)
3071{
3072 struct channel_t *ch;
3073 struct un_t *un;
3074 ulong lock_flags;
3075
3076 if (!tty || tty->magic != TTY_MAGIC)
3077 return;
3078
3079 un = tty->driver_data;
3080 if (!un || un->magic != DGNC_UNIT_MAGIC)
3081 return;
3082
3083 ch = un->un_ch;
3084 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
3085 return;
3086
3087 DPR_IOCTL(("dgnc_tty_flush_buffer on port: %d start\n", ch->ch_portnum));
3088
3089 DGNC_LOCK(ch->ch_lock, lock_flags);
3090
3091 ch->ch_flags &= ~CH_STOP;
3092
3093 /* Flush our write queue */
3094 ch->ch_w_head = ch->ch_w_tail;
3095
3096 /* Flush UARTs transmit FIFO */
3097 ch->ch_bd->bd_ops->flush_uart_write(ch);
3098
3099 if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
3100 ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
3101 wake_up_interruptible(&ch->ch_tun.un_flags_wait);
3102 }
3103 if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
3104 ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
3105 wake_up_interruptible(&ch->ch_pun.un_flags_wait);
3106 }
3107
3108 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3109
3110 DPR_IOCTL(("dgnc_tty_flush_buffer finish\n"));
3111}
3112
3113
3114
3115/*****************************************************************************
3116 *
3117 * The IOCTL function and all of its helpers
3118 *
3119 *****************************************************************************/
3120
3121/*
3122 * dgnc_tty_ioctl()
3123 *
3124 * The usual assortment of ioctl's
3125 */
3126static int dgnc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
3127 unsigned long arg)
3128{
3129 struct board_t *bd;
3130 struct channel_t *ch;
3131 struct un_t *un;
3132 int rc;
3133 ulong lock_flags;
3134 void __user *uarg = (void __user *) arg;
3135
3136 if (!tty || tty->magic != TTY_MAGIC)
3137 return (-ENODEV);
3138
3139 un = tty->driver_data;
3140 if (!un || un->magic != DGNC_UNIT_MAGIC)
3141 return (-ENODEV);
3142
3143 ch = un->un_ch;
3144 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
3145 return (-ENODEV);
3146
3147 bd = ch->ch_bd;
3148 if (!bd || bd->magic != DGNC_BOARD_MAGIC)
3149 return (-ENODEV);
3150
3151 DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
3152 ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3153
3154 DGNC_LOCK(ch->ch_lock, lock_flags);
3155
3156 if (un->un_open_count <= 0) {
3157 DPR_BASIC(("dgnc_tty_ioctl - unit not open.\n"));
3158 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3159 return(-EIO);
3160 }
3161
3162 switch (cmd) {
3163
3164 /* Here are all the standard ioctl's that we MUST implement */
3165
3166 case TCSBRK:
3167 /*
3168 * TCSBRK is SVID version: non-zero arg --> no break
3169 * this behaviour is exploited by tcdrain().
3170 *
3171 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
3172 * between 0.25 and 0.5 seconds so we'll ask for something
3173 * in the middle: 0.375 seconds.
3174 */
3175 rc = tty_check_change(tty);
3176 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3177 if (rc) {
3178 return(rc);
3179 }
3180
3181 rc = ch->ch_bd->bd_ops->drain(tty, 0);
3182
3183 if (rc) {
3184 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
3185 return(-EINTR);
3186 }
3187
3188 DGNC_LOCK(ch->ch_lock, lock_flags);
3189
3190 if(((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) {
3191 ch->ch_bd->bd_ops->send_break(ch, 250);
3192 }
3193
3194 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3195
3196 DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
3197 ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3198
3199 return(0);
3200
3201
3202 case TCSBRKP:
3203 /* support for POSIX tcsendbreak()
3204 * According to POSIX.1 spec (7.2.2.1.2) breaks should be
3205 * between 0.25 and 0.5 seconds so we'll ask for something
3206 * in the middle: 0.375 seconds.
3207 */
3208 rc = tty_check_change(tty);
3209 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3210 if (rc) {
3211 return(rc);
3212 }
3213
3214 rc = ch->ch_bd->bd_ops->drain(tty, 0);
3215 if (rc) {
3216 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
3217 return(-EINTR);
3218 }
3219
3220 DGNC_LOCK(ch->ch_lock, lock_flags);
3221
3222 ch->ch_bd->bd_ops->send_break(ch, 250);
3223
3224 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3225
3226 DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
3227 ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3228
3229 return(0);
3230
3231 case TIOCSBRK:
3232 rc = tty_check_change(tty);
3233 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3234 if (rc) {
3235 return(rc);
3236 }
3237
3238 rc = ch->ch_bd->bd_ops->drain(tty, 0);
3239 if (rc) {
3240 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
3241 return(-EINTR);
3242 }
3243
3244 DGNC_LOCK(ch->ch_lock, lock_flags);
3245
3246 ch->ch_bd->bd_ops->send_break(ch, 250);
3247
3248 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3249
3250 DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
3251 ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3252
3253 return(0);
3254
3255 case TIOCCBRK:
3256 /* Do Nothing */
3257 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3258 return 0;
3259
3260 case TIOCGSOFTCAR:
3261
3262 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3263
3264 rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
3265 return(rc);
3266
3267 case TIOCSSOFTCAR:
3268
3269 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3270 rc = get_user(arg, (unsigned long __user *) arg);
3271 if (rc)
3272 return(rc);
3273
3274 DGNC_LOCK(ch->ch_lock, lock_flags);
3275 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
3276 ch->ch_bd->bd_ops->param(tty);
3277 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3278
3279 return(0);
3280
3281 case TIOCMGET:
3282 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3283 return(dgnc_get_modem_info(ch, uarg));
3284
3285 case TIOCMBIS:
3286 case TIOCMBIC:
3287 case TIOCMSET:
3288 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3289 return(dgnc_set_modem_info(tty, cmd, uarg));
3290
3291 /*
3292 * Here are any additional ioctl's that we want to implement
3293 */
3294
3295 case TCFLSH:
3296 /*
3297 * The linux tty driver doesn't have a flush
3298 * input routine for the driver, assuming all backed
3299 * up data is in the line disc. buffers. However,
3300 * we all know that's not the case. Here, we
3301 * act on the ioctl, but then lie and say we didn't
3302 * so the line discipline will process the flush
3303 * also.
3304 */
3305 rc = tty_check_change(tty);
3306 if (rc) {
3307 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3308 return(rc);
3309 }
3310
3311 if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
3312 ch->ch_r_head = ch->ch_r_tail;
3313 ch->ch_bd->bd_ops->flush_uart_read(ch);
3314 /* Force queue flow control to be released, if needed */
3315 dgnc_check_queue_flow_control(ch);
3316 }
3317
3318 if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) {
3319 if (!(un->un_type == DGNC_PRINT)) {
3320 ch->ch_w_head = ch->ch_w_tail;
3321 ch->ch_bd->bd_ops->flush_uart_write(ch);
3322
3323 if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) {
3324 ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY);
3325 wake_up_interruptible(&ch->ch_tun.un_flags_wait);
3326 }
3327
3328 if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) {
3329 ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY);
3330 wake_up_interruptible(&ch->ch_pun.un_flags_wait);
3331 }
3332
3333 }
3334 }
3335
3336 /* pretend we didn't recognize this IOCTL */
3337 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3338 return(-ENOIOCTLCMD);
3339
3340#ifdef TIOCGETP
3341 case TIOCGETP:
3342#endif
3343 case TCGETS:
3344 case TCGETA:
3345#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
3346 if (tty->ldisc->ops->ioctl) {
3347#else
3348 if (tty->ldisc.ops->ioctl) {
3349#endif
3350 int retval = (-ENXIO);
3351
3352 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3353
3354 if (tty->termios) {
3355#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
3356 retval = ((tty->ldisc->ops->ioctl) (tty, file, cmd, arg));
3357#else
3358 retval = ((tty->ldisc.ops->ioctl) (tty, file, cmd, arg));
3359#endif
3360 }
3361
3362 DPR_IOCTL(("dgnc_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n",
3363 __LINE__, ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3364 return(retval);
3365 }
3366
3367 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3368 DPR_IOCTL(("dgnc_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n",
3369 __LINE__, ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3370
3371 return(-ENOIOCTLCMD);
3372
3373 case TCSETSF:
3374 case TCSETSW:
3375 /*
3376 * The linux tty driver doesn't have a flush
3377 * input routine for the driver, assuming all backed
3378 * up data is in the line disc. buffers. However,
3379 * we all know that's not the case. Here, we
3380 * act on the ioctl, but then lie and say we didn't
3381 * so the line discipline will process the flush
3382 * also.
3383 */
3384 if (cmd == TCSETSF) {
3385 /* flush rx */
3386 ch->ch_flags &= ~CH_STOP;
3387 ch->ch_r_head = ch->ch_r_tail;
3388 ch->ch_bd->bd_ops->flush_uart_read(ch);
3389 /* Force queue flow control to be released, if needed */
3390 dgnc_check_queue_flow_control(ch);
3391 }
3392
3393 /* now wait for all the output to drain */
3394 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3395 rc = ch->ch_bd->bd_ops->drain(tty, 0);
3396 if (rc) {
3397 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d\n", rc));
3398 return(-EINTR);
3399 }
3400
3401 DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
3402 ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
3403
3404 /* pretend we didn't recognize this */
3405 return(-ENOIOCTLCMD);
3406
3407 case TCSETAW:
3408
3409 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3410 rc = ch->ch_bd->bd_ops->drain(tty, 0);
3411 if (rc) {
3412 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
3413 return(-EINTR);
3414 }
3415
3416 /* pretend we didn't recognize this */
3417 return(-ENOIOCTLCMD);
3418
3419 case TCXONC:
3420 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3421 /* Make the ld do it */
3422 return(-ENOIOCTLCMD);
3423
3424 case DIGI_GETA:
3425 /* get information for ditty */
3426 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3427 return(dgnc_tty_digigeta(tty, uarg));
3428
3429 case DIGI_SETAW:
3430 case DIGI_SETAF:
3431
3432 /* set information for ditty */
3433 if (cmd == (DIGI_SETAW)) {
3434
3435 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3436 rc = ch->ch_bd->bd_ops->drain(tty, 0);
3437 if (rc) {
3438 DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
3439 return(-EINTR);
3440 }
3441 DGNC_LOCK(ch->ch_lock, lock_flags);
3442 }
3443 else {
3444 tty_ldisc_flush(tty);
3445 }
3446 /* fall thru */
3447
3448 case DIGI_SETA:
3449 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3450 return(dgnc_tty_digiseta(tty, uarg));
3451
3452 case DIGI_LOOPBACK:
3453 {
3454 uint loopback = 0;
3455 /* Let go of locks when accessing user space, could sleep */
3456 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3457 rc = get_user(loopback, (unsigned int __user *) arg);
3458 if (rc)
3459 return(rc);
3460 DGNC_LOCK(ch->ch_lock, lock_flags);
3461
3462 /* Enable/disable internal loopback for this port */
3463 if (loopback)
3464 ch->ch_flags |= CH_LOOPBACK;
3465 else
3466 ch->ch_flags &= ~(CH_LOOPBACK);
3467
3468 ch->ch_bd->bd_ops->param(tty);
3469 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3470 return(0);
3471 }
3472
3473 case DIGI_GETCUSTOMBAUD:
3474 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3475 rc = put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
3476 return(rc);
3477
3478 case DIGI_SETCUSTOMBAUD:
3479 {
3480 uint new_rate;
3481 /* Let go of locks when accessing user space, could sleep */
3482 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3483 rc = get_user(new_rate, (unsigned int __user *) arg);
3484 if (rc)
3485 return(rc);
3486 DGNC_LOCK(ch->ch_lock, lock_flags);
3487 dgnc_set_custom_speed(ch, new_rate);
3488 ch->ch_bd->bd_ops->param(tty);
3489 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3490 return(0);
3491 }
3492
3493 /*
3494 * This ioctl allows insertion of a character into the front
3495 * of any pending data to be transmitted.
3496 *
3497 * This ioctl is to satify the "Send Character Immediate"
3498 * call that the RealPort protocol spec requires.
3499 */
3500 case DIGI_REALPORT_SENDIMMEDIATE:
3501 {
3502 unsigned char c;
3503 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3504 rc = get_user(c, (unsigned char __user *) arg);
3505 if (rc)
3506 return(rc);
3507 DGNC_LOCK(ch->ch_lock, lock_flags);
3508 ch->ch_bd->bd_ops->send_immediate_char(ch, c);
3509 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3510 return(0);
3511 }
3512
3513 /*
3514 * This ioctl returns all the current counts for the port.
3515 *
3516 * This ioctl is to satify the "Line Error Counters"
3517 * call that the RealPort protocol spec requires.
3518 */
3519 case DIGI_REALPORT_GETCOUNTERS:
3520 {
3521 struct digi_getcounter buf;
3522
3523 buf.norun = ch->ch_err_overrun;
3524 buf.noflow = 0; /* The driver doesn't keep this stat */
3525 buf.nframe = ch->ch_err_frame;
3526 buf.nparity = ch->ch_err_parity;
3527 buf.nbreak = ch->ch_err_break;
3528 buf.rbytes = ch->ch_rxcount;
3529 buf.tbytes = ch->ch_txcount;
3530
3531 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3532
3533 if (copy_to_user(uarg, &buf, sizeof(struct digi_getcounter))) {
3534 return (-EFAULT);
3535 }
3536 return(0);
3537 }
3538
3539 /*
3540 * This ioctl returns all current events.
3541 *
3542 * This ioctl is to satify the "Event Reporting"
3543 * call that the RealPort protocol spec requires.
3544 */
3545 case DIGI_REALPORT_GETEVENTS:
3546 {
3547 unsigned int events = 0;
3548
3549 /* NOTE: MORE EVENTS NEEDS TO BE ADDED HERE */
3550 if (ch->ch_flags & CH_BREAK_SENDING)
3551 events |= EV_TXB;
3552 if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP)) {
3553 events |= (EV_OPU | EV_OPS);
3554 }
3555 if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI)) {
3556 events |= (EV_IPU | EV_IPS);
3557 }
3558
3559 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3560 rc = put_user(events, (unsigned int __user *) arg);
3561 return(rc);
3562 }
3563
3564 /*
3565 * This ioctl returns TOUT and TIN counters based
3566 * upon the values passed in by the RealPort Server.
3567 * It also passes back whether the UART Transmitter is
3568 * empty as well.
3569 */
3570 case DIGI_REALPORT_GETBUFFERS:
3571 {
3572 struct digi_getbuffer buf;
3573 int tdist;
3574 int count;
3575
3576 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3577
3578 /*
3579 * Get data from user first.
3580 */
3581 if (copy_from_user(&buf, uarg, sizeof(struct digi_getbuffer))) {
3582 return (-EFAULT);
3583 }
3584
3585 DGNC_LOCK(ch->ch_lock, lock_flags);
3586
3587 /*
3588 * Figure out how much data is in our RX and TX queues.
3589 */
3590 buf.rxbuf = (ch->ch_r_head - ch->ch_r_tail) & RQUEUEMASK;
3591 buf.txbuf = (ch->ch_w_head - ch->ch_w_tail) & WQUEUEMASK;
3592
3593 /*
3594 * Is the UART empty? Add that value to whats in our TX queue.
3595 */
3596 count = buf.txbuf + ch->ch_bd->bd_ops->get_uart_bytes_left(ch);
3597
3598 /*
3599 * Figure out how much data the RealPort Server believes should
3600 * be in our TX queue.
3601 */
3602 tdist = (buf.tIn - buf.tOut) & 0xffff;
3603
3604 /*
3605 * If we have more data than the RealPort Server believes we
3606 * should have, reduce our count to its amount.
3607 *
3608 * This count difference CAN happen because the Linux LD can
3609 * insert more characters into our queue for OPOST processing
3610 * that the RealPort Server doesn't know about.
3611 */
3612 if (buf.txbuf > tdist) {
3613 buf.txbuf = tdist;
3614 }
3615
3616 /*
3617 * Report whether our queue and UART TX are completely empty.
3618 */
3619 if (count) {
3620 buf.txdone = 0;
3621 } else {
3622 buf.txdone = 1;
3623 }
3624
3625 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3626
3627 if (copy_to_user(uarg, &buf, sizeof(struct digi_getbuffer))) {
3628 return (-EFAULT);
3629 }
3630 return(0);
3631 }
3632 default:
3633 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3634
3635 DPR_IOCTL(("dgnc_tty_ioctl - in default\n"));
3636 DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
3637 dgnc_ioctl_name(cmd), cmd, arg));
3638
3639 return(-ENOIOCTLCMD);
3640 }
3641
3642 DGNC_UNLOCK(ch->ch_lock, lock_flags);
3643
3644 DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
3645 dgnc_ioctl_name(cmd), cmd, arg));
3646
3647 return(0);
3648}
diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h
new file mode 100644
index 000000000000..deb388d2f4cf
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_tty.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 */
21
22#ifndef __DGNC_TTY_H
23#define __DGNC_TTY_H
24
25#include "dgnc_driver.h"
26
27int dgnc_tty_register(struct board_t *brd);
28
29int dgnc_tty_preinit(void);
30int dgnc_tty_init(struct board_t *);
31
32void dgnc_tty_post_uninit(void);
33void dgnc_tty_uninit(struct board_t *);
34
35void dgnc_input(struct channel_t *ch);
36void dgnc_carrier(struct channel_t *ch);
37void dgnc_wakeup_writes(struct channel_t *ch);
38void dgnc_check_queue_flow_control(struct channel_t *ch);
39
40void dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int nbuf);
41
42#endif
diff --git a/drivers/staging/dgnc/dgnc_types.h b/drivers/staging/dgnc/dgnc_types.h
new file mode 100644
index 000000000000..4fa358535f84
--- /dev/null
+++ b/drivers/staging/dgnc/dgnc_types.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 */
21
22#ifndef __DGNC_TYPES_H
23#define __DGNC_TYPES_H
24
25#ifndef TRUE
26# define TRUE 1
27#endif
28
29#ifndef FALSE
30# define FALSE 0
31#endif
32
33/* Required for our shared headers! */
34typedef unsigned char uchar;
35
36#endif
diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h
new file mode 100644
index 000000000000..ab903823ab07
--- /dev/null
+++ b/drivers/staging/dgnc/digi.h
@@ -0,0 +1,419 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * $Id: digi.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $
20 *
21 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
22 */
23
24#ifndef __DIGI_H
25#define __DIGI_H
26
27/************************************************************************
28 *** Definitions for Digi ditty(1) command.
29 ************************************************************************/
30
31
32/*
33 * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved.
34 */
35
36/************************************************************************
37 * This module provides application access to special Digi
38 * serial line enhancements which are not standard UNIX(tm) features.
39 ************************************************************************/
40
41#if !defined(TIOCMODG)
42
43#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */
44#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */
45
46#ifndef TIOCM_LE
47#define TIOCM_LE 0x01 /* line enable */
48#define TIOCM_DTR 0x02 /* data terminal ready */
49#define TIOCM_RTS 0x04 /* request to send */
50#define TIOCM_ST 0x08 /* secondary transmit */
51#define TIOCM_SR 0x10 /* secondary receive */
52#define TIOCM_CTS 0x20 /* clear to send */
53#define TIOCM_CAR 0x40 /* carrier detect */
54#define TIOCM_RNG 0x80 /* ring indicator */
55#define TIOCM_DSR 0x100 /* data set ready */
56#define TIOCM_RI TIOCM_RNG /* ring (alternate) */
57#define TIOCM_CD TIOCM_CAR /* carrier detect (alt) */
58#endif
59
60#endif
61
62#if !defined(TIOCMSET)
63#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */
64#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */
65#endif
66
67#if !defined(TIOCMBIC)
68#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */
69#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */
70#endif
71
72
73#if !defined(TIOCSDTR)
74#define TIOCSDTR ('e'<<8) | 0 /* set DTR */
75#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */
76#endif
77
78/************************************************************************
79 * Ioctl command arguments for DIGI parameters.
80 ************************************************************************/
81#define DIGI_GETA ('e'<<8) | 94 /* Read params */
82
83#define DIGI_SETA ('e'<<8) | 95 /* Set params */
84#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */
85#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */
86
87#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */
88 /* Adapter Memory */
89
90#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */
91 /* control characters */
92#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */
93 /* control characters */
94#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */
95 /* flow control chars */
96#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */
97 /* flow control chars */
98
99#define DIGI_GEDELAY ('d'<<8) | 246 /* Get edelay */
100#define DIGI_SEDELAY ('d'<<8) | 247 /* Set edelay */
101
102struct digiflow_t {
103 unsigned char startc; /* flow cntl start char */
104 unsigned char stopc; /* flow cntl stop char */
105};
106
107
108#ifdef FLOW_2200
109#define F2200_GETA ('e'<<8) | 104 /* Get 2x36 flow cntl flags */
110#define F2200_SETAW ('e'<<8) | 105 /* Set 2x36 flow cntl flags */
111#define F2200_MASK 0x03 /* 2200 flow cntl bit mask */
112#define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */
113#define PCNTL_2200 0x02 /* 2x36 printer flow cntl */
114#define F2200_XON 0xf8
115#define P2200_XON 0xf9
116#define F2200_XOFF 0xfa
117#define P2200_XOFF 0xfb
118
119#define FXOFF_MASK 0x03 /* 2200 flow status mask */
120#define RCVD_FXOFF 0x01 /* 2x36 Terminal XOFF rcvd */
121#define RCVD_PXOFF 0x02 /* 2x36 Printer XOFF rcvd */
122#endif
123
124/************************************************************************
125 * Values for digi_flags
126 ************************************************************************/
127#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */
128#define DIGI_FAST 0x0002 /* Fast baud rates */
129#define RTSPACE 0x0004 /* RTS input flow control */
130#define CTSPACE 0x0008 /* CTS output flow control */
131#define DSRPACE 0x0010 /* DSR output flow control */
132#define DCDPACE 0x0020 /* DCD output flow control */
133#define DTRPACE 0x0040 /* DTR input flow control */
134#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */
135#define DIGI_FORCEDCD 0x0100 /* Force carrier */
136#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */
137#define DIGI_AIXON 0x0400 /* Aux flow control in fep */
138#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl*/
139#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input*/
140#define DIGI_DTR_TOGGLE 0x2000 /* Support DTR Toggle */
141#define DIGI_422 0x4000 /* for 422/232 selectable panel */
142#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */
143
144/************************************************************************
145 * These options are not supported on the comxi.
146 ************************************************************************/
147#define DIGI_COMXI (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
148
149#define DIGI_PLEN 28 /* String length */
150#define DIGI_TSIZ 10 /* Terminal string len */
151
152/************************************************************************
153 * Structure used with ioctl commands for DIGI parameters.
154 ************************************************************************/
155struct digi_t {
156 unsigned short digi_flags; /* Flags (see above) */
157 unsigned short digi_maxcps; /* Max printer CPS */
158 unsigned short digi_maxchar; /* Max chars in print queue */
159 unsigned short digi_bufsize; /* Buffer size */
160 unsigned char digi_onlen; /* Length of ON string */
161 unsigned char digi_offlen; /* Length of OFF string */
162 char digi_onstr[DIGI_PLEN]; /* Printer on string */
163 char digi_offstr[DIGI_PLEN]; /* Printer off string */
164 char digi_term[DIGI_TSIZ]; /* terminal string */
165};
166
167/************************************************************************
168 * KME definitions and structures.
169 ************************************************************************/
170#define RW_IDLE 0 /* Operation complete */
171#define RW_READ 1 /* Read Concentrator Memory */
172#define RW_WRITE 2 /* Write Concentrator Memory */
173
174struct rw_t {
175 unsigned char rw_req; /* Request type */
176 unsigned char rw_board; /* Host Adapter board number */
177 unsigned char rw_conc; /* Concentrator number */
178 unsigned char rw_reserved; /* Reserved for expansion */
179 unsigned int rw_addr; /* Address in concentrator */
180 unsigned short rw_size; /* Read/write request length */
181 unsigned char rw_data[128]; /* Data to read/write */
182};
183
184/***********************************************************************
185 * Shrink Buffer and Board Information definitions and structures.
186
187 ************************************************************************/
188 /* Board type return codes */
189#define PCXI_TYPE 1 /* Board type at the designated port is a PC/Xi */
190#define PCXM_TYPE 2 /* Board type at the designated port is a PC/Xm */
191#define PCXE_TYPE 3 /* Board type at the designated port is a PC/Xe */
192#define MCXI_TYPE 4 /* Board type at the designated port is a MC/Xi */
193#define COMXI_TYPE 5 /* Board type at the designated port is a COM/Xi */
194
195 /* Non-Zero Result codes. */
196#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */
197#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */
198#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */
199#define RESULT_TOOSML 4 /* Too small an area to shrink. */
200#define RESULT_NOCHAN 5 /* Channel structure for the board was not found */
201
202struct shrink_buf_struct {
203 unsigned int shrink_buf_vaddr; /* Virtual address of board */
204 unsigned int shrink_buf_phys; /* Physical address of board */
205 unsigned int shrink_buf_bseg; /* Amount of board memory */
206 unsigned int shrink_buf_hseg; /* '186 Begining of Dual-Port */
207
208 unsigned int shrink_buf_lseg; /* '186 Begining of freed memory */
209 unsigned int shrink_buf_mseg; /* Linear address from start of
210 dual-port were freed memory
211 begins, host viewpoint. */
212
213 unsigned int shrink_buf_bdparam; /* Parameter for xxmemon and
214 xxmemoff */
215
216 unsigned int shrink_buf_reserva; /* Reserved */
217 unsigned int shrink_buf_reservb; /* Reserved */
218 unsigned int shrink_buf_reservc; /* Reserved */
219 unsigned int shrink_buf_reservd; /* Reserved */
220
221 unsigned char shrink_buf_result; /* Reason for call failing
222 Zero is Good return */
223 unsigned char shrink_buf_init; /* Non-Zero if it caused an
224 xxinit call. */
225
226 unsigned char shrink_buf_anports; /* Number of async ports */
227 unsigned char shrink_buf_snports; /* Number of sync ports */
228 unsigned char shrink_buf_type; /* Board type 1 = PC/Xi,
229 2 = PC/Xm,
230 3 = PC/Xe
231 4 = MC/Xi
232 5 = COMX/i */
233 unsigned char shrink_buf_card; /* Card number */
234
235};
236
237/************************************************************************
238 * Structure to get driver status information
239 ************************************************************************/
240struct digi_dinfo {
241 unsigned int dinfo_nboards; /* # boards configured */
242 char dinfo_reserved[12]; /* for future expansion */
243 char dinfo_version[16]; /* driver version */
244};
245
246#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */
247
248/************************************************************************
249 * Structure used with ioctl commands for per-board information
250 *
251 * physsize and memsize differ when board has "windowed" memory
252 ************************************************************************/
253struct digi_info {
254 unsigned int info_bdnum; /* Board number (0 based) */
255 unsigned int info_ioport; /* io port address */
256 unsigned int info_physaddr; /* memory address */
257 unsigned int info_physsize; /* Size of host mem window */
258 unsigned int info_memsize; /* Amount of dual-port mem */
259 /* on board */
260 unsigned short info_bdtype; /* Board type */
261 unsigned short info_nports; /* number of ports */
262 char info_bdstate; /* board state */
263 char info_reserved[7]; /* for future expansion */
264};
265
266#define DIGI_GETBD ('d'<<8) | 249 /* get board info */
267
268struct digi_stat {
269 unsigned int info_chan; /* Channel number (0 based) */
270 unsigned int info_brd; /* Board number (0 based) */
271 unsigned int info_cflag; /* cflag for channel */
272 unsigned int info_iflag; /* iflag for channel */
273 unsigned int info_oflag; /* oflag for channel */
274 unsigned int info_mstat; /* mstat for channel */
275 unsigned int info_tx_data; /* tx_data for channel */
276 unsigned int info_rx_data; /* rx_data for channel */
277 unsigned int info_hflow; /* hflow for channel */
278 unsigned int info_reserved[8]; /* for future expansion */
279};
280
281#define DIGI_GETSTAT ('d'<<8) | 244 /* get board info */
282/************************************************************************
283 *
284 * Structure used with ioctl commands for per-channel information
285 *
286 ************************************************************************/
287struct digi_ch {
288 unsigned int info_bdnum; /* Board number (0 based) */
289 unsigned int info_channel; /* Channel index number */
290 unsigned int info_ch_cflag; /* Channel cflag */
291 unsigned int info_ch_iflag; /* Channel iflag */
292 unsigned int info_ch_oflag; /* Channel oflag */
293 unsigned int info_chsize; /* Channel structure size */
294 unsigned int info_sleep_stat; /* sleep status */
295 dev_t info_dev; /* device number */
296 unsigned char info_initstate; /* Channel init state */
297 unsigned char info_running; /* Channel running state */
298 int reserved[8]; /* reserved for future use */
299};
300
301/*
302* This structure is used with the DIGI_FEPCMD ioctl to
303* tell the driver which port to send the command for.
304*/
305struct digi_cmd {
306 int cmd;
307 int word;
308 int ncmds;
309 int chan; /* channel index (zero based) */
310 int bdid; /* board index (zero based) */
311};
312
313
314struct digi_getbuffer /* Struct for holding buffer use counts */
315{
316 unsigned long tIn;
317 unsigned long tOut;
318 unsigned long rxbuf;
319 unsigned long txbuf;
320 unsigned long txdone;
321};
322
323struct digi_getcounter
324{
325 unsigned long norun; /* number of UART overrun errors */
326 unsigned long noflow; /* number of buffer overflow errors */
327 unsigned long nframe; /* number of framing errors */
328 unsigned long nparity; /* number of parity errors */
329 unsigned long nbreak; /* number of breaks received */
330 unsigned long rbytes; /* number of received bytes */
331 unsigned long tbytes; /* number of bytes transmitted fully */
332};
333
334/*
335* info_sleep_stat defines
336*/
337#define INFO_RUNWAIT 0x0001
338#define INFO_WOPEN 0x0002
339#define INFO_TTIOW 0x0004
340#define INFO_CH_RWAIT 0x0008
341#define INFO_CH_WEMPTY 0x0010
342#define INFO_CH_WLOW 0x0020
343#define INFO_XXBUF_BUSY 0x0040
344
345#define DIGI_GETCH ('d'<<8) | 245 /* get board info */
346
347/* Board type definitions */
348
349#define SUBTYPE 0007
350#define T_PCXI 0000
351#define T_PCXM 0001
352#define T_PCXE 0002
353#define T_PCXR 0003
354#define T_SP 0004
355#define T_SP_PLUS 0005
356# define T_HERC 0000
357# define T_HOU 0001
358# define T_LON 0002
359# define T_CHA 0003
360#define FAMILY 0070
361#define T_COMXI 0000
362#define T_PCXX 0010
363#define T_CX 0020
364#define T_EPC 0030
365#define T_PCLITE 0040
366#define T_SPXX 0050
367#define T_AVXX 0060
368#define T_DXB 0070
369#define T_A2K_4_8 0070
370#define BUSTYPE 0700
371#define T_ISABUS 0000
372#define T_MCBUS 0100
373#define T_EISABUS 0200
374#define T_PCIBUS 0400
375
376/* Board State Definitions */
377
378#define BD_RUNNING 0x0
379#define BD_REASON 0x7f
380#define BD_NOTFOUND 0x1
381#define BD_NOIOPORT 0x2
382#define BD_NOMEM 0x3
383#define BD_NOBIOS 0x4
384#define BD_NOFEP 0x5
385#define BD_FAILED 0x6
386#define BD_ALLOCATED 0x7
387#define BD_TRIBOOT 0x8
388#define BD_BADKME 0x80
389
390#define DIGI_SPOLL ('d'<<8) | 254 /* change poller rate */
391
392#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */
393#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */
394
395#define DIGI_REALPORT_GETBUFFERS ('e'<<8 ) | 108
396#define DIGI_REALPORT_SENDIMMEDIATE ('e'<<8 ) | 109
397#define DIGI_REALPORT_GETCOUNTERS ('e'<<8 ) | 110
398#define DIGI_REALPORT_GETEVENTS ('e'<<8 ) | 111
399
400#define EV_OPU 0x0001 //!<Output paused by client
401#define EV_OPS 0x0002 //!<Output paused by reqular sw flowctrl
402#define EV_OPX 0x0004 //!<Output paused by extra sw flowctrl
403#define EV_OPH 0x0008 //!<Output paused by hw flowctrl
404#define EV_OPT 0x0800 //!<Output paused for RTS Toggle predelay
405
406#define EV_IPU 0x0010 //!<Input paused unconditionally by user
407#define EV_IPS 0x0020 //!<Input paused by high/low water marks
408//#define EV_IPH 0x0040 //!<Input paused w/ hardware
409#define EV_IPA 0x0400 //!<Input paused by pattern alarm module
410
411#define EV_TXB 0x0040 //!<Transmit break pending
412#define EV_TXI 0x0080 //!<Transmit immediate pending
413#define EV_TXF 0x0100 //!<Transmit flowctrl char pending
414#define EV_RXB 0x0200 //!<Break received
415
416#define EV_OPALL 0x080f //!<Output pause flags
417#define EV_IPALL 0x0430 //!<Input pause flags
418
419#endif /* DIGI_H */
diff --git a/drivers/staging/dgnc/dpacompat.h b/drivers/staging/dgnc/dpacompat.h
new file mode 100644
index 000000000000..44379eb22f42
--- /dev/null
+++ b/drivers/staging/dgnc/dpacompat.h
@@ -0,0 +1,115 @@
1/*
2 * Copyright 2003 Digi International (www.digi.com)
3 * Scott H Kilau <Scott_Kilau at digi dot com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
20 */
21
22
23/*
24 * This structure holds data needed for the intelligent <--> nonintelligent
25 * DPA translation
26 */
27 struct ni_info {
28 int board;
29 int channel;
30 int dtr;
31 int rts;
32 int cts;
33 int dsr;
34 int ri;
35 int dcd;
36 int curtx;
37 int currx;
38 unsigned short iflag;
39 unsigned short oflag;
40 unsigned short cflag;
41 unsigned short lflag;
42
43 unsigned int mstat;
44 unsigned char hflow;
45
46 unsigned char xmit_stopped;
47 unsigned char recv_stopped;
48
49 unsigned int baud;
50};
51
52#define RW_READ 1
53#define RW_WRITE 2
54#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */
55
56#define SUBTYPE 0007
57#define T_PCXI 0000
58#define T_PCXEM 0001
59#define T_PCXE 0002
60#define T_PCXR 0003
61#define T_SP 0004
62#define T_SP_PLUS 0005
63
64#define T_HERC 0000
65#define T_HOU 0001
66#define T_LON 0002
67#define T_CHA 0003
68
69#define T_NEO 0000
70#define T_NEO_EXPRESS 0001
71#define T_CLASSIC 0002
72
73#define FAMILY 0070
74#define T_COMXI 0000
75#define T_NI 0000
76#define T_PCXX 0010
77#define T_CX 0020
78#define T_EPC 0030
79#define T_PCLITE 0040
80#define T_SPXX 0050
81#define T_AVXX 0060
82#define T_DXB 0070
83#define T_A2K_4_8 0070
84
85#define BUSTYPE 0700
86#define T_ISABUS 0000
87#define T_MCBUS 0100
88#define T_EISABUS 0200
89#define T_PCIBUS 0400
90
91/* Board State Definitions */
92
93#define BD_RUNNING 0x0
94#define BD_REASON 0x7f
95#define BD_NOTFOUND 0x1
96#define BD_NOIOPORT 0x2
97#define BD_NOMEM 0x3
98#define BD_NOBIOS 0x4
99#define BD_NOFEP 0x5
100#define BD_FAILED 0x6
101#define BD_ALLOCATED 0x7
102#define BD_TRIBOOT 0x8
103#define BD_BADKME 0x80
104
105#define DIGI_AIXON 0x0400 /* Aux flow control in fep */
106
107/* Ioctls needed for dpa operation */
108
109#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */
110#define DIGI_GETBD ('d'<<8) | 249 /* get board info */
111#define DIGI_GET_NI_INFO ('d'<<8) | 250 /* nonintelligent state snfo */
112
113/* Other special ioctls */
114#define DIGI_TIMERIRQ ('d'<<8) | 251 /* Enable/disable RS_TIMER use */
115#define DIGI_LOOPBACK ('d'<<8) | 252 /* Enable/disable UART internal loopback */