Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (49 commits) serial8250: ratelimit "too much work" error serial: bfin_sport_uart: speed up sport RX sample rate to be 3% faster serial: abstraction for 8250 legacy ports serial/imx: check that the buffer is non-empty before sending it out serial: mfd: add more baud rates support jsm: Remove the uart port on errors Alchemy: Add UART PM methods. 8250: allow platforms to override PM hook. altera_uart: Don't use plain integer as NULL pointer altera_uart: Fix missing prototype for registering an early console altera_uart: Fixup type usage of port flags altera_uart: Make it possible to use Altera UART and 8250 ports together altera_uart: Add support for different address strides altera_uart: Add support for getting mapbase and IRQ from resources altera_uart: Add support for polling mode (IRQ-less) serial: Factor out uart_poll_timeout() from 8250 driver serial: mark the 8250 driver as maintained serial: 8250: Don't delay after transmitter is ready. tty: MAINTAINERS: add drivers/serial/jsm/ as maintained driver vcs: invoke the vt update callback when /dev/vcs* is written to ...
This commit is contained in:
commit
73ecf3a6e3
66 changed files with 1756 additions and 1532 deletions
|
@ -239,6 +239,7 @@ Your cooperation is appreciated.
|
||||||
0 = /dev/tty Current TTY device
|
0 = /dev/tty Current TTY device
|
||||||
1 = /dev/console System console
|
1 = /dev/console System console
|
||||||
2 = /dev/ptmx PTY master multiplex
|
2 = /dev/ptmx PTY master multiplex
|
||||||
|
3 = /dev/ttyprintk User messages via printk TTY device
|
||||||
64 = /dev/cua0 Callout device for ttyS0
|
64 = /dev/cua0 Callout device for ttyS0
|
||||||
...
|
...
|
||||||
255 = /dev/cua191 Callout device for ttyS191
|
255 = /dev/cua191 Callout device for ttyS191
|
||||||
|
|
|
@ -1075,6 +1075,7 @@ Table 1-11: Files in /proc/tty
|
||||||
drivers list of drivers and their usage
|
drivers list of drivers and their usage
|
||||||
ldiscs registered line disciplines
|
ldiscs registered line disciplines
|
||||||
driver/serial usage statistic and status of single tty lines
|
driver/serial usage statistic and status of single tty lines
|
||||||
|
consoles registered system console lines
|
||||||
..............................................................................
|
..............................................................................
|
||||||
|
|
||||||
To see which tty's are currently in use, you can simply look into the file
|
To see which tty's are currently in use, you can simply look into the file
|
||||||
|
@ -1093,6 +1094,37 @@ To see which tty's are currently in use, you can simply look into the file
|
||||||
/dev/tty /dev/tty 5 0 system:/dev/tty
|
/dev/tty /dev/tty 5 0 system:/dev/tty
|
||||||
unknown /dev/tty 4 1-63 console
|
unknown /dev/tty 4 1-63 console
|
||||||
|
|
||||||
|
To see which character device lines are currently used for the system console
|
||||||
|
/dev/console, you may simply look into the file /proc/tty/consoles:
|
||||||
|
|
||||||
|
> cat /proc/tty/consoles
|
||||||
|
tty0 -WU (ECp) 4:7
|
||||||
|
ttyS0 -W- (Ep) 4:64
|
||||||
|
|
||||||
|
The columns are:
|
||||||
|
|
||||||
|
device name of the device
|
||||||
|
operations R = can do read operations
|
||||||
|
W = can do write operations
|
||||||
|
U = can do unblank
|
||||||
|
flags E = it is enabled
|
||||||
|
C = it is prefered console
|
||||||
|
B = it is primary boot console
|
||||||
|
p = it is used for printk buffer
|
||||||
|
b = it is not a TTY but a Braille device
|
||||||
|
a = it is safe to use when cpu is offline
|
||||||
|
* = it is standard input of the reading process
|
||||||
|
major:minor major and minor number of the device separated by a colon
|
||||||
|
|
||||||
|
If the reading process holds /dev/console open at the regular standard input
|
||||||
|
stream the active device will be marked by an asterisk:
|
||||||
|
|
||||||
|
> cat /proc/tty/consoles < /dev/console
|
||||||
|
tty0 -WU (ECp*) 4:7
|
||||||
|
ttyS0 -W- (Ep) 4:64
|
||||||
|
> tty
|
||||||
|
/dev/pts/3
|
||||||
|
|
||||||
|
|
||||||
1.8 Miscellaneous kernel statistics in /proc/stat
|
1.8 Miscellaneous kernel statistics in /proc/stat
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -157,9 +157,11 @@ S: Maintained
|
||||||
F: drivers/net/r8169.c
|
F: drivers/net/r8169.c
|
||||||
|
|
||||||
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
||||||
|
M: Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
L: linux-serial@vger.kernel.org
|
L: linux-serial@vger.kernel.org
|
||||||
W: http://serial.sourceforge.net
|
W: http://serial.sourceforge.net
|
||||||
S: Orphan
|
S: Maintained
|
||||||
|
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
|
||||||
F: drivers/serial/8250*
|
F: drivers/serial/8250*
|
||||||
F: include/linux/serial_8250.h
|
F: include/linux/serial_8250.h
|
||||||
|
|
||||||
|
@ -3353,6 +3355,12 @@ F: fs/jbd*/
|
||||||
F: include/linux/ext*jbd*.h
|
F: include/linux/ext*jbd*.h
|
||||||
F: include/linux/jbd*.h
|
F: include/linux/jbd*.h
|
||||||
|
|
||||||
|
JSM Neo PCI based serial card
|
||||||
|
M: Breno Leitao <leitao@linux.vnet.ibm.com>
|
||||||
|
L: linux-serial@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/serial/jsm/
|
||||||
|
|
||||||
K8TEMP HARDWARE MONITORING DRIVER
|
K8TEMP HARDWARE MONITORING DRIVER
|
||||||
M: Rudolf Marek <r.marek@assembler.cz>
|
M: Rudolf Marek <r.marek@assembler.cz>
|
||||||
L: lm-sensors@lm-sensors.org
|
L: lm-sensors@lm-sensors.org
|
||||||
|
|
|
@ -1,89 +1,8 @@
|
||||||
#ifndef __ASM_ARM_IOCTLS_H
|
#ifndef __ASM_ARM_IOCTLS_H
|
||||||
#define __ASM_ARM_IOCTLS_H
|
#define __ASM_ARM_IOCTLS_H
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define TIOCGRS485 0x542E
|
|
||||||
#define TIOCSRS485 0x542F
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x545E
|
#define FIOQSIZE 0x545E
|
||||||
|
|
||||||
/* Used for packet mode */
|
#include <asm-generic/ioctls.h>
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,90 +1,6 @@
|
||||||
#ifndef __ASM_AVR32_IOCTLS_H
|
#ifndef __ASM_AVR32_IOCTLS_H
|
||||||
#define __ASM_AVR32_IOCTLS_H
|
#define __ASM_AVR32_IOCTLS_H
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
#include <asm-generic/ioctls.h>
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define TIOCGRS485 0x542E
|
|
||||||
#define TIOCSRS485 0x542F
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x5460
|
|
||||||
|
|
||||||
/* Used for packet mode */
|
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif /* __ASM_AVR32_IOCTLS_H */
|
#endif /* __ASM_AVR32_IOCTLS_H */
|
||||||
|
|
|
@ -1,93 +1,11 @@
|
||||||
#ifndef __ARCH_CRIS_IOCTLS_H__
|
#ifndef __ARCH_CRIS_IOCTLS_H__
|
||||||
#define __ARCH_CRIS_IOCTLS_H__
|
#define __ARCH_CRIS_IOCTLS_H__
|
||||||
|
|
||||||
/* verbatim copy of asm-i386/ioctls.h */
|
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x5460
|
|
||||||
|
|
||||||
#define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */
|
#define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */
|
||||||
#define TIOCSERWRRS485 0x5462 /* write rs-485 */
|
#define TIOCSERWRRS485 0x5462 /* write rs-485 */
|
||||||
#define TIOCSRS485 0x5463 /* enable rs-485 */
|
#define TIOCSRS485 0x5463 /* enable rs-485 */
|
||||||
#define TIOCGRS485 0x542E /* get rs-485 */
|
|
||||||
|
|
||||||
/* Used for packet mode */
|
#include <asm-generic/ioctls.h>
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,88 +1,10 @@
|
||||||
#ifndef __ASM_IOCTLS_H__
|
#ifndef __ASM_IOCTLS_H__
|
||||||
#define __ASM_IOCTLS_H__
|
#define __ASM_IOCTLS_H__
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
|
#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x545E
|
#define FIOQSIZE 0x545E
|
||||||
|
|
||||||
/* Used for packet mode */
|
#include <asm-generic/ioctls.h>
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif /* __ASM_IOCTLS_H__ */
|
#endif /* __ASM_IOCTLS_H__ */
|
||||||
|
|
||||||
|
|
|
@ -1,87 +1,8 @@
|
||||||
#ifndef __ARCH_H8300_IOCTLS_H__
|
#ifndef __ARCH_H8300_IOCTLS_H__
|
||||||
#define __ARCH_H8300_IOCTLS_H__
|
#define __ARCH_H8300_IOCTLS_H__
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x545E
|
#define FIOQSIZE 0x545E
|
||||||
|
|
||||||
/* Used for packet mode */
|
#include <asm-generic/ioctls.h>
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif /* __ARCH_H8300_IOCTLS_H__ */
|
#endif /* __ARCH_H8300_IOCTLS_H__ */
|
||||||
|
|
|
@ -395,7 +395,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
{
|
{
|
||||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||||
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
|
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
|
||||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
(cmd != TIOCMIWAIT)) {
|
||||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
|
printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
|
||||||
return 0;
|
return 0;
|
||||||
/*
|
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
|
||||||
* Return: write counters to the user passed counter struct
|
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
|
||||||
* RI where only 0->1 is counted.
|
|
||||||
*/
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case TIOCSERGWILD:
|
case TIOCSERGWILD:
|
||||||
case TIOCSERSWILD:
|
case TIOCSERSWILD:
|
||||||
/* "setserial -W" is called in Debian boot */
|
/* "setserial -W" is called in Debian boot */
|
||||||
|
|
|
@ -1,93 +1,6 @@
|
||||||
#ifndef _ASM_IA64_IOCTLS_H
|
#ifndef _ASM_IA64_IOCTLS_H
|
||||||
#define _ASM_IA64_IOCTLS_H
|
#define _ASM_IA64_IOCTLS_H
|
||||||
|
|
||||||
/*
|
#include <asm-generic/ioctls.h>
|
||||||
* Based on <asm-i386/ioctls.h>
|
|
||||||
*
|
|
||||||
* Modified 1998, 1999, 2002
|
|
||||||
* David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x5460
|
|
||||||
|
|
||||||
/* Used for packet mode */
|
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif /* _ASM_IA64_IOCTLS_H */
|
#endif /* _ASM_IA64_IOCTLS_H */
|
||||||
|
|
|
@ -1,87 +1,6 @@
|
||||||
#ifndef __ARCH_M32R_IOCTLS_H__
|
#ifndef __ARCH_M32R_IOCTLS_H__
|
||||||
#define __ARCH_M32R_IOCTLS_H__
|
#define __ARCH_M32R_IOCTLS_H__
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
#include <asm-generic/ioctls.h>
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402 /* Clashes with SNDCTL_TMR_START sound ioctl */
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x5460
|
|
||||||
|
|
||||||
/* Used for packet mode */
|
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif /* __ARCH_M32R_IOCTLS_H__ */
|
#endif /* __ARCH_M32R_IOCTLS_H__ */
|
||||||
|
|
|
@ -24,6 +24,33 @@
|
||||||
|
|
||||||
#include <prom.h>
|
#include <prom.h>
|
||||||
|
|
||||||
|
static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
|
||||||
|
unsigned int old_state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case 0:
|
||||||
|
if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
|
||||||
|
/* power-on sequence as suggested in the databooks */
|
||||||
|
__raw_writel(0, port->membase + UART_MOD_CNTRL);
|
||||||
|
wmb();
|
||||||
|
__raw_writel(1, port->membase + UART_MOD_CNTRL);
|
||||||
|
wmb();
|
||||||
|
}
|
||||||
|
__raw_writel(3, port->membase + UART_MOD_CNTRL); /* full on */
|
||||||
|
wmb();
|
||||||
|
serial8250_do_pm(port, state, old_state);
|
||||||
|
break;
|
||||||
|
case 3: /* power off */
|
||||||
|
serial8250_do_pm(port, state, old_state);
|
||||||
|
__raw_writel(0, port->membase + UART_MOD_CNTRL);
|
||||||
|
wmb();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
serial8250_do_pm(port, state, old_state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define PORT(_base, _irq) \
|
#define PORT(_base, _irq) \
|
||||||
{ \
|
{ \
|
||||||
.mapbase = _base, \
|
.mapbase = _base, \
|
||||||
|
@ -33,6 +60,7 @@
|
||||||
.flags = UPF_SKIP_TEST | UPF_IOREMAP | \
|
.flags = UPF_SKIP_TEST | UPF_IOREMAP | \
|
||||||
UPF_FIXED_TYPE, \
|
UPF_FIXED_TYPE, \
|
||||||
.type = PORT_16550A, \
|
.type = PORT_16550A, \
|
||||||
|
.pm = alchemy_8250_pm, \
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct plat_serial8250_port au1x00_uart_data[] = {
|
static struct plat_serial8250_port au1x00_uart_data[] = {
|
||||||
|
|
|
@ -49,11 +49,6 @@
|
||||||
* We only have to save/restore registers that aren't otherwise
|
* We only have to save/restore registers that aren't otherwise
|
||||||
* done as part of a driver pm_* function.
|
* done as part of a driver pm_* function.
|
||||||
*/
|
*/
|
||||||
static unsigned int sleep_uart0_inten;
|
|
||||||
static unsigned int sleep_uart0_fifoctl;
|
|
||||||
static unsigned int sleep_uart0_linectl;
|
|
||||||
static unsigned int sleep_uart0_clkdiv;
|
|
||||||
static unsigned int sleep_uart0_enable;
|
|
||||||
static unsigned int sleep_usb[2];
|
static unsigned int sleep_usb[2];
|
||||||
static unsigned int sleep_sys_clocks[5];
|
static unsigned int sleep_sys_clocks[5];
|
||||||
static unsigned int sleep_sys_pinfunc;
|
static unsigned int sleep_sys_pinfunc;
|
||||||
|
@ -62,22 +57,6 @@ static unsigned int sleep_static_memctlr[4][3];
|
||||||
|
|
||||||
static void save_core_regs(void)
|
static void save_core_regs(void)
|
||||||
{
|
{
|
||||||
extern void save_au1xxx_intctl(void);
|
|
||||||
extern void pm_eth0_shutdown(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Do the serial ports.....these really should be a pm_*
|
|
||||||
* registered function by the driver......but of course the
|
|
||||||
* standard serial driver doesn't understand our Au1xxx
|
|
||||||
* unique registers.
|
|
||||||
*/
|
|
||||||
sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER);
|
|
||||||
sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR);
|
|
||||||
sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
|
|
||||||
sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
|
|
||||||
sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
|
|
||||||
au_sync();
|
|
||||||
|
|
||||||
#ifndef CONFIG_SOC_AU1200
|
#ifndef CONFIG_SOC_AU1200
|
||||||
/* Shutdown USB host/device. */
|
/* Shutdown USB host/device. */
|
||||||
sleep_usb[0] = au_readl(USB_HOST_CONFIG);
|
sleep_usb[0] = au_readl(USB_HOST_CONFIG);
|
||||||
|
@ -175,20 +154,6 @@ static void restore_core_regs(void)
|
||||||
au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
|
au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
|
||||||
au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
|
au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
|
||||||
au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
|
au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable the UART if it was enabled before sleep.
|
|
||||||
* I guess I should define module control bits........
|
|
||||||
*/
|
|
||||||
if (sleep_uart0_enable & 0x02) {
|
|
||||||
au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync();
|
|
||||||
au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync();
|
|
||||||
au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync();
|
|
||||||
au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync();
|
|
||||||
au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync();
|
|
||||||
au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync();
|
|
||||||
au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void au_sleep(void)
|
void au_sleep(void)
|
||||||
|
|
|
@ -1,88 +1,6 @@
|
||||||
#ifndef _ASM_IOCTLS_H
|
#ifndef _ASM_IOCTLS_H
|
||||||
#define _ASM_IOCTLS_H
|
#define _ASM_IOCTLS_H
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
#include <asm-generic/ioctls.h>
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
/* #define TIOCTTYGSTRUCT 0x5426 - Former debugging-only ioctl */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T', 0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T', 0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number
|
|
||||||
* (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x5460
|
|
||||||
|
|
||||||
/* Used for packet mode */
|
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif /* _ASM_IOCTLS_H */
|
#endif /* _ASM_IOCTLS_H */
|
||||||
|
|
|
@ -1,94 +1,8 @@
|
||||||
/*
|
|
||||||
* include/asm-s390/ioctls.h
|
|
||||||
*
|
|
||||||
* S390 version
|
|
||||||
*
|
|
||||||
* Derived from "include/asm-i386/ioctls.h"
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __ARCH_S390_IOCTLS_H__
|
#ifndef __ARCH_S390_IOCTLS_H__
|
||||||
#define __ARCH_S390_IOCTLS_H__
|
#define __ARCH_S390_IOCTLS_H__
|
||||||
|
|
||||||
#include <asm/ioctl.h>
|
|
||||||
|
|
||||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
|
||||||
|
|
||||||
#define TCGETS 0x5401
|
|
||||||
#define TCSETS 0x5402
|
|
||||||
#define TCSETSW 0x5403
|
|
||||||
#define TCSETSF 0x5404
|
|
||||||
#define TCGETA 0x5405
|
|
||||||
#define TCSETA 0x5406
|
|
||||||
#define TCSETAW 0x5407
|
|
||||||
#define TCSETAF 0x5408
|
|
||||||
#define TCSBRK 0x5409
|
|
||||||
#define TCXONC 0x540A
|
|
||||||
#define TCFLSH 0x540B
|
|
||||||
#define TIOCEXCL 0x540C
|
|
||||||
#define TIOCNXCL 0x540D
|
|
||||||
#define TIOCSCTTY 0x540E
|
|
||||||
#define TIOCGPGRP 0x540F
|
|
||||||
#define TIOCSPGRP 0x5410
|
|
||||||
#define TIOCOUTQ 0x5411
|
|
||||||
#define TIOCSTI 0x5412
|
|
||||||
#define TIOCGWINSZ 0x5413
|
|
||||||
#define TIOCSWINSZ 0x5414
|
|
||||||
#define TIOCMGET 0x5415
|
|
||||||
#define TIOCMBIS 0x5416
|
|
||||||
#define TIOCMBIC 0x5417
|
|
||||||
#define TIOCMSET 0x5418
|
|
||||||
#define TIOCGSOFTCAR 0x5419
|
|
||||||
#define TIOCSSOFTCAR 0x541A
|
|
||||||
#define FIONREAD 0x541B
|
|
||||||
#define TIOCINQ FIONREAD
|
|
||||||
#define TIOCLINUX 0x541C
|
|
||||||
#define TIOCCONS 0x541D
|
|
||||||
#define TIOCGSERIAL 0x541E
|
|
||||||
#define TIOCSSERIAL 0x541F
|
|
||||||
#define TIOCPKT 0x5420
|
|
||||||
#define FIONBIO 0x5421
|
|
||||||
#define TIOCNOTTY 0x5422
|
|
||||||
#define TIOCSETD 0x5423
|
|
||||||
#define TIOCGETD 0x5424
|
|
||||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
|
||||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
|
||||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
|
||||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
|
||||||
#define TCGETS2 _IOR('T',0x2A, struct termios2)
|
|
||||||
#define TCSETS2 _IOW('T',0x2B, struct termios2)
|
|
||||||
#define TCSETSW2 _IOW('T',0x2C, struct termios2)
|
|
||||||
#define TCSETSF2 _IOW('T',0x2D, struct termios2)
|
|
||||||
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
|
||||||
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
|
|
||||||
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
|
|
||||||
|
|
||||||
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
|
|
||||||
#define FIOCLEX 0x5451
|
|
||||||
#define FIOASYNC 0x5452
|
|
||||||
#define TIOCSERCONFIG 0x5453
|
|
||||||
#define TIOCSERGWILD 0x5454
|
|
||||||
#define TIOCSERSWILD 0x5455
|
|
||||||
#define TIOCGLCKTRMIOS 0x5456
|
|
||||||
#define TIOCSLCKTRMIOS 0x5457
|
|
||||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
|
||||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
|
||||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
|
||||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
|
||||||
|
|
||||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
|
||||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
|
||||||
#define FIOQSIZE 0x545E
|
#define FIOQSIZE 0x545E
|
||||||
|
|
||||||
/* Used for packet mode */
|
#include <asm-generic/ioctls.h>
|
||||||
#define TIOCPKT_DATA 0
|
|
||||||
#define TIOCPKT_FLUSHREAD 1
|
|
||||||
#define TIOCPKT_FLUSHWRITE 2
|
|
||||||
#define TIOCPKT_STOP 4
|
|
||||||
#define TIOCPKT_START 8
|
|
||||||
#define TIOCPKT_NOSTOP 16
|
|
||||||
#define TIOCPKT_DOSTOP 32
|
|
||||||
#define TIOCPKT_IOCTL 64
|
|
||||||
|
|
||||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -493,6 +493,21 @@ config LEGACY_PTY_COUNT
|
||||||
When not in use, each legacy PTY occupies 12 bytes on 32-bit
|
When not in use, each legacy PTY occupies 12 bytes on 32-bit
|
||||||
architectures and 24 bytes on 64-bit architectures.
|
architectures and 24 bytes on 64-bit architectures.
|
||||||
|
|
||||||
|
config TTY_PRINTK
|
||||||
|
bool "TTY driver to output user messages via printk"
|
||||||
|
depends on EMBEDDED
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
If you say Y here, the support for writing user messages (i.e.
|
||||||
|
console messages) via printk is available.
|
||||||
|
|
||||||
|
The feature is useful to inline user messages with kernel
|
||||||
|
messages.
|
||||||
|
In order to use this feature, you should output user messages
|
||||||
|
to /dev/ttyprintk or redirect console to this TTY.
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
config BRIQ_PANEL
|
config BRIQ_PANEL
|
||||||
tristate 'Total Impact briQ front panel driver'
|
tristate 'Total Impact briQ front panel driver'
|
||||||
depends on PPC_CHRP
|
depends on PPC_CHRP
|
||||||
|
|
|
@ -12,6 +12,7 @@ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o t
|
||||||
obj-y += tty_mutex.o
|
obj-y += tty_mutex.o
|
||||||
obj-$(CONFIG_LEGACY_PTYS) += pty.o
|
obj-$(CONFIG_LEGACY_PTYS) += pty.o
|
||||||
obj-$(CONFIG_UNIX98_PTYS) += pty.o
|
obj-$(CONFIG_UNIX98_PTYS) += pty.o
|
||||||
|
obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
|
||||||
obj-y += misc.o
|
obj-y += misc.o
|
||||||
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
|
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
|
||||||
obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o
|
obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o
|
||||||
|
|
|
@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
||||||
|
* Return: write counters to the user passed counter struct
|
||||||
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
|
* RI where only 0->1 is counted.
|
||||||
|
*/
|
||||||
|
static int rs_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct async_struct *info = tty->driver_data;
|
||||||
|
struct async_icount cnow;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
cnow = info->state->icount;
|
||||||
|
local_irq_restore(flags);
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
|
@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
|
||||||
/*
|
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
|
||||||
* Return: write counters to the user passed counter struct
|
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
|
||||||
* RI where only 0->1 is counted.
|
|
||||||
*/
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
local_irq_save(flags);
|
|
||||||
cnow = info->state->icount;
|
|
||||||
local_irq_restore(flags);
|
|
||||||
icount.cts = cnow.cts;
|
|
||||||
icount.dsr = cnow.dsr;
|
|
||||||
icount.rng = cnow.rng;
|
|
||||||
icount.dcd = cnow.dcd;
|
|
||||||
icount.rx = cnow.rx;
|
|
||||||
icount.tx = cnow.tx;
|
|
||||||
icount.frame = cnow.frame;
|
|
||||||
icount.overrun = cnow.overrun;
|
|
||||||
icount.parity = cnow.parity;
|
|
||||||
icount.brk = cnow.brk;
|
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
|
||||||
|
|
||||||
if (copy_to_user(argp, &icount, sizeof(icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
case TIOCSERGWILD:
|
case TIOCSERGWILD:
|
||||||
case TIOCSERSWILD:
|
case TIOCSERSWILD:
|
||||||
/* "setserial -W" is called in Debian boot */
|
/* "setserial -W" is called in Debian boot */
|
||||||
|
@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
|
||||||
.wait_until_sent = rs_wait_until_sent,
|
.wait_until_sent = rs_wait_until_sent,
|
||||||
.tiocmget = rs_tiocmget,
|
.tiocmget = rs_tiocmget,
|
||||||
.tiocmset = rs_tiocmset,
|
.tiocmset = rs_tiocmset,
|
||||||
|
.get_icount = rs_get_icount,
|
||||||
.proc_fops = &rs_proc_fops,
|
.proc_fops = &rs_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
* RI where only 0->1 is counted.
|
* RI where only 0->1 is counted.
|
||||||
*/
|
*/
|
||||||
case TIOCGICOUNT: {
|
|
||||||
struct serial_icounter_struct sic = { };
|
|
||||||
|
|
||||||
spin_lock_irqsave(&info->card->card_lock, flags);
|
|
||||||
cnow = info->icount;
|
|
||||||
spin_unlock_irqrestore(&info->card->card_lock, flags);
|
|
||||||
|
|
||||||
sic.cts = cnow.cts;
|
|
||||||
sic.dsr = cnow.dsr;
|
|
||||||
sic.rng = cnow.rng;
|
|
||||||
sic.dcd = cnow.dcd;
|
|
||||||
sic.rx = cnow.rx;
|
|
||||||
sic.tx = cnow.tx;
|
|
||||||
sic.frame = cnow.frame;
|
|
||||||
sic.overrun = cnow.overrun;
|
|
||||||
sic.parity = cnow.parity;
|
|
||||||
sic.brk = cnow.brk;
|
|
||||||
sic.buf_overrun = cnow.buf_overrun;
|
|
||||||
|
|
||||||
if (copy_to_user(argp, &sic, sizeof(sic)))
|
|
||||||
ret_val = -EFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
ret_val = -ENOIOCTLCMD;
|
ret_val = -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return ret_val;
|
return ret_val;
|
||||||
} /* cy_ioctl */
|
} /* cy_ioctl */
|
||||||
|
|
||||||
|
static int cy_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *sic)
|
||||||
|
{
|
||||||
|
struct cyclades_port *info = tty->driver_data;
|
||||||
|
struct cyclades_icount cnow; /* Used to snapshot */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&info->card->card_lock, flags);
|
||||||
|
cnow = info->icount;
|
||||||
|
spin_unlock_irqrestore(&info->card->card_lock, flags);
|
||||||
|
|
||||||
|
sic->cts = cnow.cts;
|
||||||
|
sic->dsr = cnow.dsr;
|
||||||
|
sic->rng = cnow.rng;
|
||||||
|
sic->dcd = cnow.dcd;
|
||||||
|
sic->rx = cnow.rx;
|
||||||
|
sic->tx = cnow.tx;
|
||||||
|
sic->frame = cnow.frame;
|
||||||
|
sic->overrun = cnow.overrun;
|
||||||
|
sic->parity = cnow.parity;
|
||||||
|
sic->brk = cnow.brk;
|
||||||
|
sic->buf_overrun = cnow.buf_overrun;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine allows the tty driver to be notified when
|
* This routine allows the tty driver to be notified when
|
||||||
* device's termios settings have changed. Note that a
|
* device's termios settings have changed. Note that a
|
||||||
|
@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
|
||||||
.wait_until_sent = cy_wait_until_sent,
|
.wait_until_sent = cy_wait_until_sent,
|
||||||
.tiocmget = cy_tiocmget,
|
.tiocmget = cy_tiocmget,
|
||||||
.tiocmset = cy_tiocmset,
|
.tiocmset = cy_tiocmset,
|
||||||
|
.get_icount = cy_get_icount,
|
||||||
.proc_fops = &cyclades_proc_fops,
|
.proc_fops = &cyclades_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,8 @@ static void ip2_hangup(PTTY);
|
||||||
static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
|
static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
|
||||||
static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
|
static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
|
static int ip2_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount);
|
||||||
|
|
||||||
static void set_irq(int, int);
|
static void set_irq(int, int);
|
||||||
static void ip2_interrupt_bh(struct work_struct *work);
|
static void ip2_interrupt_bh(struct work_struct *work);
|
||||||
|
@ -456,6 +458,7 @@ static const struct tty_operations ip2_ops = {
|
||||||
.hangup = ip2_hangup,
|
.hangup = ip2_hangup,
|
||||||
.tiocmget = ip2_tiocmget,
|
.tiocmget = ip2_tiocmget,
|
||||||
.tiocmset = ip2_tiocmset,
|
.tiocmset = ip2_tiocmset,
|
||||||
|
.get_icount = ip2_get_icount,
|
||||||
.proc_fops = &ip2_proc_fops,
|
.proc_fops = &ip2_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2130,7 +2133,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
|
||||||
i2ChanStrPtr pCh = DevTable[tty->index];
|
i2ChanStrPtr pCh = DevTable[tty->index];
|
||||||
i2eBordStrPtr pB;
|
i2eBordStrPtr pB;
|
||||||
struct async_icount cprev, cnow; /* kernel counter temps */
|
struct async_icount cprev, cnow; /* kernel counter temps */
|
||||||
struct serial_icounter_struct __user *p_cuser;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
|
@ -2298,34 +2300,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
|
||||||
return rc;
|
return rc;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
|
||||||
* Return: write counters to the user passed counter struct
|
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for RI where
|
|
||||||
* only 0->1 is counted. The controller is quite capable of counting
|
|
||||||
* both, but this done to preserve compatibility with the standard
|
|
||||||
* serial driver.
|
|
||||||
*/
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
|
|
||||||
|
|
||||||
write_lock_irqsave(&pB->read_fifo_spinlock, flags);
|
|
||||||
cnow = pCh->icount;
|
|
||||||
write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
|
|
||||||
p_cuser = argp;
|
|
||||||
rc = put_user(cnow.cts, &p_cuser->cts);
|
|
||||||
rc = put_user(cnow.dsr, &p_cuser->dsr);
|
|
||||||
rc = put_user(cnow.rng, &p_cuser->rng);
|
|
||||||
rc = put_user(cnow.dcd, &p_cuser->dcd);
|
|
||||||
rc = put_user(cnow.rx, &p_cuser->rx);
|
|
||||||
rc = put_user(cnow.tx, &p_cuser->tx);
|
|
||||||
rc = put_user(cnow.frame, &p_cuser->frame);
|
|
||||||
rc = put_user(cnow.overrun, &p_cuser->overrun);
|
|
||||||
rc = put_user(cnow.parity, &p_cuser->parity);
|
|
||||||
rc = put_user(cnow.brk, &p_cuser->brk);
|
|
||||||
rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The rest are not supported by this driver. By returning -ENOIOCTLCMD they
|
* The rest are not supported by this driver. By returning -ENOIOCTLCMD they
|
||||||
* will be passed to the line discipline for it to handle.
|
* will be passed to the line discipline for it to handle.
|
||||||
|
@ -2350,6 +2324,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ip2_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
i2ChanStrPtr pCh = DevTable[tty->index];
|
||||||
|
i2eBordStrPtr pB;
|
||||||
|
struct async_icount cnow; /* kernel counter temp */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if ( pCh == NULL )
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
pB = pCh->pMyBord;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
||||||
|
* Return: write counters to the user passed counter struct
|
||||||
|
* NB: both 1->0 and 0->1 transitions are counted except for RI where
|
||||||
|
* only 0->1 is counted. The controller is quite capable of counting
|
||||||
|
* both, but this done to preserve compatibility with the standard
|
||||||
|
* serial driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
write_lock_irqsave(&pB->read_fifo_spinlock, flags);
|
||||||
|
cnow = pCh->icount;
|
||||||
|
write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Function: GetSerialInfo() */
|
/* Function: GetSerialInfo() */
|
||||||
/* Parameters: Pointer to channel structure */
|
/* Parameters: Pointer to channel structure */
|
||||||
|
|
|
@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
|
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
|
||||||
test_bit(TTY_IO_ERROR, &tty->flags))
|
test_bit(TTY_IO_ERROR, &tty->flags))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
|
||||||
return wait_event_interruptible(info->port.delta_msr_wait,
|
return wait_event_interruptible(info->port.delta_msr_wait,
|
||||||
mxser_cflags_changed(info, arg, &cnow));
|
mxser_cflags_changed(info, arg, &cnow));
|
||||||
/*
|
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
|
||||||
* Return: write counters to the user passed counter struct
|
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
|
||||||
* RI where only 0->1 is counted.
|
|
||||||
*/
|
|
||||||
case TIOCGICOUNT: {
|
|
||||||
struct serial_icounter_struct icnt = { 0 };
|
|
||||||
spin_lock_irqsave(&info->slock, flags);
|
|
||||||
cnow = info->icount;
|
|
||||||
spin_unlock_irqrestore(&info->slock, flags);
|
|
||||||
|
|
||||||
icnt.frame = cnow.frame;
|
|
||||||
icnt.brk = cnow.brk;
|
|
||||||
icnt.overrun = cnow.overrun;
|
|
||||||
icnt.buf_overrun = cnow.buf_overrun;
|
|
||||||
icnt.parity = cnow.parity;
|
|
||||||
icnt.rx = cnow.rx;
|
|
||||||
icnt.tx = cnow.tx;
|
|
||||||
icnt.cts = cnow.cts;
|
|
||||||
icnt.dsr = cnow.dsr;
|
|
||||||
icnt.rng = cnow.rng;
|
|
||||||
icnt.dcd = cnow.dcd;
|
|
||||||
|
|
||||||
return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
|
|
||||||
}
|
|
||||||
case MOXA_HighSpeedOn:
|
case MOXA_HighSpeedOn:
|
||||||
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
|
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
|
||||||
case MOXA_SDS_RSTICOUNTER:
|
case MOXA_SDS_RSTICOUNTER:
|
||||||
|
@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
||||||
|
* Return: write counters to the user passed counter struct
|
||||||
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
|
* RI where only 0->1 is counted.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int mxser_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct mxser_port *info = tty->driver_data;
|
||||||
|
struct async_icount cnow;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&info->slock, flags);
|
||||||
|
cnow = info->icount;
|
||||||
|
spin_unlock_irqrestore(&info->slock, flags);
|
||||||
|
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void mxser_stoprx(struct tty_struct *tty)
|
static void mxser_stoprx(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct mxser_port *info = tty->driver_data;
|
struct mxser_port *info = tty->driver_data;
|
||||||
|
@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
|
||||||
.wait_until_sent = mxser_wait_until_sent,
|
.wait_until_sent = mxser_wait_until_sent,
|
||||||
.tiocmget = mxser_tiocmget,
|
.tiocmget = mxser_tiocmget,
|
||||||
.tiocmset = mxser_tiocmset,
|
.tiocmset = mxser_tiocmset,
|
||||||
|
.get_icount = mxser_get_icount,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tty_port_operations mxser_port_ops = {
|
struct tty_port_operations mxser_port_ops = {
|
||||||
|
@ -2339,20 +2347,11 @@ struct tty_port_operations mxser_port_ops = {
|
||||||
* The MOXA Smartio/Industio serial driver boot-time initialization code!
|
* The MOXA Smartio/Industio serial driver boot-time initialization code!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
|
static void mxser_release_ISA_res(struct mxser_board *brd)
|
||||||
unsigned int irq)
|
|
||||||
{
|
{
|
||||||
if (irq)
|
free_irq(brd->irq, brd);
|
||||||
free_irq(brd->irq, brd);
|
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
|
||||||
if (pdev != NULL) { /* PCI */
|
release_region(brd->vector, 1);
|
||||||
#ifdef CONFIG_PCI
|
|
||||||
pci_release_region(pdev, 2);
|
|
||||||
pci_release_region(pdev, 3);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
|
|
||||||
release_region(brd->vector, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit mxser_initbrd(struct mxser_board *brd,
|
static int __devinit mxser_initbrd(struct mxser_board *brd,
|
||||||
|
@ -2397,13 +2396,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
|
||||||
|
|
||||||
retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
|
retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
|
||||||
brd);
|
brd);
|
||||||
if (retval) {
|
if (retval)
|
||||||
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
|
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
|
||||||
"conflict with another device.\n",
|
"conflict with another device.\n",
|
||||||
brd->info->name, brd->irq);
|
brd->info->name, brd->irq);
|
||||||
/* We hold resources, we need to release them. */
|
|
||||||
mxser_release_res(brd, pdev, 0);
|
|
||||||
}
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
||||||
ioaddress = pci_resource_start(pdev, 2);
|
ioaddress = pci_resource_start(pdev, 2);
|
||||||
retval = pci_request_region(pdev, 2, "mxser(IO)");
|
retval = pci_request_region(pdev, 2, "mxser(IO)");
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err;
|
goto err_dis;
|
||||||
|
|
||||||
brd->info = &mxser_cards[ent->driver_data];
|
brd->info = &mxser_cards[ent->driver_data];
|
||||||
for (i = 0; i < brd->info->nports; i++)
|
for (i = 0; i < brd->info->nports; i++)
|
||||||
|
@ -2565,7 +2562,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
||||||
ioaddress = pci_resource_start(pdev, 3);
|
ioaddress = pci_resource_start(pdev, 3);
|
||||||
retval = pci_request_region(pdev, 3, "mxser(vector)");
|
retval = pci_request_region(pdev, 3, "mxser(vector)");
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err_relio;
|
goto err_zero;
|
||||||
brd->vector = ioaddress;
|
brd->vector = ioaddress;
|
||||||
|
|
||||||
/* irq */
|
/* irq */
|
||||||
|
@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
||||||
/* mxser_initbrd will hook ISR. */
|
/* mxser_initbrd will hook ISR. */
|
||||||
retval = mxser_initbrd(brd, pdev);
|
retval = mxser_initbrd(brd, pdev);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto err_null;
|
goto err_rel3;
|
||||||
|
|
||||||
for (i = 0; i < brd->info->nports; i++)
|
for (i = 0; i < brd->info->nports; i++)
|
||||||
tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
|
tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
|
||||||
|
@ -2616,10 +2613,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
||||||
pci_set_drvdata(pdev, brd);
|
pci_set_drvdata(pdev, brd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err_relio:
|
err_rel3:
|
||||||
pci_release_region(pdev, 2);
|
pci_release_region(pdev, 3);
|
||||||
err_null:
|
err_zero:
|
||||||
brd->info = NULL;
|
brd->info = NULL;
|
||||||
|
pci_release_region(pdev, 2);
|
||||||
|
err_dis:
|
||||||
|
pci_disable_device(pdev);
|
||||||
err:
|
err:
|
||||||
return retval;
|
return retval;
|
||||||
#else
|
#else
|
||||||
|
@ -2629,14 +2629,19 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
||||||
|
|
||||||
static void __devexit mxser_remove(struct pci_dev *pdev)
|
static void __devexit mxser_remove(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
struct mxser_board *brd = pci_get_drvdata(pdev);
|
struct mxser_board *brd = pci_get_drvdata(pdev);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < brd->info->nports; i++)
|
for (i = 0; i < brd->info->nports; i++)
|
||||||
tty_unregister_device(mxvar_sdriver, brd->idx + i);
|
tty_unregister_device(mxvar_sdriver, brd->idx + i);
|
||||||
|
|
||||||
mxser_release_res(brd, pdev, 1);
|
free_irq(pdev->irq, brd);
|
||||||
|
pci_release_region(pdev, 2);
|
||||||
|
pci_release_region(pdev, 3);
|
||||||
|
pci_disable_device(pdev);
|
||||||
brd->info = NULL;
|
brd->info = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pci_driver mxser_driver = {
|
static struct pci_driver mxser_driver = {
|
||||||
|
@ -2741,7 +2746,7 @@ static void __exit mxser_module_exit(void)
|
||||||
|
|
||||||
for (i = 0; i < MXSER_BOARDS; i++)
|
for (i = 0; i < MXSER_BOARDS; i++)
|
||||||
if (mxser_boards[i].info != NULL)
|
if (mxser_boards[i].info != NULL)
|
||||||
mxser_release_res(&mxser_boards[i], NULL, 1);
|
mxser_release_ISA_res(&mxser_boards[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(mxser_module_init);
|
module_init(mxser_module_init);
|
||||||
|
|
|
@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
|
static int ntty_tiocgicount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
{
|
{
|
||||||
|
struct port *port = tty->driver_data;
|
||||||
const struct async_icount cnow = port->tty_icount;
|
const struct async_icount cnow = port->tty_icount;
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
|
|
||||||
icount.cts = cnow.cts;
|
icount->cts = cnow.cts;
|
||||||
icount.dsr = cnow.dsr;
|
icount->dsr = cnow.dsr;
|
||||||
icount.rng = cnow.rng;
|
icount->rng = cnow.rng;
|
||||||
icount.dcd = cnow.dcd;
|
icount->dcd = cnow.dcd;
|
||||||
icount.rx = cnow.rx;
|
icount->rx = cnow.rx;
|
||||||
icount.tx = cnow.tx;
|
icount->tx = cnow.tx;
|
||||||
icount.frame = cnow.frame;
|
icount->frame = cnow.frame;
|
||||||
icount.overrun = cnow.overrun;
|
icount->overrun = cnow.overrun;
|
||||||
icount.parity = cnow.parity;
|
icount->parity = cnow.parity;
|
||||||
icount.brk = cnow.brk;
|
icount->brk = cnow.brk;
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
return 0;
|
||||||
return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ntty_ioctl(struct tty_struct *tty, struct file *file,
|
static int ntty_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
rval = wait_event_interruptible(port->tty_wait,
|
rval = wait_event_interruptible(port->tty_wait,
|
||||||
ntty_cflags_changed(port, arg, &cprev));
|
ntty_cflags_changed(port, arg, &cprev));
|
||||||
break;
|
break;
|
||||||
} case TIOCGICOUNT:
|
}
|
||||||
rval = ntty_ioctl_tiocgicount(port, argp);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
DBG1("ERR: 0x%08X, %d", cmd, cmd);
|
DBG1("ERR: 0x%08X, %d", cmd, cmd);
|
||||||
break;
|
break;
|
||||||
|
@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
|
||||||
.chars_in_buffer = ntty_chars_in_buffer,
|
.chars_in_buffer = ntty_chars_in_buffer,
|
||||||
.tiocmget = ntty_tiocmget,
|
.tiocmget = ntty_tiocmget,
|
||||||
.tiocmset = ntty_tiocmset,
|
.tiocmset = ntty_tiocmset,
|
||||||
|
.get_icount = ntty_tiocgicount,
|
||||||
.install = ntty_install,
|
.install = ntty_install,
|
||||||
.cleanup = ntty_cleanup,
|
.cleanup = ntty_cleanup,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2191,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mgslpc_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
|
||||||
|
struct mgsl_icount cnow; /* kernel counter temps */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
|
cnow = info->icount;
|
||||||
|
spin_unlock_irqrestore(&info->lock,flags);
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Service an IOCTL request
|
/* Service an IOCTL request
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
|
@ -2206,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
|
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
|
||||||
int error;
|
|
||||||
struct mgsl_icount cnow; /* kernel counter temps */
|
|
||||||
struct serial_icounter_struct __user *p_cuser; /* user space */
|
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||||
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
|
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
|
||||||
|
@ -2220,7 +2242,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
(cmd != TIOCMIWAIT)) {
|
||||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -2250,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
return wait_events(info, argp);
|
return wait_events(info, argp);
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
return modem_input_wait(info,(int)arg);
|
return modem_input_wait(info,(int)arg);
|
||||||
case TIOCGICOUNT:
|
|
||||||
spin_lock_irqsave(&info->lock,flags);
|
|
||||||
cnow = info->icount;
|
|
||||||
spin_unlock_irqrestore(&info->lock,flags);
|
|
||||||
p_cuser = argp;
|
|
||||||
PUT_USER(error,cnow.cts, &p_cuser->cts);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.rng, &p_cuser->rng);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.dcd, &p_cuser->dcd);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.rx, &p_cuser->rx);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.tx, &p_cuser->tx);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.frame, &p_cuser->frame);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.overrun, &p_cuser->overrun);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.parity, &p_cuser->parity);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.brk, &p_cuser->brk);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
|
|
||||||
if (error) return error;
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
|
|
@ -676,7 +676,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
||||||
|
|
||||||
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
||||||
|
|
||||||
tty_add_file(tty, filp);
|
retval = tty_add_file(tty, filp);
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
|
||||||
retval = devpts_pty_new(inode, tty->link);
|
retval = devpts_pty_new(inode, tty->link);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
|
|
@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
|
||||||
|
|
||||||
} /* end of mgsl_break() */
|
} /* end of mgsl_break() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
||||||
|
* Return: write counters to the user passed counter struct
|
||||||
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
|
* RI where only 0->1 is counted.
|
||||||
|
*/
|
||||||
|
static int msgl_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct mgsl_struct * info = tty->driver_data;
|
||||||
|
struct mgsl_icount cnow; /* kernel counter temps */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&info->irq_spinlock,flags);
|
||||||
|
cnow = info->icount;
|
||||||
|
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* mgsl_ioctl() Service an IOCTL request
|
/* mgsl_ioctl() Service an IOCTL request
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
|
@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
(cmd != TIOCMIWAIT)) {
|
||||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
|
|
||||||
static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
|
static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
struct mgsl_icount cnow; /* kernel counter temps */
|
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
struct serial_icounter_struct __user *p_cuser; /* user space */
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case MGSL_IOCGPARAMS:
|
case MGSL_IOCGPARAMS:
|
||||||
|
@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
return modem_input_wait(info,(int)arg);
|
return modem_input_wait(info,(int)arg);
|
||||||
|
|
||||||
/*
|
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
|
||||||
* Return: write counters to the user passed counter struct
|
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
|
||||||
* RI where only 0->1 is counted.
|
|
||||||
*/
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
spin_lock_irqsave(&info->irq_spinlock,flags);
|
|
||||||
cnow = info->icount;
|
|
||||||
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
|
||||||
p_cuser = argp;
|
|
||||||
PUT_USER(error,cnow.cts, &p_cuser->cts);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.rng, &p_cuser->rng);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.dcd, &p_cuser->dcd);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.rx, &p_cuser->rx);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.tx, &p_cuser->tx);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.frame, &p_cuser->frame);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.overrun, &p_cuser->overrun);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.parity, &p_cuser->parity);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.brk, &p_cuser->brk);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
|
|
||||||
if (error) return error;
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
|
||||||
.hangup = mgsl_hangup,
|
.hangup = mgsl_hangup,
|
||||||
.tiocmget = tiocmget,
|
.tiocmget = tiocmget,
|
||||||
.tiocmset = tiocmset,
|
.tiocmset = tiocmset,
|
||||||
|
.get_icount = msgl_get_icount,
|
||||||
.proc_fops = &mgsl_proc_fops,
|
.proc_fops = &mgsl_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct slgt_info *info = tty->driver_data;
|
struct slgt_info *info = tty->driver_data;
|
||||||
struct mgsl_icount cnow; /* kernel counter temps */
|
|
||||||
struct serial_icounter_struct __user *p_cuser; /* user space */
|
|
||||||
unsigned long flags;
|
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
|
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
|
||||||
|
|
||||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
(cmd != TIOCMIWAIT)) {
|
||||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return wait_mgsl_event(info, argp);
|
return wait_mgsl_event(info, argp);
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
return modem_input_wait(info,(int)arg);
|
return modem_input_wait(info,(int)arg);
|
||||||
case TIOCGICOUNT:
|
|
||||||
spin_lock_irqsave(&info->lock,flags);
|
|
||||||
cnow = info->icount;
|
|
||||||
spin_unlock_irqrestore(&info->lock,flags);
|
|
||||||
p_cuser = argp;
|
|
||||||
if (put_user(cnow.cts, &p_cuser->cts) ||
|
|
||||||
put_user(cnow.dsr, &p_cuser->dsr) ||
|
|
||||||
put_user(cnow.rng, &p_cuser->rng) ||
|
|
||||||
put_user(cnow.dcd, &p_cuser->dcd) ||
|
|
||||||
put_user(cnow.rx, &p_cuser->rx) ||
|
|
||||||
put_user(cnow.tx, &p_cuser->tx) ||
|
|
||||||
put_user(cnow.frame, &p_cuser->frame) ||
|
|
||||||
put_user(cnow.overrun, &p_cuser->overrun) ||
|
|
||||||
put_user(cnow.parity, &p_cuser->parity) ||
|
|
||||||
put_user(cnow.brk, &p_cuser->brk) ||
|
|
||||||
put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
case MGSL_IOCSGPIO:
|
case MGSL_IOCSGPIO:
|
||||||
return set_gpio(info, argp);
|
return set_gpio(info, argp);
|
||||||
case MGSL_IOCGGPIO:
|
case MGSL_IOCGGPIO:
|
||||||
|
@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct slgt_info *info = tty->driver_data;
|
||||||
|
struct mgsl_icount cnow; /* kernel counter temps */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
|
cnow = info->icount;
|
||||||
|
spin_unlock_irqrestore(&info->lock,flags);
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* support for 32 bit ioctl calls on 64 bit systems
|
* support for 32 bit ioctl calls on 64 bit systems
|
||||||
*/
|
*/
|
||||||
|
@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
case MGSL_IOCSGPIO:
|
case MGSL_IOCSGPIO:
|
||||||
case MGSL_IOCGGPIO:
|
case MGSL_IOCGGPIO:
|
||||||
case MGSL_IOCWAITGPIO:
|
case MGSL_IOCWAITGPIO:
|
||||||
case TIOCGICOUNT:
|
|
||||||
rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MGSL_IOCSTXIDLE:
|
case MGSL_IOCSTXIDLE:
|
||||||
case MGSL_IOCTXENABLE:
|
case MGSL_IOCTXENABLE:
|
||||||
case MGSL_IOCRXENABLE:
|
case MGSL_IOCRXENABLE:
|
||||||
|
@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
|
||||||
.hangup = hangup,
|
.hangup = hangup,
|
||||||
.tiocmget = tiocmget,
|
.tiocmget = tiocmget,
|
||||||
.tiocmset = tiocmset,
|
.tiocmset = tiocmset,
|
||||||
|
.get_icount = get_icount,
|
||||||
.proc_fops = &synclink_gt_proc_fops,
|
.proc_fops = &synclink_gt_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
SLMP_INFO *info = tty->driver_data;
|
SLMP_INFO *info = tty->driver_data;
|
||||||
int error;
|
|
||||||
struct mgsl_icount cnow; /* kernel counter temps */
|
|
||||||
struct serial_icounter_struct __user *p_cuser; /* user space */
|
|
||||||
unsigned long flags;
|
|
||||||
void __user *argp = (void __user *)arg;
|
void __user *argp = (void __user *)arg;
|
||||||
|
|
||||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||||
|
@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
(cmd != TIOCMIWAIT)) {
|
||||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
* RI where only 0->1 is counted.
|
* RI where only 0->1 is counted.
|
||||||
*/
|
*/
|
||||||
case TIOCGICOUNT:
|
|
||||||
spin_lock_irqsave(&info->lock,flags);
|
|
||||||
cnow = info->icount;
|
|
||||||
spin_unlock_irqrestore(&info->lock,flags);
|
|
||||||
p_cuser = argp;
|
|
||||||
PUT_USER(error,cnow.cts, &p_cuser->cts);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.rng, &p_cuser->rng);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.dcd, &p_cuser->dcd);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.rx, &p_cuser->rx);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.tx, &p_cuser->tx);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.frame, &p_cuser->frame);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.overrun, &p_cuser->overrun);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.parity, &p_cuser->parity);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.brk, &p_cuser->brk);
|
|
||||||
if (error) return error;
|
|
||||||
PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
|
|
||||||
if (error) return error;
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
SLMP_INFO *info = tty->driver_data;
|
||||||
|
struct mgsl_icount cnow; /* kernel counter temps */
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&info->lock,flags);
|
||||||
|
cnow = info->icount;
|
||||||
|
spin_unlock_irqrestore(&info->lock,flags);
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* /proc fs routines....
|
* /proc fs routines....
|
||||||
*/
|
*/
|
||||||
|
@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
|
||||||
.hangup = hangup,
|
.hangup = hangup,
|
||||||
.tiocmget = tiocmget,
|
.tiocmget = tiocmget,
|
||||||
.tiocmset = tiocmset,
|
.tiocmset = tiocmset,
|
||||||
|
.get_icount = get_icount,
|
||||||
.proc_fops = &synclinkmp_proc_fops,
|
.proc_fops = &synclinkmp_proc_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -183,6 +184,8 @@ struct tty_struct *alloc_tty_struct(void)
|
||||||
|
|
||||||
void free_tty_struct(struct tty_struct *tty)
|
void free_tty_struct(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
|
if (tty->dev)
|
||||||
|
put_device(tty->dev);
|
||||||
kfree(tty->write_buf);
|
kfree(tty->write_buf);
|
||||||
tty_buffer_free_all(tty);
|
tty_buffer_free_all(tty);
|
||||||
kfree(tty);
|
kfree(tty);
|
||||||
|
@ -194,12 +197,13 @@ static inline struct tty_struct *file_tty(struct file *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Associate a new file with the tty structure */
|
/* Associate a new file with the tty structure */
|
||||||
void tty_add_file(struct tty_struct *tty, struct file *file)
|
int tty_add_file(struct tty_struct *tty, struct file *file)
|
||||||
{
|
{
|
||||||
struct tty_file_private *priv;
|
struct tty_file_private *priv;
|
||||||
|
|
||||||
/* XXX: must implement proper error handling in callers */
|
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
|
||||||
priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
priv->tty = tty;
|
priv->tty = tty;
|
||||||
priv->file = file;
|
priv->file = file;
|
||||||
|
@ -208,6 +212,8 @@ void tty_add_file(struct tty_struct *tty, struct file *file)
|
||||||
spin_lock(&tty_files_lock);
|
spin_lock(&tty_files_lock);
|
||||||
list_add(&priv->list, &tty->tty_files);
|
list_add(&priv->list, &tty->tty_files);
|
||||||
spin_unlock(&tty_files_lock);
|
spin_unlock(&tty_files_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete file from its tty */
|
/* Delete file from its tty */
|
||||||
|
@ -1875,7 +1881,11 @@ static int tty_open(struct inode *inode, struct file *filp)
|
||||||
return PTR_ERR(tty);
|
return PTR_ERR(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
tty_add_file(tty, filp);
|
retval = tty_add_file(tty, filp);
|
||||||
|
if (retval) {
|
||||||
|
tty_unlock();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
check_tty_count(tty, "tty_open");
|
check_tty_count(tty, "tty_open");
|
||||||
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||||
|
@ -2502,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
|
||||||
return tty->ops->tiocmset(tty, file, set, clear);
|
return tty->ops->tiocmset(tty, file, set, clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
|
||||||
|
{
|
||||||
|
int retval = -EINVAL;
|
||||||
|
struct serial_icounter_struct icount;
|
||||||
|
memset(&icount, 0, sizeof(icount));
|
||||||
|
if (tty->ops->get_icount)
|
||||||
|
retval = tty->ops->get_icount(tty, &icount);
|
||||||
|
if (retval != 0)
|
||||||
|
return retval;
|
||||||
|
if (copy_to_user(arg, &icount, sizeof(icount)))
|
||||||
|
return -EFAULT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
|
struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||||
|
@ -2622,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case TIOCMBIC:
|
case TIOCMBIC:
|
||||||
case TIOCMBIS:
|
case TIOCMBIS:
|
||||||
return tty_tiocmset(tty, file, cmd, p);
|
return tty_tiocmset(tty, file, cmd, p);
|
||||||
|
case TIOCGICOUNT:
|
||||||
|
retval = tty_tiocgicount(tty, p);
|
||||||
|
/* For the moment allow fall through to the old method */
|
||||||
|
if (retval != -EINVAL)
|
||||||
|
return retval;
|
||||||
|
break;
|
||||||
case TCFLSH:
|
case TCFLSH:
|
||||||
switch (arg) {
|
switch (arg) {
|
||||||
case TCIFLUSH:
|
case TCIFLUSH:
|
||||||
|
@ -2783,6 +2813,20 @@ void do_SAK(struct tty_struct *tty)
|
||||||
|
|
||||||
EXPORT_SYMBOL(do_SAK);
|
EXPORT_SYMBOL(do_SAK);
|
||||||
|
|
||||||
|
static int dev_match_devt(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
dev_t *devt = data;
|
||||||
|
return dev->devt == *devt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must put_device() after it's unused! */
|
||||||
|
static struct device *tty_get_device(struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
dev_t devt = tty_devnum(tty);
|
||||||
|
return class_find_device(tty_class, NULL, &devt, dev_match_devt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize_tty_struct
|
* initialize_tty_struct
|
||||||
* @tty: tty to initialize
|
* @tty: tty to initialize
|
||||||
|
@ -2823,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty,
|
||||||
tty->ops = driver->ops;
|
tty->ops = driver->ops;
|
||||||
tty->index = idx;
|
tty->index = idx;
|
||||||
tty_line_name(driver, idx, tty->name);
|
tty_line_name(driver, idx, tty->name);
|
||||||
|
tty->dev = tty_get_device(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2980,6 +3025,7 @@ int tty_register_driver(struct tty_driver *driver)
|
||||||
int i;
|
int i;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
void **p = NULL;
|
void **p = NULL;
|
||||||
|
struct device *d;
|
||||||
|
|
||||||
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
|
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
|
||||||
p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
|
p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
|
||||||
|
@ -3027,12 +3073,31 @@ int tty_register_driver(struct tty_driver *driver)
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
|
|
||||||
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
|
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
|
||||||
for (i = 0; i < driver->num; i++)
|
for (i = 0; i < driver->num; i++) {
|
||||||
tty_register_device(driver, i, NULL);
|
d = tty_register_device(driver, i, NULL);
|
||||||
|
if (IS_ERR(d)) {
|
||||||
|
error = PTR_ERR(d);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
proc_tty_register_driver(driver);
|
proc_tty_register_driver(driver);
|
||||||
driver->flags |= TTY_DRIVER_INSTALLED;
|
driver->flags |= TTY_DRIVER_INSTALLED;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
for (i--; i >= 0; i--)
|
||||||
|
tty_unregister_device(driver, i);
|
||||||
|
|
||||||
|
mutex_lock(&tty_mutex);
|
||||||
|
list_del(&driver->tty_drivers);
|
||||||
|
mutex_unlock(&tty_mutex);
|
||||||
|
|
||||||
|
unregister_chrdev_region(dev, driver->num);
|
||||||
|
driver->ttys = NULL;
|
||||||
|
driver->termios = NULL;
|
||||||
|
kfree(p);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(tty_register_driver);
|
EXPORT_SYMBOL(tty_register_driver);
|
||||||
|
|
225
drivers/char/ttyprintk.c
Normal file
225
drivers/char/ttyprintk.c
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* linux/drivers/char/ttyprintk.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Samo Pogacnik
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the smems of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This pseudo device allows user to make printk messages. It is possible
|
||||||
|
* to store "console" messages inline with kernel messages for better analyses
|
||||||
|
* of the boot process, for example.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
|
||||||
|
struct ttyprintk_port {
|
||||||
|
struct tty_port port;
|
||||||
|
struct mutex port_write_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ttyprintk_port tpk_port;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our simple preformatting supports transparent output of (time-stamped)
|
||||||
|
* printk messages (also suitable for logging service):
|
||||||
|
* - any cr is replaced by nl
|
||||||
|
* - adds a ttyprintk source tag in front of each line
|
||||||
|
* - too long message is fragmeted, with '\'nl between fragments
|
||||||
|
* - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
|
||||||
|
* it is emptied on the fly during preformatting.
|
||||||
|
*/
|
||||||
|
#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
|
||||||
|
#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
|
||||||
|
static const char *tpk_tag = "[U] "; /* U for User */
|
||||||
|
static int tpk_curr;
|
||||||
|
|
||||||
|
static int tpk_printk(const unsigned char *buf, int count)
|
||||||
|
{
|
||||||
|
static char tmp[TPK_STR_SIZE + 4];
|
||||||
|
int i = tpk_curr;
|
||||||
|
|
||||||
|
if (buf == NULL) {
|
||||||
|
/* flush tmp[] */
|
||||||
|
if (tpk_curr > 0) {
|
||||||
|
/* non nl or cr terminated message - add nl */
|
||||||
|
tmp[tpk_curr + 0] = '\n';
|
||||||
|
tmp[tpk_curr + 1] = '\0';
|
||||||
|
printk(KERN_INFO "%s%s", tpk_tag, tmp);
|
||||||
|
tpk_curr = 0;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
tmp[tpk_curr] = buf[i];
|
||||||
|
if (tpk_curr < TPK_STR_SIZE) {
|
||||||
|
switch (buf[i]) {
|
||||||
|
case '\r':
|
||||||
|
/* replace cr with nl */
|
||||||
|
tmp[tpk_curr + 0] = '\n';
|
||||||
|
tmp[tpk_curr + 1] = '\0';
|
||||||
|
printk(KERN_INFO "%s%s", tpk_tag, tmp);
|
||||||
|
tpk_curr = 0;
|
||||||
|
if (buf[i + 1] == '\n')
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
tmp[tpk_curr + 1] = '\0';
|
||||||
|
printk(KERN_INFO "%s%s", tpk_tag, tmp);
|
||||||
|
tpk_curr = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tpk_curr++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* end of tmp buffer reached: cut the message in two */
|
||||||
|
tmp[tpk_curr + 1] = '\\';
|
||||||
|
tmp[tpk_curr + 2] = '\n';
|
||||||
|
tmp[tpk_curr + 3] = '\0';
|
||||||
|
printk(KERN_INFO "%s%s", tpk_tag, tmp);
|
||||||
|
tpk_curr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TTY operations open function.
|
||||||
|
*/
|
||||||
|
static int tpk_open(struct tty_struct *tty, struct file *filp)
|
||||||
|
{
|
||||||
|
tty->driver_data = &tpk_port;
|
||||||
|
|
||||||
|
return tty_port_open(&tpk_port.port, tty, filp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TTY operations close function.
|
||||||
|
*/
|
||||||
|
static void tpk_close(struct tty_struct *tty, struct file *filp)
|
||||||
|
{
|
||||||
|
struct ttyprintk_port *tpkp = tty->driver_data;
|
||||||
|
|
||||||
|
mutex_lock(&tpkp->port_write_mutex);
|
||||||
|
/* flush tpk_printk buffer */
|
||||||
|
tpk_printk(NULL, 0);
|
||||||
|
mutex_unlock(&tpkp->port_write_mutex);
|
||||||
|
|
||||||
|
tty_port_close(&tpkp->port, tty, filp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TTY operations write function.
|
||||||
|
*/
|
||||||
|
static int tpk_write(struct tty_struct *tty,
|
||||||
|
const unsigned char *buf, int count)
|
||||||
|
{
|
||||||
|
struct ttyprintk_port *tpkp = tty->driver_data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
/* exclusive use of tpk_printk within this tty */
|
||||||
|
mutex_lock(&tpkp->port_write_mutex);
|
||||||
|
ret = tpk_printk(buf, count);
|
||||||
|
mutex_unlock(&tpkp->port_write_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TTY operations write_room function.
|
||||||
|
*/
|
||||||
|
static int tpk_write_room(struct tty_struct *tty)
|
||||||
|
{
|
||||||
|
return TPK_MAX_ROOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TTY operations ioctl function.
|
||||||
|
*/
|
||||||
|
static int tpk_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct ttyprintk_port *tpkp = tty->driver_data;
|
||||||
|
|
||||||
|
if (!tpkp)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
/* Stop TIOCCONS */
|
||||||
|
case TIOCCONS:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
default:
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct tty_operations ttyprintk_ops = {
|
||||||
|
.open = tpk_open,
|
||||||
|
.close = tpk_close,
|
||||||
|
.write = tpk_write,
|
||||||
|
.write_room = tpk_write_room,
|
||||||
|
.ioctl = tpk_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tty_port_operations null_ops = { };
|
||||||
|
|
||||||
|
static struct tty_driver *ttyprintk_driver;
|
||||||
|
|
||||||
|
static int __init ttyprintk_init(void)
|
||||||
|
{
|
||||||
|
int ret = -ENOMEM;
|
||||||
|
void *rp;
|
||||||
|
|
||||||
|
ttyprintk_driver = alloc_tty_driver(1);
|
||||||
|
if (!ttyprintk_driver)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ttyprintk_driver->owner = THIS_MODULE;
|
||||||
|
ttyprintk_driver->driver_name = "ttyprintk";
|
||||||
|
ttyprintk_driver->name = "ttyprintk";
|
||||||
|
ttyprintk_driver->major = TTYAUX_MAJOR;
|
||||||
|
ttyprintk_driver->minor_start = 3;
|
||||||
|
ttyprintk_driver->num = 1;
|
||||||
|
ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
|
||||||
|
ttyprintk_driver->init_termios = tty_std_termios;
|
||||||
|
ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
|
||||||
|
ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
|
||||||
|
TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||||
|
tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
|
||||||
|
|
||||||
|
ret = tty_register_driver(ttyprintk_driver);
|
||||||
|
if (ret < 0) {
|
||||||
|
printk(KERN_ERR "Couldn't register ttyprintk driver\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create our unnumbered device */
|
||||||
|
rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
|
||||||
|
ttyprintk_driver->name);
|
||||||
|
if (IS_ERR(rp)) {
|
||||||
|
printk(KERN_ERR "Couldn't create ttyprintk device\n");
|
||||||
|
ret = PTR_ERR(rp);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_port_init(&tpk_port.port);
|
||||||
|
tpk_port.port.ops = &null_ops;
|
||||||
|
mutex_init(&tpk_port.port_write_mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
put_tty_driver(ttyprintk_driver);
|
||||||
|
ttyprintk_driver = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
module_init(ttyprintk_init);
|
|
@ -35,6 +35,12 @@
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/poll.h>
|
||||||
|
#include <linux/signal.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/notifier.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
@ -45,6 +51,86 @@
|
||||||
#undef addr
|
#undef addr
|
||||||
#define HEADER_SIZE 4
|
#define HEADER_SIZE 4
|
||||||
|
|
||||||
|
struct vcs_poll_data {
|
||||||
|
struct notifier_block notifier;
|
||||||
|
unsigned int cons_num;
|
||||||
|
bool seen_last_update;
|
||||||
|
wait_queue_head_t waitq;
|
||||||
|
struct fasync_struct *fasync;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
|
||||||
|
{
|
||||||
|
struct vt_notifier_param *param = _param;
|
||||||
|
struct vc_data *vc = param->vc;
|
||||||
|
struct vcs_poll_data *poll =
|
||||||
|
container_of(nb, struct vcs_poll_data, notifier);
|
||||||
|
int currcons = poll->cons_num;
|
||||||
|
|
||||||
|
if (code != VT_UPDATE)
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
|
if (currcons == 0)
|
||||||
|
currcons = fg_console;
|
||||||
|
else
|
||||||
|
currcons--;
|
||||||
|
if (currcons != vc->vc_num)
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
|
poll->seen_last_update = false;
|
||||||
|
wake_up_interruptible(&poll->waitq);
|
||||||
|
kill_fasync(&poll->fasync, SIGIO, POLL_IN);
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vcs_poll_data_free(struct vcs_poll_data *poll)
|
||||||
|
{
|
||||||
|
unregister_vt_notifier(&poll->notifier);
|
||||||
|
kfree(poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct vcs_poll_data *
|
||||||
|
vcs_poll_data_get(struct file *file)
|
||||||
|
{
|
||||||
|
struct vcs_poll_data *poll = file->private_data;
|
||||||
|
|
||||||
|
if (poll)
|
||||||
|
return poll;
|
||||||
|
|
||||||
|
poll = kzalloc(sizeof(*poll), GFP_KERNEL);
|
||||||
|
if (!poll)
|
||||||
|
return NULL;
|
||||||
|
poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
|
||||||
|
init_waitqueue_head(&poll->waitq);
|
||||||
|
poll->notifier.notifier_call = vcs_notifier;
|
||||||
|
if (register_vt_notifier(&poll->notifier) != 0) {
|
||||||
|
kfree(poll);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code may be called either through ->poll() or ->fasync().
|
||||||
|
* If we have two threads using the same file descriptor, they could
|
||||||
|
* both enter this function, both notice that the structure hasn't
|
||||||
|
* been allocated yet and go ahead allocating it in parallel, but
|
||||||
|
* only one of them must survive and be shared otherwise we'd leak
|
||||||
|
* memory with a dangling notifier callback.
|
||||||
|
*/
|
||||||
|
spin_lock(&file->f_lock);
|
||||||
|
if (!file->private_data) {
|
||||||
|
file->private_data = poll;
|
||||||
|
} else {
|
||||||
|
/* someone else raced ahead of us */
|
||||||
|
vcs_poll_data_free(poll);
|
||||||
|
poll = file->private_data;
|
||||||
|
}
|
||||||
|
spin_unlock(&file->f_lock);
|
||||||
|
|
||||||
|
return poll;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vcs_size(struct inode *inode)
|
vcs_size(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +188,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||||
struct inode *inode = file->f_path.dentry->d_inode;
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
unsigned int currcons = iminor(inode);
|
unsigned int currcons = iminor(inode);
|
||||||
struct vc_data *vc;
|
struct vc_data *vc;
|
||||||
|
struct vcs_poll_data *poll;
|
||||||
long pos;
|
long pos;
|
||||||
long viewed, attr, read;
|
long viewed, attr, read;
|
||||||
int col, maxcol;
|
int col, maxcol;
|
||||||
|
@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
|
poll = file->private_data;
|
||||||
|
if (count && poll)
|
||||||
|
poll->seen_last_update = true;
|
||||||
read = 0;
|
read = 0;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
while (count) {
|
while (count) {
|
||||||
|
@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||||
}
|
}
|
||||||
*ppos += written;
|
*ppos += written;
|
||||||
ret = written;
|
ret = written;
|
||||||
|
if (written)
|
||||||
|
vcs_scr_updated(vc);
|
||||||
|
|
||||||
unlock_out:
|
unlock_out:
|
||||||
release_console_sem();
|
release_console_sem();
|
||||||
|
@ -457,6 +549,37 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
vcs_poll(struct file *file, poll_table *wait)
|
||||||
|
{
|
||||||
|
struct vcs_poll_data *poll = vcs_poll_data_get(file);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (poll) {
|
||||||
|
poll_wait(file, &poll->waitq, wait);
|
||||||
|
if (!poll->seen_last_update)
|
||||||
|
ret = POLLIN | POLLRDNORM;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vcs_fasync(int fd, struct file *file, int on)
|
||||||
|
{
|
||||||
|
struct vcs_poll_data *poll = file->private_data;
|
||||||
|
|
||||||
|
if (!poll) {
|
||||||
|
/* don't allocate anything if all we want is disable fasync */
|
||||||
|
if (!on)
|
||||||
|
return 0;
|
||||||
|
poll = vcs_poll_data_get(file);
|
||||||
|
if (!poll)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fasync_helper(fd, file, on, &poll->fasync);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vcs_open(struct inode *inode, struct file *filp)
|
vcs_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
|
@ -470,11 +593,23 @@ vcs_open(struct inode *inode, struct file *filp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vcs_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct vcs_poll_data *poll = file->private_data;
|
||||||
|
|
||||||
|
if (poll)
|
||||||
|
vcs_poll_data_free(poll);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations vcs_fops = {
|
static const struct file_operations vcs_fops = {
|
||||||
.llseek = vcs_lseek,
|
.llseek = vcs_lseek,
|
||||||
.read = vcs_read,
|
.read = vcs_read,
|
||||||
.write = vcs_write,
|
.write = vcs_write,
|
||||||
|
.poll = vcs_poll,
|
||||||
|
.fasync = vcs_fasync,
|
||||||
.open = vcs_open,
|
.open = vcs_open,
|
||||||
|
.release = vcs_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct class *vc_class;
|
static struct class *vc_class;
|
||||||
|
|
|
@ -4182,6 +4182,11 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vcs_scr_updated(struct vc_data *vc)
|
||||||
|
{
|
||||||
|
notify_update(vc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Visible symbols for modules
|
* Visible symbols for modules
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -165,6 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
|
||||||
serio->open = serport_serio_open;
|
serio->open = serport_serio_open;
|
||||||
serio->close = serport_serio_close;
|
serio->close = serport_serio_close;
|
||||||
serio->port_data = serport;
|
serio->port_data = serport;
|
||||||
|
serio->dev.parent = tty->dev;
|
||||||
|
|
||||||
serio_register_port(serport->serio);
|
serio_register_port(serport->serio);
|
||||||
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
|
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
|
||||||
|
|
|
@ -1645,11 +1645,11 @@ hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
* RI where only 0->1 is counted.
|
* RI where only 0->1 is counted.
|
||||||
*/
|
*/
|
||||||
static int hso_get_count(struct hso_serial *serial,
|
static int hso_get_count(struct tty_struct *tty,
|
||||||
struct serial_icounter_struct __user *icnt)
|
struct serial_icounter_struct *icount)
|
||||||
{
|
{
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
struct uart_icount cnow;
|
struct uart_icount cnow;
|
||||||
|
struct hso_serial *serial = get_serial_by_tty(tty);
|
||||||
struct hso_tiocmget *tiocmget = serial->tiocmget;
|
struct hso_tiocmget *tiocmget = serial->tiocmget;
|
||||||
|
|
||||||
memset(&icount, 0, sizeof(struct serial_icounter_struct));
|
memset(&icount, 0, sizeof(struct serial_icounter_struct));
|
||||||
|
@ -1660,19 +1660,19 @@ static int hso_get_count(struct hso_serial *serial,
|
||||||
memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
|
memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
|
||||||
spin_unlock_irq(&serial->serial_lock);
|
spin_unlock_irq(&serial->serial_lock);
|
||||||
|
|
||||||
icount.cts = cnow.cts;
|
icount->cts = cnow.cts;
|
||||||
icount.dsr = cnow.dsr;
|
icount->dsr = cnow.dsr;
|
||||||
icount.rng = cnow.rng;
|
icount->rng = cnow.rng;
|
||||||
icount.dcd = cnow.dcd;
|
icount->dcd = cnow.dcd;
|
||||||
icount.rx = cnow.rx;
|
icount->rx = cnow.rx;
|
||||||
icount.tx = cnow.tx;
|
icount->tx = cnow.tx;
|
||||||
icount.frame = cnow.frame;
|
icount->frame = cnow.frame;
|
||||||
icount.overrun = cnow.overrun;
|
icount->overrun = cnow.overrun;
|
||||||
icount.parity = cnow.parity;
|
icount->parity = cnow.parity;
|
||||||
icount.brk = cnow.brk;
|
icount->brk = cnow.brk;
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1764,10 +1764,6 @@ static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
ret = hso_wait_modem_status(serial, arg);
|
ret = hso_wait_modem_status(serial, arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
ret = hso_get_count(serial, uarg);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
ret = -ENOIOCTLCMD;
|
ret = -ENOIOCTLCMD;
|
||||||
break;
|
break;
|
||||||
|
@ -3300,6 +3296,7 @@ static const struct tty_operations hso_serial_ops = {
|
||||||
.chars_in_buffer = hso_serial_chars_in_buffer,
|
.chars_in_buffer = hso_serial_chars_in_buffer,
|
||||||
.tiocmget = hso_serial_tiocmget,
|
.tiocmget = hso_serial_tiocmget,
|
||||||
.tiocmset = hso_serial_tiocmset,
|
.tiocmset = hso_serial_tiocmset,
|
||||||
|
.get_icount = hso_get_count,
|
||||||
.unthrottle = hso_unthrottle
|
.unthrottle = hso_unthrottle
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1381,6 +1381,30 @@ static void send_break(ser_info_t *info, unsigned int duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
||||||
|
* Return: write counters to the user passed counter struct
|
||||||
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
|
* RI where only 0->1 is counted.
|
||||||
|
*/
|
||||||
|
static int rs_360_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
ser_info_t *info = (ser_info_t *)tty->driver_data;
|
||||||
|
struct async_icount cnow;
|
||||||
|
|
||||||
|
local_irq_disable();
|
||||||
|
cnow = info->state->icount;
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
|
static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -1394,7 +1418,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
if (cmd != TIOCMIWAIT) {
|
||||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
|
|
||||||
* Return: write counters to the user passed counter struct
|
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
|
||||||
* RI where only 0->1 is counted.
|
|
||||||
*/
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
local_irq_disable();
|
|
||||||
cnow = info->state->icount;
|
|
||||||
local_irq_enable();
|
|
||||||
p_cuser = (struct serial_icounter_struct *) arg;
|
|
||||||
/* error = put_user(cnow.cts, &p_cuser->cts); */
|
|
||||||
/* if (error) return error; */
|
|
||||||
/* error = put_user(cnow.dsr, &p_cuser->dsr); */
|
|
||||||
/* if (error) return error; */
|
|
||||||
/* error = put_user(cnow.rng, &p_cuser->rng); */
|
|
||||||
/* if (error) return error; */
|
|
||||||
/* error = put_user(cnow.dcd, &p_cuser->dcd); */
|
|
||||||
/* if (error) return error; */
|
|
||||||
|
|
||||||
put_user(cnow.cts, &p_cuser->cts);
|
|
||||||
put_user(cnow.dsr, &p_cuser->dsr);
|
|
||||||
put_user(cnow.rng, &p_cuser->rng);
|
|
||||||
put_user(cnow.dcd, &p_cuser->dcd);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
@ -154,12 +155,6 @@ struct uart_8250_port {
|
||||||
unsigned char lsr_saved_flags;
|
unsigned char lsr_saved_flags;
|
||||||
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
|
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
|
||||||
unsigned char msr_saved_flags;
|
unsigned char msr_saved_flags;
|
||||||
|
|
||||||
/*
|
|
||||||
* We provide a per-port pm hook.
|
|
||||||
*/
|
|
||||||
void (*pm)(struct uart_port *port,
|
|
||||||
unsigned int state, unsigned int old);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct irq_info {
|
struct irq_info {
|
||||||
|
@ -1606,8 +1601,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
|
||||||
|
|
||||||
if (l == i->head && pass_counter++ > PASS_LIMIT) {
|
if (l == i->head && pass_counter++ > PASS_LIMIT) {
|
||||||
/* If we hit this, we're dead. */
|
/* If we hit this, we're dead. */
|
||||||
printk(KERN_ERR "serial8250: too much work for "
|
printk_ratelimited(KERN_ERR
|
||||||
"irq%d\n", irq);
|
"serial8250: too much work for irq%d\n", irq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (l != end);
|
} while (l != end);
|
||||||
|
@ -1722,12 +1717,6 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
|
||||||
mutex_unlock(&hash_mutex);
|
mutex_unlock(&hash_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base timer interval for polling */
|
|
||||||
static inline int poll_timeout(int timeout)
|
|
||||||
{
|
|
||||||
return timeout > 6 ? (timeout / 2 - 2) : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is used to handle ports that do not have an
|
* This function is used to handle ports that do not have an
|
||||||
* interrupt. This doesn't work very well for 16450's, but gives
|
* interrupt. This doesn't work very well for 16450's, but gives
|
||||||
|
@ -1742,7 +1731,7 @@ static void serial8250_timeout(unsigned long data)
|
||||||
iir = serial_in(up, UART_IIR);
|
iir = serial_in(up, UART_IIR);
|
||||||
if (!(iir & UART_IIR_NO_INT))
|
if (!(iir & UART_IIR_NO_INT))
|
||||||
serial8250_handle_port(up);
|
serial8250_handle_port(up);
|
||||||
mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
|
mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial8250_backup_timeout(unsigned long data)
|
static void serial8250_backup_timeout(unsigned long data)
|
||||||
|
@ -1787,7 +1776,7 @@ static void serial8250_backup_timeout(unsigned long data)
|
||||||
|
|
||||||
/* Standard timer interval plus 0.2s to keep the port running */
|
/* Standard timer interval plus 0.2s to keep the port running */
|
||||||
mod_timer(&up->timer,
|
mod_timer(&up->timer,
|
||||||
jiffies + poll_timeout(up->port.timeout) + HZ / 5);
|
jiffies + uart_poll_timeout(&up->port) + HZ / 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int serial8250_tx_empty(struct uart_port *port)
|
static unsigned int serial8250_tx_empty(struct uart_port *port)
|
||||||
|
@ -1867,15 +1856,17 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
||||||
unsigned int status, tmout = 10000;
|
unsigned int status, tmout = 10000;
|
||||||
|
|
||||||
/* Wait up to 10ms for the character(s) to be sent. */
|
/* Wait up to 10ms for the character(s) to be sent. */
|
||||||
do {
|
for (;;) {
|
||||||
status = serial_in(up, UART_LSR);
|
status = serial_in(up, UART_LSR);
|
||||||
|
|
||||||
up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
|
up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
|
||||||
|
|
||||||
|
if ((status & bits) == bits)
|
||||||
|
break;
|
||||||
if (--tmout == 0)
|
if (--tmout == 0)
|
||||||
break;
|
break;
|
||||||
udelay(1);
|
udelay(1);
|
||||||
} while ((status & bits) != bits);
|
}
|
||||||
|
|
||||||
/* Wait up to 1s for flow control if necessary */
|
/* Wait up to 1s for flow control if necessary */
|
||||||
if (up->port.flags & UPF_CONS_FLOW) {
|
if (up->port.flags & UPF_CONS_FLOW) {
|
||||||
|
@ -2069,7 +2060,7 @@ static int serial8250_startup(struct uart_port *port)
|
||||||
up->timer.function = serial8250_backup_timeout;
|
up->timer.function = serial8250_backup_timeout;
|
||||||
up->timer.data = (unsigned long)up;
|
up->timer.data = (unsigned long)up;
|
||||||
mod_timer(&up->timer, jiffies +
|
mod_timer(&up->timer, jiffies +
|
||||||
poll_timeout(up->port.timeout) + HZ / 5);
|
uart_poll_timeout(port) + HZ / 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2079,7 +2070,7 @@ static int serial8250_startup(struct uart_port *port)
|
||||||
*/
|
*/
|
||||||
if (!is_real_interrupt(up->port.irq)) {
|
if (!is_real_interrupt(up->port.irq)) {
|
||||||
up->timer.data = (unsigned long)up;
|
up->timer.data = (unsigned long)up;
|
||||||
mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
|
mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
|
||||||
} else {
|
} else {
|
||||||
retval = serial_link_irq_chain(up);
|
retval = serial_link_irq_chain(up);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -2440,16 +2431,24 @@ serial8250_set_ldisc(struct uart_port *port, int new)
|
||||||
port->flags &= ~UPF_HARDPPS_CD;
|
port->flags &= ~UPF_HARDPPS_CD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
serial8250_pm(struct uart_port *port, unsigned int state,
|
void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
||||||
unsigned int oldstate)
|
unsigned int oldstate)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *p = (struct uart_8250_port *)port;
|
struct uart_8250_port *p = (struct uart_8250_port *)port;
|
||||||
|
|
||||||
serial8250_set_sleep(p, state != 0);
|
serial8250_set_sleep(p, state != 0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(serial8250_do_pm);
|
||||||
|
|
||||||
if (p->pm)
|
static void
|
||||||
p->pm(port, state, oldstate);
|
serial8250_pm(struct uart_port *port, unsigned int state,
|
||||||
|
unsigned int oldstate)
|
||||||
|
{
|
||||||
|
if (port->pm)
|
||||||
|
port->pm(port, state, oldstate);
|
||||||
|
else
|
||||||
|
serial8250_do_pm(port, state, oldstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int serial8250_port_size(struct uart_8250_port *pt)
|
static unsigned int serial8250_port_size(struct uart_8250_port *pt)
|
||||||
|
@ -2674,6 +2673,16 @@ static struct uart_ops serial8250_pops = {
|
||||||
|
|
||||||
static struct uart_8250_port serial8250_ports[UART_NR];
|
static struct uart_8250_port serial8250_ports[UART_NR];
|
||||||
|
|
||||||
|
static void (*serial8250_isa_config)(int port, struct uart_port *up,
|
||||||
|
unsigned short *capabilities);
|
||||||
|
|
||||||
|
void serial8250_set_isa_configurator(
|
||||||
|
void (*v)(int port, struct uart_port *up, unsigned short *capabilities))
|
||||||
|
{
|
||||||
|
serial8250_isa_config = v;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(serial8250_set_isa_configurator);
|
||||||
|
|
||||||
static void __init serial8250_isa_init_ports(void)
|
static void __init serial8250_isa_init_ports(void)
|
||||||
{
|
{
|
||||||
struct uart_8250_port *up;
|
struct uart_8250_port *up;
|
||||||
|
@ -2719,6 +2728,9 @@ static void __init serial8250_isa_init_ports(void)
|
||||||
up->port.regshift = old_serial_port[i].iomem_reg_shift;
|
up->port.regshift = old_serial_port[i].iomem_reg_shift;
|
||||||
set_io_from_upio(&up->port);
|
set_io_from_upio(&up->port);
|
||||||
up->port.irqflags |= irqflag;
|
up->port.irqflags |= irqflag;
|
||||||
|
if (serial8250_isa_config != NULL)
|
||||||
|
serial8250_isa_config(i, &up->port, &up->capabilities);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3010,6 +3022,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
|
||||||
port.serial_in = p->serial_in;
|
port.serial_in = p->serial_in;
|
||||||
port.serial_out = p->serial_out;
|
port.serial_out = p->serial_out;
|
||||||
port.set_termios = p->set_termios;
|
port.set_termios = p->set_termios;
|
||||||
|
port.pm = p->pm;
|
||||||
port.dev = &dev->dev;
|
port.dev = &dev->dev;
|
||||||
port.irqflags |= irqflag;
|
port.irqflags |= irqflag;
|
||||||
ret = serial8250_register_port(&port);
|
ret = serial8250_register_port(&port);
|
||||||
|
@ -3176,6 +3189,12 @@ int serial8250_register_port(struct uart_port *port)
|
||||||
/* Possibly override set_termios call */
|
/* Possibly override set_termios call */
|
||||||
if (port->set_termios)
|
if (port->set_termios)
|
||||||
uart->port.set_termios = port->set_termios;
|
uart->port.set_termios = port->set_termios;
|
||||||
|
if (port->pm)
|
||||||
|
uart->port.pm = port->pm;
|
||||||
|
|
||||||
|
if (serial8250_isa_config != NULL)
|
||||||
|
serial8250_isa_config(0, &uart->port,
|
||||||
|
&uart->capabilities);
|
||||||
|
|
||||||
ret = uart_add_one_port(&serial8250_reg, &uart->port);
|
ret = uart_add_one_port(&serial8250_reg, &uart->port);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|
|
@ -718,13 +718,6 @@ config SERIAL_MRST_MAX3110
|
||||||
the Intel Moorestown platform. On other systems use the max3100
|
the Intel Moorestown platform. On other systems use the max3100
|
||||||
driver.
|
driver.
|
||||||
|
|
||||||
config MRST_MAX3110_IRQ
|
|
||||||
boolean "Enable GPIO IRQ for Max3110 over Moorestown"
|
|
||||||
default n
|
|
||||||
depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL
|
|
||||||
help
|
|
||||||
This has to be enabled after Moorestown GPIO driver is loaded
|
|
||||||
|
|
||||||
config SERIAL_MFD_HSU
|
config SERIAL_MFD_HSU
|
||||||
tristate "Medfield High Speed UART support"
|
tristate "Medfield High Speed UART support"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
|
@ -27,6 +28,8 @@
|
||||||
#include <linux/altera_uart.h>
|
#include <linux/altera_uart.h>
|
||||||
|
|
||||||
#define DRV_NAME "altera_uart"
|
#define DRV_NAME "altera_uart"
|
||||||
|
#define SERIAL_ALTERA_MAJOR 204
|
||||||
|
#define SERIAL_ALTERA_MINOR 213
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Altera UART register definitions according to the Nios UART datasheet:
|
* Altera UART register definitions according to the Nios UART datasheet:
|
||||||
|
@ -76,13 +79,28 @@
|
||||||
*/
|
*/
|
||||||
struct altera_uart {
|
struct altera_uart {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
|
struct timer_list tmr;
|
||||||
unsigned int sigs; /* Local copy of line sigs */
|
unsigned int sigs; /* Local copy of line sigs */
|
||||||
unsigned short imr; /* Local IMR mirror */
|
unsigned short imr; /* Local IMR mirror */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u32 altera_uart_readl(struct uart_port *port, int reg)
|
||||||
|
{
|
||||||
|
struct altera_uart_platform_uart *platp = port->private_data;
|
||||||
|
|
||||||
|
return readl(port->membase + (reg << platp->bus_shift));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void altera_uart_writel(struct uart_port *port, u32 dat, int reg)
|
||||||
|
{
|
||||||
|
struct altera_uart_platform_uart *platp = port->private_data;
|
||||||
|
|
||||||
|
writel(dat, port->membase + (reg << platp->bus_shift));
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int altera_uart_tx_empty(struct uart_port *port)
|
static unsigned int altera_uart_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
return (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||||
ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
|
ALTERA_UART_STATUS_TMT_MSK) ? TIOCSER_TEMT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +109,7 @@ static unsigned int altera_uart_get_mctrl(struct uart_port *port)
|
||||||
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
unsigned int sigs;
|
unsigned int sigs;
|
||||||
|
|
||||||
sigs =
|
sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||||
(readl(port->membase + ALTERA_UART_STATUS_REG) &
|
|
||||||
ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
|
ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
|
||||||
sigs |= (pp->sigs & TIOCM_RTS);
|
sigs |= (pp->sigs & TIOCM_RTS);
|
||||||
|
|
||||||
|
@ -108,7 +125,7 @@ static void altera_uart_set_mctrl(struct uart_port *port, unsigned int sigs)
|
||||||
pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
|
pp->imr |= ALTERA_UART_CONTROL_RTS_MSK;
|
||||||
else
|
else
|
||||||
pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
|
pp->imr &= ~ALTERA_UART_CONTROL_RTS_MSK;
|
||||||
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_uart_start_tx(struct uart_port *port)
|
static void altera_uart_start_tx(struct uart_port *port)
|
||||||
|
@ -116,7 +133,7 @@ static void altera_uart_start_tx(struct uart_port *port)
|
||||||
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
|
||||||
pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
|
pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
|
||||||
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_uart_stop_tx(struct uart_port *port)
|
static void altera_uart_stop_tx(struct uart_port *port)
|
||||||
|
@ -124,7 +141,7 @@ static void altera_uart_stop_tx(struct uart_port *port)
|
||||||
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
|
||||||
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
|
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
|
||||||
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_uart_stop_rx(struct uart_port *port)
|
static void altera_uart_stop_rx(struct uart_port *port)
|
||||||
|
@ -132,7 +149,7 @@ static void altera_uart_stop_rx(struct uart_port *port)
|
||||||
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
|
||||||
pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
|
pp->imr &= ~ALTERA_UART_CONTROL_RRDY_MSK;
|
||||||
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void altera_uart_break_ctl(struct uart_port *port, int break_state)
|
static void altera_uart_break_ctl(struct uart_port *port, int break_state)
|
||||||
|
@ -145,7 +162,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
|
||||||
pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
|
pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
|
||||||
else
|
else
|
||||||
pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
|
pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
|
||||||
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +185,8 @@ static void altera_uart_set_termios(struct uart_port *port,
|
||||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
|
uart_update_timeout(port, termios->c_cflag, baud);
|
||||||
|
altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,14 +196,15 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
|
||||||
unsigned char ch, flag;
|
unsigned char ch, flag;
|
||||||
unsigned short status;
|
unsigned short status;
|
||||||
|
|
||||||
while ((status = readl(port->membase + ALTERA_UART_STATUS_REG)) &
|
while ((status = altera_uart_readl(port, ALTERA_UART_STATUS_REG)) &
|
||||||
ALTERA_UART_STATUS_RRDY_MSK) {
|
ALTERA_UART_STATUS_RRDY_MSK) {
|
||||||
ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
|
ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
|
||||||
flag = TTY_NORMAL;
|
flag = TTY_NORMAL;
|
||||||
port->icount.rx++;
|
port->icount.rx++;
|
||||||
|
|
||||||
if (status & ALTERA_UART_STATUS_E_MSK) {
|
if (status & ALTERA_UART_STATUS_E_MSK) {
|
||||||
writel(status, port->membase + ALTERA_UART_STATUS_REG);
|
altera_uart_writel(port, status,
|
||||||
|
ALTERA_UART_STATUS_REG);
|
||||||
|
|
||||||
if (status & ALTERA_UART_STATUS_BRK_MSK) {
|
if (status & ALTERA_UART_STATUS_BRK_MSK) {
|
||||||
port->icount.brk++;
|
port->icount.brk++;
|
||||||
|
@ -225,18 +244,18 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
|
||||||
|
|
||||||
if (port->x_char) {
|
if (port->x_char) {
|
||||||
/* Send special char - probably flow control */
|
/* Send special char - probably flow control */
|
||||||
writel(port->x_char, port->membase + ALTERA_UART_TXDATA_REG);
|
altera_uart_writel(port, port->x_char, ALTERA_UART_TXDATA_REG);
|
||||||
port->x_char = 0;
|
port->x_char = 0;
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||||
ALTERA_UART_STATUS_TRDY_MSK) {
|
ALTERA_UART_STATUS_TRDY_MSK) {
|
||||||
if (xmit->head == xmit->tail)
|
if (xmit->head == xmit->tail)
|
||||||
break;
|
break;
|
||||||
writel(xmit->buf[xmit->tail],
|
altera_uart_writel(port, xmit->buf[xmit->tail],
|
||||||
port->membase + ALTERA_UART_TXDATA_REG);
|
ALTERA_UART_TXDATA_REG);
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
port->icount.tx++;
|
port->icount.tx++;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +265,7 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
|
||||||
|
|
||||||
if (xmit->head == xmit->tail) {
|
if (xmit->head == xmit->tail) {
|
||||||
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
|
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
|
||||||
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +275,7 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
|
||||||
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
unsigned int isr;
|
unsigned int isr;
|
||||||
|
|
||||||
isr = readl(port->membase + ALTERA_UART_STATUS_REG) & pp->imr;
|
isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
|
||||||
|
|
||||||
spin_lock(&port->lock);
|
spin_lock(&port->lock);
|
||||||
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
|
if (isr & ALTERA_UART_STATUS_RRDY_MSK)
|
||||||
|
@ -268,14 +287,23 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data)
|
||||||
return IRQ_RETVAL(isr);
|
return IRQ_RETVAL(isr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void altera_uart_timer(unsigned long data)
|
||||||
|
{
|
||||||
|
struct uart_port *port = (void *)data;
|
||||||
|
struct altera_uart *pp = container_of(port, struct altera_uart, port);
|
||||||
|
|
||||||
|
altera_uart_interrupt(0, port);
|
||||||
|
mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
|
||||||
|
}
|
||||||
|
|
||||||
static void altera_uart_config_port(struct uart_port *port, int flags)
|
static void altera_uart_config_port(struct uart_port *port, int flags)
|
||||||
{
|
{
|
||||||
port->type = PORT_ALTERA_UART;
|
port->type = PORT_ALTERA_UART;
|
||||||
|
|
||||||
/* Clear mask, so no surprise interrupts. */
|
/* Clear mask, so no surprise interrupts. */
|
||||||
writel(0, port->membase + ALTERA_UART_CONTROL_REG);
|
altera_uart_writel(port, 0, ALTERA_UART_CONTROL_REG);
|
||||||
/* Clear status register */
|
/* Clear status register */
|
||||||
writel(0, port->membase + ALTERA_UART_STATUS_REG);
|
altera_uart_writel(port, 0, ALTERA_UART_STATUS_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int altera_uart_startup(struct uart_port *port)
|
static int altera_uart_startup(struct uart_port *port)
|
||||||
|
@ -284,6 +312,12 @@ static int altera_uart_startup(struct uart_port *port)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!port->irq) {
|
||||||
|
setup_timer(&pp->tmr, altera_uart_timer, (unsigned long)port);
|
||||||
|
mod_timer(&pp->tmr, jiffies + uart_poll_timeout(port));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
|
ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED,
|
||||||
DRV_NAME, port);
|
DRV_NAME, port);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -316,7 +350,10 @@ static void altera_uart_shutdown(struct uart_port *port)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
|
|
||||||
free_irq(port->irq, port);
|
if (port->irq)
|
||||||
|
free_irq(port->irq, port);
|
||||||
|
else
|
||||||
|
del_timer_sync(&pp->tmr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *altera_uart_type(struct uart_port *port)
|
static const char *altera_uart_type(struct uart_port *port)
|
||||||
|
@ -384,8 +421,9 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
|
||||||
port->iotype = SERIAL_IO_MEM;
|
port->iotype = SERIAL_IO_MEM;
|
||||||
port->irq = platp[i].irq;
|
port->irq = platp[i].irq;
|
||||||
port->uartclk = platp[i].uartclk;
|
port->uartclk = platp[i].uartclk;
|
||||||
port->flags = ASYNC_BOOT_AUTOCONF;
|
port->flags = UPF_BOOT_AUTOCONF;
|
||||||
port->ops = &altera_uart_ops;
|
port->ops = &altera_uart_ops;
|
||||||
|
port->private_data = platp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -393,7 +431,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
|
||||||
|
|
||||||
static void altera_uart_console_putc(struct uart_port *port, const char c)
|
static void altera_uart_console_putc(struct uart_port *port, const char c)
|
||||||
{
|
{
|
||||||
while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
|
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||||
ALTERA_UART_STATUS_TRDY_MSK))
|
ALTERA_UART_STATUS_TRDY_MSK))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
|
||||||
|
@ -423,7 +461,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options)
|
||||||
if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
|
if (co->index < 0 || co->index >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
port = &altera_uart_ports[co->index].port;
|
port = &altera_uart_ports[co->index].port;
|
||||||
if (port->membase == 0)
|
if (!port->membase)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (options)
|
if (options)
|
||||||
|
@ -435,7 +473,7 @@ static int __init altera_uart_console_setup(struct console *co, char *options)
|
||||||
static struct uart_driver altera_uart_driver;
|
static struct uart_driver altera_uart_driver;
|
||||||
|
|
||||||
static struct console altera_uart_console = {
|
static struct console altera_uart_console = {
|
||||||
.name = "ttyS",
|
.name = "ttyAL",
|
||||||
.write = altera_uart_console_write,
|
.write = altera_uart_console_write,
|
||||||
.device = uart_console_device,
|
.device = uart_console_device,
|
||||||
.setup = altera_uart_console_setup,
|
.setup = altera_uart_console_setup,
|
||||||
|
@ -466,9 +504,9 @@ console_initcall(altera_uart_console_init);
|
||||||
static struct uart_driver altera_uart_driver = {
|
static struct uart_driver altera_uart_driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.driver_name = DRV_NAME,
|
.driver_name = DRV_NAME,
|
||||||
.dev_name = "ttyS",
|
.dev_name = "ttyAL",
|
||||||
.major = TTY_MAJOR,
|
.major = SERIAL_ALTERA_MAJOR,
|
||||||
.minor = 64,
|
.minor = SERIAL_ALTERA_MINOR,
|
||||||
.nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
|
.nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
|
||||||
.cons = ALTERA_UART_CONSOLE,
|
.cons = ALTERA_UART_CONSOLE,
|
||||||
};
|
};
|
||||||
|
@ -477,38 +515,55 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
|
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
|
||||||
struct uart_port *port;
|
struct uart_port *port;
|
||||||
int i;
|
struct resource *res_mem;
|
||||||
|
struct resource *res_irq;
|
||||||
|
int i = pdev->id;
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS && platp[i].mapbase; i++) {
|
/* -1 emphasizes that the platform must have one port, no .N suffix */
|
||||||
port = &altera_uart_ports[i].port;
|
if (i == -1)
|
||||||
|
i = 0;
|
||||||
|
|
||||||
port->line = i;
|
if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
|
||||||
port->type = PORT_ALTERA_UART;
|
return -EINVAL;
|
||||||
port->mapbase = platp[i].mapbase;
|
|
||||||
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
|
|
||||||
port->iotype = SERIAL_IO_MEM;
|
|
||||||
port->irq = platp[i].irq;
|
|
||||||
port->uartclk = platp[i].uartclk;
|
|
||||||
port->ops = &altera_uart_ops;
|
|
||||||
port->flags = ASYNC_BOOT_AUTOCONF;
|
|
||||||
|
|
||||||
uart_add_one_port(&altera_uart_driver, port);
|
port = &altera_uart_ports[i].port;
|
||||||
}
|
|
||||||
|
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (res_mem)
|
||||||
|
port->mapbase = res_mem->start;
|
||||||
|
else if (platp->mapbase)
|
||||||
|
port->mapbase = platp->mapbase;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||||
|
if (res_irq)
|
||||||
|
port->irq = res_irq->start;
|
||||||
|
else if (platp->irq)
|
||||||
|
port->irq = platp->irq;
|
||||||
|
|
||||||
|
port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
|
||||||
|
if (!port->membase)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
port->line = i;
|
||||||
|
port->type = PORT_ALTERA_UART;
|
||||||
|
port->iotype = SERIAL_IO_MEM;
|
||||||
|
port->uartclk = platp->uartclk;
|
||||||
|
port->ops = &altera_uart_ops;
|
||||||
|
port->flags = UPF_BOOT_AUTOCONF;
|
||||||
|
port->private_data = platp;
|
||||||
|
|
||||||
|
uart_add_one_port(&altera_uart_driver, port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devexit altera_uart_remove(struct platform_device *pdev)
|
static int __devexit altera_uart_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct uart_port *port;
|
struct uart_port *port = &altera_uart_ports[pdev->id].port;
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_SERIAL_ALTERA_UART_MAXPORTS; i++) {
|
|
||||||
port = &altera_uart_ports[i].port;
|
|
||||||
if (port)
|
|
||||||
uart_remove_one_port(&altera_uart_driver, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
uart_remove_one_port(&altera_uart_driver, port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,3 +605,4 @@ MODULE_DESCRIPTION("Altera UART driver");
|
||||||
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
|
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS("platform:" DRV_NAME);
|
MODULE_ALIAS("platform:" DRV_NAME);
|
||||||
|
MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_ALTERA_MAJOR);
|
||||||
|
|
|
@ -131,7 +131,12 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
|
||||||
pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
|
pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
|
||||||
|
|
||||||
tclkdiv = sclk / (2 * baud_rate) - 1;
|
tclkdiv = sclk / (2 * baud_rate) - 1;
|
||||||
rclkdiv = sclk / (2 * baud_rate * 2) - 1;
|
/* The actual uart baud rate of devices vary between +/-2%. The sport
|
||||||
|
* RX sample rate should be faster than the double of the worst case,
|
||||||
|
* otherwise, wrong data are received. So, set sport RX clock to be
|
||||||
|
* 3% faster.
|
||||||
|
*/
|
||||||
|
rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1;
|
||||||
SPORT_PUT_TCLKDIV(up, tclkdiv);
|
SPORT_PUT_TCLKDIV(up, tclkdiv);
|
||||||
SPORT_PUT_RCLKDIV(up, rclkdiv);
|
SPORT_PUT_RCLKDIV(up, rclkdiv);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
|
|
|
@ -327,14 +327,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
||||||
{
|
{
|
||||||
struct circ_buf *xmit = &sport->port.state->xmit;
|
struct circ_buf *xmit = &sport->port.state->xmit;
|
||||||
|
|
||||||
while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
|
while (!uart_circ_empty(xmit) &&
|
||||||
|
!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
|
||||||
/* send xmit->buf[xmit->tail]
|
/* send xmit->buf[xmit->tail]
|
||||||
* out the port here */
|
* out the port here */
|
||||||
writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
|
writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||||
sport->port.icount.tx++;
|
sport->port.icount.tx++;
|
||||||
if (uart_circ_empty(xmit))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||||
|
|
|
@ -172,13 +172,15 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device
|
||||||
jsm_uart_port_init here! */
|
jsm_uart_port_init here! */
|
||||||
dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
|
dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out_free_irq;
|
goto out_free_uart;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_set_drvdata(pdev, brd);
|
pci_set_drvdata(pdev, brd);
|
||||||
pci_save_state(pdev);
|
pci_save_state(pdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
out_free_uart:
|
||||||
|
jsm_remove_uart_port(brd);
|
||||||
out_free_irq:
|
out_free_irq:
|
||||||
jsm_remove_uart_port(brd);
|
jsm_remove_uart_port(brd);
|
||||||
free_irq(brd->irq, brd);
|
free_irq(brd->irq, brd);
|
||||||
|
|
|
@ -986,12 +986,14 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
|
s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL);
|
||||||
if (!s->rxbuf) {
|
if (!s->rxbuf) {
|
||||||
pr_err("Allocating RX buffer failed\n");
|
pr_err("Allocating RX buffer failed\n");
|
||||||
return -ENOMEM;
|
retval = -ENOMEM;
|
||||||
|
goto err_free4;
|
||||||
}
|
}
|
||||||
s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
|
s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL);
|
||||||
if (!s->rxstr) {
|
if (!s->rxstr) {
|
||||||
pr_err("Allocating RX buffer failed\n");
|
pr_err("Allocating RX buffer failed\n");
|
||||||
return -ENOMEM;
|
retval = -ENOMEM;
|
||||||
|
goto err_free3;
|
||||||
}
|
}
|
||||||
/* SPI Tx buffer
|
/* SPI Tx buffer
|
||||||
* SPI transfer buffer
|
* SPI transfer buffer
|
||||||
|
@ -1002,7 +1004,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
|
s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL);
|
||||||
if (!s->txbuf) {
|
if (!s->txbuf) {
|
||||||
pr_err("Allocating TX buffer failed\n");
|
pr_err("Allocating TX buffer failed\n");
|
||||||
return -ENOMEM;
|
retval = -ENOMEM;
|
||||||
|
goto err_free2;
|
||||||
}
|
}
|
||||||
/* Initialize shared data lock */
|
/* Initialize shared data lock */
|
||||||
spin_lock_init(&s->data_lock);
|
spin_lock_init(&s->data_lock);
|
||||||
|
@ -1021,13 +1024,15 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
buf[0] = MAX3107_REVID_REG;
|
buf[0] = MAX3107_REVID_REG;
|
||||||
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
|
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
|
||||||
dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
|
dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n");
|
||||||
return -EIO;
|
retval = -EIO;
|
||||||
|
goto err_free1;
|
||||||
}
|
}
|
||||||
if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
|
if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 &&
|
||||||
(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
|
(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
|
||||||
dev_err(&s->spi->dev, "REVID %x does not match\n",
|
dev_err(&s->spi->dev, "REVID %x does not match\n",
|
||||||
(buf[0] & MAX3107_SPI_RX_DATA_MASK));
|
(buf[0] & MAX3107_SPI_RX_DATA_MASK));
|
||||||
return -ENODEV;
|
retval = -ENODEV;
|
||||||
|
goto err_free1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
@ -1047,7 +1052,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
/* Perform SPI transfer */
|
/* Perform SPI transfer */
|
||||||
if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
|
if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
|
||||||
dev_err(&s->spi->dev, "SPI transfer for init failed\n");
|
dev_err(&s->spi->dev, "SPI transfer for init failed\n");
|
||||||
return -EIO;
|
retval = -EIO;
|
||||||
|
goto err_free1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register UART driver */
|
/* Register UART driver */
|
||||||
|
@ -1055,7 +1061,7 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
retval = uart_register_driver(&max3107_uart_driver);
|
retval = uart_register_driver(&max3107_uart_driver);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
dev_err(&s->spi->dev, "Registering UART driver failed\n");
|
dev_err(&s->spi->dev, "Registering UART driver failed\n");
|
||||||
return retval;
|
goto err_free1;
|
||||||
}
|
}
|
||||||
driver_registered = 1;
|
driver_registered = 1;
|
||||||
}
|
}
|
||||||
|
@ -1074,13 +1080,13 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
retval = uart_add_one_port(&max3107_uart_driver, &s->port);
|
retval = uart_add_one_port(&max3107_uart_driver, &s->port);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
dev_err(&s->spi->dev, "Adding UART port failed\n");
|
dev_err(&s->spi->dev, "Adding UART port failed\n");
|
||||||
return retval;
|
goto err_free1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdata->configure) {
|
if (pdata->configure) {
|
||||||
retval = pdata->configure(s);
|
retval = pdata->configure(s);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
goto err_free1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go to suspend mode */
|
/* Go to suspend mode */
|
||||||
|
@ -1088,6 +1094,16 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
||||||
pdata->hw_suspend(s, 1);
|
pdata->hw_suspend(s, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_free1:
|
||||||
|
kfree(s->txbuf);
|
||||||
|
err_free2:
|
||||||
|
kfree(s->rxstr);
|
||||||
|
err_free3:
|
||||||
|
kfree(s->rxbuf);
|
||||||
|
err_free4:
|
||||||
|
kfree(s);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(max3107_probe);
|
EXPORT_SYMBOL_GPL(max3107_probe);
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,9 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf,
|
||||||
len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
|
len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
|
||||||
"DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
|
"DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
|
||||||
|
|
||||||
|
if (len > HSU_REGS_BUFSIZE)
|
||||||
|
len = HSU_REGS_BUFSIZE;
|
||||||
|
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -219,6 +222,9 @@ static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
|
||||||
len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
|
len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
|
||||||
"D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
|
"D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
|
||||||
|
|
||||||
|
if (len > HSU_REGS_BUFSIZE)
|
||||||
|
len = HSU_REGS_BUFSIZE;
|
||||||
|
|
||||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -925,39 +931,52 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
cval |= UART_LCR_EPAR;
|
cval |= UART_LCR_EPAR;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* The base clk is 50Mhz, and the baud rate come from:
|
||||||
|
* baud = 50M * MUL / (DIV * PS * DLAB)
|
||||||
|
*
|
||||||
* For those basic low baud rate we can get the direct
|
* For those basic low baud rate we can get the direct
|
||||||
* scalar from 2746800, like 115200 = 2746800/24, for those
|
* scalar from 2746800, like 115200 = 2746800/24. For those
|
||||||
* higher baud rate, we have to handle them case by case,
|
* higher baud rate, we handle them case by case, mainly by
|
||||||
* but DIV reg is never touched as its default value 0x3d09
|
* adjusting the MUL/PS registers, and DIV register is kept
|
||||||
|
* as default value 0x3d09 to make things simple
|
||||||
*/
|
*/
|
||||||
baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
|
baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
|
||||||
quot = uart_get_divisor(port, baud);
|
|
||||||
|
|
||||||
|
quot = 1;
|
||||||
switch (baud) {
|
switch (baud) {
|
||||||
case 3500000:
|
case 3500000:
|
||||||
mul = 0x3345;
|
mul = 0x3345;
|
||||||
ps = 0xC;
|
ps = 0xC;
|
||||||
quot = 1;
|
break;
|
||||||
|
case 3000000:
|
||||||
|
mul = 0x2EE0;
|
||||||
break;
|
break;
|
||||||
case 2500000:
|
case 2500000:
|
||||||
mul = 0x2710;
|
mul = 0x2710;
|
||||||
ps = 0x10;
|
|
||||||
quot = 1;
|
|
||||||
break;
|
break;
|
||||||
case 18432000:
|
case 2000000:
|
||||||
|
mul = 0x1F40;
|
||||||
|
break;
|
||||||
|
case 1843200:
|
||||||
mul = 0x2400;
|
mul = 0x2400;
|
||||||
ps = 0x10;
|
|
||||||
quot = 1;
|
|
||||||
break;
|
break;
|
||||||
case 1500000:
|
case 1500000:
|
||||||
mul = 0x1D4C;
|
mul = 0x1770;
|
||||||
ps = 0xc;
|
break;
|
||||||
quot = 1;
|
case 1000000:
|
||||||
|
mul = 0xFA0;
|
||||||
|
break;
|
||||||
|
case 500000:
|
||||||
|
mul = 0x7D0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
/* Use uart_get_divisor to get quot for other baud rates */
|
||||||
|
quot = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!quot)
|
||||||
|
quot = uart_get_divisor(port, baud);
|
||||||
|
|
||||||
if ((up->port.uartclk / quot) < (2400 * 16))
|
if ((up->port.uartclk / quot) < (2400 * 16))
|
||||||
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
|
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
|
||||||
else if ((up->port.uartclk / quot) < (230400 * 16))
|
else if ((up->port.uartclk / quot) < (230400 * 16))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown
|
* mrst_max3110.c - spi uart protocol driver for Maxim 3110
|
||||||
*
|
*
|
||||||
* Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com>
|
* Copyright (c) 2008-2010, Intel Corporation.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
@ -32,18 +32,13 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/sysrq.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/tty_flip.h>
|
#include <linux/tty_flip.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
|
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <asm/atomic.h>
|
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/spi/dw_spi.h>
|
|
||||||
|
|
||||||
#include "mrst_max3110.h"
|
#include "mrst_max3110.h"
|
||||||
|
|
||||||
|
@ -56,7 +51,7 @@
|
||||||
struct uart_max3110 {
|
struct uart_max3110 {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
struct spi_device *spi;
|
struct spi_device *spi;
|
||||||
char *name;
|
char name[24];
|
||||||
|
|
||||||
wait_queue_head_t wq;
|
wait_queue_head_t wq;
|
||||||
struct task_struct *main_thread;
|
struct task_struct *main_thread;
|
||||||
|
@ -67,35 +62,30 @@ struct uart_max3110 {
|
||||||
u16 cur_conf;
|
u16 cur_conf;
|
||||||
u8 clock;
|
u8 clock;
|
||||||
u8 parity, word_7bits;
|
u8 parity, word_7bits;
|
||||||
|
u16 irq;
|
||||||
|
|
||||||
unsigned long uart_flags;
|
unsigned long uart_flags;
|
||||||
|
|
||||||
/* console related */
|
/* console related */
|
||||||
struct circ_buf con_xmit;
|
struct circ_buf con_xmit;
|
||||||
|
|
||||||
/* irq related */
|
|
||||||
u16 irq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* global data structure, may need be removed */
|
/* global data structure, may need be removed */
|
||||||
struct uart_max3110 *pmax;
|
static struct uart_max3110 *pmax;
|
||||||
static inline void receive_char(struct uart_max3110 *max, u8 ch);
|
|
||||||
static void receive_chars(struct uart_max3110 *max,
|
static void receive_chars(struct uart_max3110 *max,
|
||||||
unsigned char *str, int len);
|
unsigned char *str, int len);
|
||||||
static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf);
|
static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
|
||||||
static void max3110_console_receive(struct uart_max3110 *max);
|
static void max3110_con_receive(struct uart_max3110 *max);
|
||||||
|
|
||||||
int max3110_write_then_read(struct uart_max3110 *max,
|
static int max3110_write_then_read(struct uart_max3110 *max,
|
||||||
const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
|
const void *txbuf, void *rxbuf, unsigned len, int always_fast)
|
||||||
{
|
{
|
||||||
struct spi_device *spi = max->spi;
|
struct spi_device *spi = max->spi;
|
||||||
struct spi_message message;
|
struct spi_message message;
|
||||||
struct spi_transfer x;
|
struct spi_transfer x;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!txbuf || !rxbuf)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
spi_message_init(&message);
|
spi_message_init(&message);
|
||||||
memset(&x, 0, sizeof x);
|
memset(&x, 0, sizeof x);
|
||||||
x.len = len;
|
x.len = len;
|
||||||
|
@ -104,7 +94,7 @@ int max3110_write_then_read(struct uart_max3110 *max,
|
||||||
spi_message_add_tail(&x, &message);
|
spi_message_add_tail(&x, &message);
|
||||||
|
|
||||||
if (always_fast)
|
if (always_fast)
|
||||||
x.speed_hz = 3125000;
|
x.speed_hz = spi->max_speed_hz;
|
||||||
else if (max->baud)
|
else if (max->baud)
|
||||||
x.speed_hz = max->baud;
|
x.speed_hz = max->baud;
|
||||||
|
|
||||||
|
@ -113,58 +103,80 @@ int max3110_write_then_read(struct uart_max3110 *max,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a u16 to the device, and return one u16 read back */
|
/* Write a 16b word to the device */
|
||||||
int max3110_out(struct uart_max3110 *max, const u16 out)
|
static int max3110_out(struct uart_max3110 *max, const u16 out)
|
||||||
{
|
{
|
||||||
u16 tmp;
|
void *buf;
|
||||||
|
u16 *obuf, *ibuf;
|
||||||
|
u8 ch;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1);
|
buf = kzalloc(8, GFP_KERNEL | GFP_DMA);
|
||||||
if (ret)
|
if (!buf)
|
||||||
return ret;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
obuf = buf;
|
||||||
|
ibuf = buf + 4;
|
||||||
|
*obuf = out;
|
||||||
|
ret = max3110_write_then_read(max, obuf, ibuf, 2, 1);
|
||||||
|
if (ret) {
|
||||||
|
pr_warning(PR_FMT "%s(): get err msg %d when sending 0x%x\n",
|
||||||
|
__func__, ret, out);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* If some valid data is read back */
|
/* If some valid data is read back */
|
||||||
if (tmp & MAX3110_READ_DATA_AVAILABLE)
|
if (*ibuf & MAX3110_READ_DATA_AVAILABLE) {
|
||||||
receive_char(max, (tmp & 0xff));
|
ch = *ibuf & 0xff;
|
||||||
|
receive_chars(max, &ch, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_READ_LEN 20
|
|
||||||
/*
|
/*
|
||||||
* This is usually used to read data from SPIC RX FIFO, which doesn't
|
* This is usually used to read data from SPIC RX FIFO, which doesn't
|
||||||
* need any delay like flushing character out. It returns how many
|
* need any delay like flushing character out.
|
||||||
* valide bytes are read back
|
*
|
||||||
|
* Return how many valide bytes are read back
|
||||||
*/
|
*/
|
||||||
static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf)
|
static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf)
|
||||||
{
|
{
|
||||||
u16 out[MAX_READ_LEN], in[MAX_READ_LEN];
|
void *buf;
|
||||||
u8 *pbuf, valid_str[MAX_READ_LEN];
|
u16 *obuf, *ibuf;
|
||||||
int i, j, bytelen;
|
u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
|
||||||
|
int i, j, blen;
|
||||||
|
|
||||||
if (len > MAX_READ_LEN) {
|
blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
|
||||||
pr_err(PR_FMT "read len %d is too large\n", len);
|
buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
|
||||||
|
if (!buf) {
|
||||||
|
pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytelen = len * 2;
|
/* tx/rx always have the same length */
|
||||||
memset(out, 0, bytelen);
|
obuf = buf;
|
||||||
memset(in, 0, bytelen);
|
ibuf = buf + blen;
|
||||||
|
|
||||||
if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1))
|
if (max3110_write_then_read(max, obuf, ibuf, blen, 1)) {
|
||||||
|
kfree(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If caller don't provide a buffer, then handle received char */
|
/* If caller doesn't provide a buffer, then handle received char */
|
||||||
pbuf = buf ? buf : valid_str;
|
pbuf = rxbuf ? rxbuf : valid_str;
|
||||||
|
|
||||||
for (i = 0, j = 0; i < len; i++) {
|
for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) {
|
||||||
if (in[i] & MAX3110_READ_DATA_AVAILABLE)
|
if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
|
||||||
pbuf[j++] = (u8)(in[i] & 0xff);
|
pbuf[j++] = ibuf[i] & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j && (pbuf == valid_str))
|
if (j && (pbuf == valid_str))
|
||||||
receive_chars(max, valid_str, j);
|
receive_chars(max, valid_str, j);
|
||||||
|
|
||||||
|
kfree(buf);
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,10 +190,6 @@ static void serial_m3110_con_putchar(struct uart_port *port, int ch)
|
||||||
xmit->buf[xmit->head] = (char)ch;
|
xmit->buf[xmit->head] = (char)ch;
|
||||||
xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1);
|
xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags))
|
|
||||||
wake_up_process(max->main_thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -197,6 +205,9 @@ static void serial_m3110_con_write(struct console *co,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
|
uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar);
|
||||||
|
|
||||||
|
if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags))
|
||||||
|
wake_up_process(pmax->main_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init
|
static int __init
|
||||||
|
@ -210,6 +221,9 @@ serial_m3110_con_setup(struct console *co, char *options)
|
||||||
|
|
||||||
pr_info(PR_FMT "setting up console\n");
|
pr_info(PR_FMT "setting up console\n");
|
||||||
|
|
||||||
|
if (co->index == -1)
|
||||||
|
co->index = 0;
|
||||||
|
|
||||||
if (!max) {
|
if (!max) {
|
||||||
pr_err(PR_FMT "pmax is NULL, return");
|
pr_err(PR_FMT "pmax is NULL, return");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -240,8 +254,6 @@ static struct console serial_m3110_console = {
|
||||||
.data = &serial_m3110_reg,
|
.data = &serial_m3110_reg,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MRST_CONSOLE (&serial_m3110_console)
|
|
||||||
|
|
||||||
static unsigned int serial_m3110_tx_empty(struct uart_port *port)
|
static unsigned int serial_m3110_tx_empty(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -259,32 +271,44 @@ static void serial_m3110_stop_rx(struct uart_port *port)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WORDS_PER_XFER 128
|
#define WORDS_PER_XFER 128
|
||||||
static inline void send_circ_buf(struct uart_max3110 *max,
|
static void send_circ_buf(struct uart_max3110 *max,
|
||||||
struct circ_buf *xmit)
|
struct circ_buf *xmit)
|
||||||
{
|
{
|
||||||
int len, left = 0;
|
void *buf;
|
||||||
u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER];
|
u16 *obuf, *ibuf;
|
||||||
u8 valid_str[WORDS_PER_XFER];
|
u8 valid_str[WORDS_PER_XFER];
|
||||||
int i, j;
|
int i, j, len, blen, dma_size, left, ret = 0;
|
||||||
|
|
||||||
|
|
||||||
|
dma_size = WORDS_PER_XFER * sizeof(u16) * 2;
|
||||||
|
buf = kzalloc(dma_size, GFP_KERNEL | GFP_DMA);
|
||||||
|
if (!buf)
|
||||||
|
return;
|
||||||
|
obuf = buf;
|
||||||
|
ibuf = buf + dma_size/2;
|
||||||
|
|
||||||
while (!uart_circ_empty(xmit)) {
|
while (!uart_circ_empty(xmit)) {
|
||||||
left = uart_circ_chars_pending(xmit);
|
left = uart_circ_chars_pending(xmit);
|
||||||
while (left) {
|
while (left) {
|
||||||
len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left;
|
len = min(left, WORDS_PER_XFER);
|
||||||
|
blen = len * sizeof(u16);
|
||||||
|
memset(ibuf, 0, blen);
|
||||||
|
|
||||||
memset(obuf, 0, len * 2);
|
|
||||||
memset(ibuf, 0, len * 2);
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
|
obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
|
||||||
xmit->tail = (xmit->tail + 1) &
|
xmit->tail = (xmit->tail + 1) &
|
||||||
(UART_XMIT_SIZE - 1);
|
(UART_XMIT_SIZE - 1);
|
||||||
}
|
}
|
||||||
max3110_write_then_read(max, (u8 *)obuf,
|
|
||||||
(u8 *)ibuf, len * 2, 0);
|
/* Fail to send msg to console is not very critical */
|
||||||
|
ret = max3110_write_then_read(max, obuf, ibuf, blen, 0);
|
||||||
|
if (ret)
|
||||||
|
pr_warning(PR_FMT "%s(): get err msg %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
|
||||||
for (i = 0, j = 0; i < len; i++) {
|
for (i = 0, j = 0; i < len; i++) {
|
||||||
if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
|
if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
|
||||||
valid_str[j++] = (u8)(ibuf[i] & 0xff);
|
valid_str[j++] = ibuf[i] & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j)
|
if (j)
|
||||||
|
@ -294,6 +318,8 @@ static inline void send_circ_buf(struct uart_max3110 *max,
|
||||||
left -= len;
|
left -= len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void transmit_char(struct uart_max3110 *max)
|
static void transmit_char(struct uart_max3110 *max)
|
||||||
|
@ -313,8 +339,10 @@ static void transmit_char(struct uart_max3110 *max)
|
||||||
serial_m3110_stop_tx(port);
|
serial_m3110_stop_tx(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This will be called by uart_write() and tty_write, can't
|
/*
|
||||||
* go to sleep */
|
* This will be called by uart_write() and tty_write, can't
|
||||||
|
* go to sleep
|
||||||
|
*/
|
||||||
static void serial_m3110_start_tx(struct uart_port *port)
|
static void serial_m3110_start_tx(struct uart_port *port)
|
||||||
{
|
{
|
||||||
struct uart_max3110 *max =
|
struct uart_max3110 *max =
|
||||||
|
@ -336,7 +364,7 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len)
|
||||||
|
|
||||||
tty = port->state->port.tty;
|
tty = port->state->port.tty;
|
||||||
if (!tty)
|
if (!tty)
|
||||||
return; /* receive some char before the tty is opened */
|
return;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
usable = tty_buffer_request_room(tty, len);
|
usable = tty_buffer_request_room(tty, len);
|
||||||
|
@ -344,32 +372,37 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len)
|
||||||
tty_insert_flip_string(tty, str, usable);
|
tty_insert_flip_string(tty, str, usable);
|
||||||
str += usable;
|
str += usable;
|
||||||
port->icount.rx += usable;
|
port->icount.rx += usable;
|
||||||
tty_flip_buffer_push(tty);
|
|
||||||
}
|
}
|
||||||
len -= usable;
|
len -= usable;
|
||||||
}
|
}
|
||||||
|
tty_flip_buffer_push(tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void receive_char(struct uart_max3110 *max, u8 ch)
|
/*
|
||||||
{
|
* This routine will be used in read_thread or RX IRQ handling,
|
||||||
receive_chars(max, &ch, 1);
|
* it will first do one round buffer read(8 words), if there is some
|
||||||
}
|
* valid RX data, will try to read 5 more rounds till all data
|
||||||
|
* is read out.
|
||||||
static void max3110_console_receive(struct uart_max3110 *max)
|
*
|
||||||
|
* Use stack space as data buffer to save some system load, and chose
|
||||||
|
* 504 Btyes as a threadhold to do a bulk push to upper tty layer when
|
||||||
|
* receiving bulk data, a much bigger buffer may cause stack overflow
|
||||||
|
*/
|
||||||
|
static void max3110_con_receive(struct uart_max3110 *max)
|
||||||
{
|
{
|
||||||
int loop = 1, num, total = 0;
|
int loop = 1, num, total = 0;
|
||||||
u8 recv_buf[512], *pbuf;
|
u8 recv_buf[512], *pbuf;
|
||||||
|
|
||||||
pbuf = recv_buf;
|
pbuf = recv_buf;
|
||||||
do {
|
do {
|
||||||
num = max3110_read_multi(max, 8, pbuf);
|
num = max3110_read_multi(max, pbuf);
|
||||||
|
|
||||||
if (num) {
|
if (num) {
|
||||||
loop = 10;
|
loop = 5;
|
||||||
pbuf += num;
|
pbuf += num;
|
||||||
total += num;
|
total += num;
|
||||||
|
|
||||||
if (total >= 500) {
|
if (total >= 504) {
|
||||||
receive_chars(max, recv_buf, total);
|
receive_chars(max, recv_buf, total);
|
||||||
pbuf = recv_buf;
|
pbuf = recv_buf;
|
||||||
total = 0;
|
total = 0;
|
||||||
|
@ -397,7 +430,7 @@ static int max3110_main_thread(void *_max)
|
||||||
mutex_lock(&max->thread_mutex);
|
mutex_lock(&max->thread_mutex);
|
||||||
|
|
||||||
if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
|
if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
|
||||||
max3110_console_receive(max);
|
max3110_con_receive(max);
|
||||||
|
|
||||||
/* first handle console output */
|
/* first handle console output */
|
||||||
if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
|
if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
|
||||||
|
@ -414,7 +447,6 @@ static int max3110_main_thread(void *_max)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MRST_MAX3110_IRQ
|
|
||||||
static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
|
static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct uart_max3110 *max = dev_id;
|
struct uart_max3110 *max = dev_id;
|
||||||
|
@ -426,7 +458,7 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id)
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* if don't use RX IRQ, then need a thread to polling read */
|
/* if don't use RX IRQ, then need a thread to polling read */
|
||||||
static int max3110_read_thread(void *_max)
|
static int max3110_read_thread(void *_max)
|
||||||
{
|
{
|
||||||
|
@ -434,9 +466,14 @@ static int max3110_read_thread(void *_max)
|
||||||
|
|
||||||
pr_info(PR_FMT "start read thread\n");
|
pr_info(PR_FMT "start read thread\n");
|
||||||
do {
|
do {
|
||||||
mutex_lock(&max->thread_mutex);
|
/*
|
||||||
max3110_console_receive(max);
|
* If can't acquire the mutex, it means the main thread
|
||||||
mutex_unlock(&max->thread_mutex);
|
* is running which will also perform the rx job
|
||||||
|
*/
|
||||||
|
if (mutex_trylock(&max->thread_mutex)) {
|
||||||
|
max3110_con_receive(max);
|
||||||
|
mutex_unlock(&max->thread_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
schedule_timeout(HZ / 20);
|
schedule_timeout(HZ / 20);
|
||||||
|
@ -444,7 +481,6 @@ static int max3110_read_thread(void *_max)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int serial_m3110_startup(struct uart_port *port)
|
static int serial_m3110_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
|
@ -453,33 +489,54 @@ static int serial_m3110_startup(struct uart_port *port)
|
||||||
u16 config = 0;
|
u16 config = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (port->line != 0)
|
if (port->line != 0) {
|
||||||
pr_err(PR_FMT "uart port startup failed\n");
|
pr_err(PR_FMT "uart port startup failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* firstly disable all IRQ and config it to 115200, 8n1 */
|
/* Disable all IRQ and config it to 115200, 8n1 */
|
||||||
config = WC_TAG | WC_FIFO_ENABLE
|
config = WC_TAG | WC_FIFO_ENABLE
|
||||||
| WC_1_STOPBITS
|
| WC_1_STOPBITS
|
||||||
| WC_8BIT_WORD
|
| WC_8BIT_WORD
|
||||||
| WC_BAUD_DR2;
|
| WC_BAUD_DR2;
|
||||||
ret = max3110_out(max, config);
|
|
||||||
|
|
||||||
/* as we use thread to handle tx/rx, need set low latency */
|
/* as we use thread to handle tx/rx, need set low latency */
|
||||||
port->state->port.tty->low_latency = 1;
|
port->state->port.tty->low_latency = 1;
|
||||||
|
|
||||||
#ifdef CONFIG_MRST_MAX3110_IRQ
|
if (max->irq) {
|
||||||
ret = request_irq(max->irq, serial_m3110_irq,
|
max->read_thread = NULL;
|
||||||
|
ret = request_irq(max->irq, serial_m3110_irq,
|
||||||
IRQ_TYPE_EDGE_FALLING, "max3110", max);
|
IRQ_TYPE_EDGE_FALLING, "max3110", max);
|
||||||
if (ret)
|
if (ret) {
|
||||||
return ret;
|
max->irq = 0;
|
||||||
|
pr_err(PR_FMT "unable to allocate IRQ, polling\n");
|
||||||
|
} else {
|
||||||
|
/* Enable RX IRQ only */
|
||||||
|
config |= WC_RXA_IRQ_ENABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* enable RX IRQ only */
|
if (max->irq == 0) {
|
||||||
config |= WC_RXA_IRQ_ENABLE;
|
/* If IRQ is disabled, start a read thread for input data */
|
||||||
max3110_out(max, config);
|
max->read_thread =
|
||||||
#else
|
kthread_run(max3110_read_thread, max, "max3110_read");
|
||||||
/* if IRQ is disabled, start a read thread for input data */
|
if (IS_ERR(max->read_thread)) {
|
||||||
max->read_thread =
|
ret = PTR_ERR(max->read_thread);
|
||||||
kthread_run(max3110_read_thread, max, "max3110_read");
|
max->read_thread = NULL;
|
||||||
#endif
|
pr_err(PR_FMT "Can't create read thread!\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = max3110_out(max, config);
|
||||||
|
if (ret) {
|
||||||
|
if (max->irq)
|
||||||
|
free_irq(max->irq, max);
|
||||||
|
if (max->read_thread)
|
||||||
|
kthread_stop(max->read_thread);
|
||||||
|
max->read_thread = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
max->cur_conf = config;
|
max->cur_conf = config;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -496,9 +553,8 @@ static void serial_m3110_shutdown(struct uart_port *port)
|
||||||
max->read_thread = NULL;
|
max->read_thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MRST_MAX3110_IRQ
|
if (max->irq)
|
||||||
free_irq(max->irq, max);
|
free_irq(max->irq, max);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Disable interrupts from this port */
|
/* Disable interrupts from this port */
|
||||||
config = WC_TAG | WC_SW_SHDI;
|
config = WC_TAG | WC_SW_SHDI;
|
||||||
|
@ -516,8 +572,7 @@ static int serial_m3110_request_port(struct uart_port *port)
|
||||||
|
|
||||||
static void serial_m3110_config_port(struct uart_port *port, int flags)
|
static void serial_m3110_config_port(struct uart_port *port, int flags)
|
||||||
{
|
{
|
||||||
/* give it fake type */
|
port->type = PORT_MAX3100;
|
||||||
port->type = PORT_PXA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -552,6 +607,9 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
new_conf |= WC_7BIT_WORD;
|
new_conf |= WC_7BIT_WORD;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* We only support CS7 & CS8 */
|
||||||
|
termios->c_cflag &= ~CSIZE;
|
||||||
|
termios->c_cflag |= CS8;
|
||||||
case CS8:
|
case CS8:
|
||||||
cval = UART_LCR_WLEN8;
|
cval = UART_LCR_WLEN8;
|
||||||
new_conf |= WC_8BIT_WORD;
|
new_conf |= WC_8BIT_WORD;
|
||||||
|
@ -560,7 +618,7 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
|
||||||
baud = uart_get_baud_rate(port, termios, old, 0, 230400);
|
baud = uart_get_baud_rate(port, termios, old, 0, 230400);
|
||||||
|
|
||||||
/* first calc the div for 1.8MHZ clock case */
|
/* First calc the div for 1.8MHZ clock case */
|
||||||
switch (baud) {
|
switch (baud) {
|
||||||
case 300:
|
case 300:
|
||||||
clk_div = WC_BAUD_DR384;
|
clk_div = WC_BAUD_DR384;
|
||||||
|
@ -596,7 +654,7 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
if (max->clock & MAX3110_HIGH_CLK)
|
if (max->clock & MAX3110_HIGH_CLK)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* pick the previous baud rate */
|
/* Pick the previous baud rate */
|
||||||
baud = max->baud;
|
baud = max->baud;
|
||||||
clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
|
clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
|
||||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||||
|
@ -604,15 +662,21 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
|
||||||
if (max->clock & MAX3110_HIGH_CLK) {
|
if (max->clock & MAX3110_HIGH_CLK) {
|
||||||
clk_div += 1;
|
clk_div += 1;
|
||||||
/* high clk version max3110 doesn't support B300 */
|
/* High clk version max3110 doesn't support B300 */
|
||||||
if (baud == 300)
|
if (baud == 300) {
|
||||||
baud = 600;
|
baud = 600;
|
||||||
|
clk_div = WC_BAUD_DR384;
|
||||||
|
}
|
||||||
if (baud == 230400)
|
if (baud == 230400)
|
||||||
clk_div = WC_BAUD_DR1;
|
clk_div = WC_BAUD_DR1;
|
||||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div;
|
new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div;
|
||||||
|
|
||||||
|
if (unlikely(termios->c_cflag & CMSPAR))
|
||||||
|
termios->c_cflag &= ~CMSPAR;
|
||||||
|
|
||||||
if (termios->c_cflag & CSTOPB)
|
if (termios->c_cflag & CSTOPB)
|
||||||
new_conf |= WC_2_STOPBITS;
|
new_conf |= WC_2_STOPBITS;
|
||||||
else
|
else
|
||||||
|
@ -632,13 +696,14 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||||
|
|
||||||
new_conf |= WC_TAG;
|
new_conf |= WC_TAG;
|
||||||
if (new_conf != max->cur_conf) {
|
if (new_conf != max->cur_conf) {
|
||||||
max3110_out(max, new_conf);
|
if (!max3110_out(max, new_conf)) {
|
||||||
max->cur_conf = new_conf;
|
max->cur_conf = new_conf;
|
||||||
max->baud = baud;
|
max->baud = baud;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't handle hw handshaking */
|
/* Don't handle hw handshaking */
|
||||||
static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
|
static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
|
return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
|
||||||
|
@ -672,7 +737,7 @@ struct uart_ops serial_m3110_ops = {
|
||||||
.break_ctl = serial_m3110_break_ctl,
|
.break_ctl = serial_m3110_break_ctl,
|
||||||
.startup = serial_m3110_startup,
|
.startup = serial_m3110_startup,
|
||||||
.shutdown = serial_m3110_shutdown,
|
.shutdown = serial_m3110_shutdown,
|
||||||
.set_termios = serial_m3110_set_termios, /* must have */
|
.set_termios = serial_m3110_set_termios,
|
||||||
.pm = serial_m3110_pm,
|
.pm = serial_m3110_pm,
|
||||||
.type = serial_m3110_type,
|
.type = serial_m3110_type,
|
||||||
.release_port = serial_m3110_release_port,
|
.release_port = serial_m3110_release_port,
|
||||||
|
@ -688,52 +753,60 @@ static struct uart_driver serial_m3110_reg = {
|
||||||
.major = TTY_MAJOR,
|
.major = TTY_MAJOR,
|
||||||
.minor = 64,
|
.minor = 64,
|
||||||
.nr = 1,
|
.nr = 1,
|
||||||
.cons = MRST_CONSOLE,
|
.cons = &serial_m3110_console,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
|
static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
|
||||||
{
|
{
|
||||||
|
struct uart_max3110 *max = spi_get_drvdata(spi);
|
||||||
|
|
||||||
|
disable_irq(max->irq);
|
||||||
|
uart_suspend_port(&serial_m3110_reg, &max->port);
|
||||||
|
max3110_out(max, max->cur_conf | WC_SW_SHDI);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_m3110_resume(struct spi_device *spi)
|
static int serial_m3110_resume(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
|
struct uart_max3110 *max = spi_get_drvdata(spi);
|
||||||
|
|
||||||
|
max3110_out(max, max->cur_conf);
|
||||||
|
uart_resume_port(&serial_m3110_reg, &max->port);
|
||||||
|
enable_irq(max->irq);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define serial_m3110_suspend NULL
|
||||||
|
#define serial_m3110_resume NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct dw_spi_chip spi0_uart = {
|
static int __devinit serial_m3110_probe(struct spi_device *spi)
|
||||||
.poll_mode = 1,
|
|
||||||
.enable_dma = 0,
|
|
||||||
.type = SPI_FRF_SPI,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int serial_m3110_probe(struct spi_device *spi)
|
|
||||||
{
|
{
|
||||||
struct uart_max3110 *max;
|
struct uart_max3110 *max;
|
||||||
int ret;
|
void *buffer;
|
||||||
unsigned char *buffer;
|
|
||||||
u16 res;
|
u16 res;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
max = kzalloc(sizeof(*max), GFP_KERNEL);
|
max = kzalloc(sizeof(*max), GFP_KERNEL);
|
||||||
if (!max)
|
if (!max)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* set spi info */
|
/* Set spi info */
|
||||||
spi->mode = SPI_MODE_0;
|
|
||||||
spi->bits_per_word = 16;
|
spi->bits_per_word = 16;
|
||||||
max->clock = MAX3110_HIGH_CLK;
|
max->clock = MAX3110_HIGH_CLK;
|
||||||
spi->controller_data = &spi0_uart;
|
|
||||||
|
|
||||||
spi_setup(spi);
|
spi_setup(spi);
|
||||||
|
|
||||||
max->port.type = PORT_PXA; /* need apply for a max3110 type */
|
max->port.type = PORT_MAX3100;
|
||||||
max->port.fifosize = 2; /* only have 16b buffer */
|
max->port.fifosize = 2; /* Only have 16b buffer */
|
||||||
max->port.ops = &serial_m3110_ops;
|
max->port.ops = &serial_m3110_ops;
|
||||||
max->port.line = 0;
|
max->port.line = 0;
|
||||||
max->port.dev = &spi->dev;
|
max->port.dev = &spi->dev;
|
||||||
max->port.uartclk = 115200;
|
max->port.uartclk = 115200;
|
||||||
|
|
||||||
max->spi = spi;
|
max->spi = spi;
|
||||||
max->name = spi->modalias; /* use spi name as the name */
|
strcpy(max->name, spi->modalias);
|
||||||
max->irq = (u16)spi->irq;
|
max->irq = (u16)spi->irq;
|
||||||
|
|
||||||
mutex_init(&max->thread_mutex);
|
mutex_init(&max->thread_mutex);
|
||||||
|
@ -755,13 +828,15 @@ static int serial_m3110_probe(struct spi_device *spi)
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_get_page;
|
goto err_get_page;
|
||||||
}
|
}
|
||||||
buffer = (unsigned char *)__get_free_page(GFP_KERNEL);
|
|
||||||
|
buffer = (void *)__get_free_page(GFP_KERNEL);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_get_page;
|
goto err_get_page;
|
||||||
}
|
}
|
||||||
max->con_xmit.buf = (unsigned char *)buffer;
|
max->con_xmit.buf = buffer;
|
||||||
max->con_xmit.head = max->con_xmit.tail = 0;
|
max->con_xmit.head = 0;
|
||||||
|
max->con_xmit.tail = 0;
|
||||||
|
|
||||||
max->main_thread = kthread_run(max3110_main_thread,
|
max->main_thread = kthread_run(max3110_main_thread,
|
||||||
max, "max3110_main");
|
max, "max3110_main");
|
||||||
|
@ -770,8 +845,10 @@ static int serial_m3110_probe(struct spi_device *spi)
|
||||||
goto err_kthread;
|
goto err_kthread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spi_set_drvdata(spi, max);
|
||||||
pmax = max;
|
pmax = max;
|
||||||
/* give membase a psudo value to pass serial_core's check */
|
|
||||||
|
/* Give membase a psudo value to pass serial_core's check */
|
||||||
max->port.membase = (void *)0xff110000;
|
max->port.membase = (void *)0xff110000;
|
||||||
uart_add_one_port(&serial_m3110_reg, &max->port);
|
uart_add_one_port(&serial_m3110_reg, &max->port);
|
||||||
|
|
||||||
|
@ -780,19 +857,17 @@ static int serial_m3110_probe(struct spi_device *spi)
|
||||||
err_kthread:
|
err_kthread:
|
||||||
free_page((unsigned long)buffer);
|
free_page((unsigned long)buffer);
|
||||||
err_get_page:
|
err_get_page:
|
||||||
pmax = NULL;
|
|
||||||
kfree(max);
|
kfree(max);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max3110_remove(struct spi_device *dev)
|
static int __devexit serial_m3110_remove(struct spi_device *dev)
|
||||||
{
|
{
|
||||||
struct uart_max3110 *max = pmax;
|
struct uart_max3110 *max = spi_get_drvdata(dev);
|
||||||
|
|
||||||
if (!pmax)
|
if (!max)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pmax = NULL;
|
|
||||||
uart_remove_one_port(&serial_m3110_reg, &max->port);
|
uart_remove_one_port(&serial_m3110_reg, &max->port);
|
||||||
|
|
||||||
free_page((unsigned long)max->con_xmit.buf);
|
free_page((unsigned long)max->con_xmit.buf);
|
||||||
|
@ -811,13 +886,12 @@ static struct spi_driver uart_max3110_driver = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.probe = serial_m3110_probe,
|
.probe = serial_m3110_probe,
|
||||||
.remove = __devexit_p(max3110_remove),
|
.remove = __devexit_p(serial_m3110_remove),
|
||||||
.suspend = serial_m3110_suspend,
|
.suspend = serial_m3110_suspend,
|
||||||
.resume = serial_m3110_resume,
|
.resume = serial_m3110_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int __init serial_m3110_init(void)
|
||||||
int __init serial_m3110_init(void)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -832,7 +906,7 @@ int __init serial_m3110_init(void)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __exit serial_m3110_exit(void)
|
static void __exit serial_m3110_exit(void)
|
||||||
{
|
{
|
||||||
spi_unregister_driver(&uart_max3110_driver);
|
spi_unregister_driver(&uart_max3110_driver);
|
||||||
uart_unregister_driver(&serial_m3110_reg);
|
uart_unregister_driver(&serial_m3110_reg);
|
||||||
|
@ -841,5 +915,5 @@ void __exit serial_m3110_exit(void)
|
||||||
module_init(serial_m3110_init);
|
module_init(serial_m3110_init);
|
||||||
module_exit(serial_m3110_exit);
|
module_exit(serial_m3110_exit);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_ALIAS("max3110-uart");
|
MODULE_ALIAS("max3110-uart");
|
||||||
|
|
|
@ -56,4 +56,5 @@
|
||||||
#define WC_BAUD_DR192 (0xE)
|
#define WC_BAUD_DR192 (0xE)
|
||||||
#define WC_BAUD_DR384 (0xF)
|
#define WC_BAUD_DR384 (0xF)
|
||||||
|
|
||||||
|
#define M3110_RX_FIFO_DEPTH 8
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1074,10 +1074,10 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
|
||||||
* NB: both 1->0 and 0->1 transitions are counted except for
|
* NB: both 1->0 and 0->1 transitions are counted except for
|
||||||
* RI where only 0->1 is counted.
|
* RI where only 0->1 is counted.
|
||||||
*/
|
*/
|
||||||
static int uart_get_count(struct uart_state *state,
|
static int uart_get_icount(struct tty_struct *tty,
|
||||||
struct serial_icounter_struct __user *icnt)
|
struct serial_icounter_struct *icount)
|
||||||
{
|
{
|
||||||
struct serial_icounter_struct icount;
|
struct uart_state *state = tty->driver_data;
|
||||||
struct uart_icount cnow;
|
struct uart_icount cnow;
|
||||||
struct uart_port *uport = state->uart_port;
|
struct uart_port *uport = state->uart_port;
|
||||||
|
|
||||||
|
@ -1085,19 +1085,19 @@ static int uart_get_count(struct uart_state *state,
|
||||||
memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
|
memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
|
||||||
spin_unlock_irq(&uport->lock);
|
spin_unlock_irq(&uport->lock);
|
||||||
|
|
||||||
icount.cts = cnow.cts;
|
icount->cts = cnow.cts;
|
||||||
icount.dsr = cnow.dsr;
|
icount->dsr = cnow.dsr;
|
||||||
icount.rng = cnow.rng;
|
icount->rng = cnow.rng;
|
||||||
icount.dcd = cnow.dcd;
|
icount->dcd = cnow.dcd;
|
||||||
icount.rx = cnow.rx;
|
icount->rx = cnow.rx;
|
||||||
icount.tx = cnow.tx;
|
icount->tx = cnow.tx;
|
||||||
icount.frame = cnow.frame;
|
icount->frame = cnow.frame;
|
||||||
icount.overrun = cnow.overrun;
|
icount->overrun = cnow.overrun;
|
||||||
icount.parity = cnow.parity;
|
icount->parity = cnow.parity;
|
||||||
icount.brk = cnow.brk;
|
icount->brk = cnow.brk;
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
ret = uart_wait_modem_status(state, arg);
|
ret = uart_wait_modem_status(state, arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
ret = uart_get_count(state, uarg);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != -ENOIOCTLCMD)
|
if (ret != -ENOIOCTLCMD)
|
||||||
|
@ -2065,7 +2061,19 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
|
||||||
/*
|
/*
|
||||||
* Re-enable the console device after suspending.
|
* Re-enable the console device after suspending.
|
||||||
*/
|
*/
|
||||||
if (uart_console(uport)) {
|
if (console_suspend_enabled && uart_console(uport)) {
|
||||||
|
/*
|
||||||
|
* First try to use the console cflag setting.
|
||||||
|
*/
|
||||||
|
memset(&termios, 0, sizeof(struct ktermios));
|
||||||
|
termios.c_cflag = uport->cons->cflag;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If that's unset, use the tty termios setting.
|
||||||
|
*/
|
||||||
|
if (port->tty && port->tty->termios && termios.c_cflag == 0)
|
||||||
|
termios = *(port->tty->termios);
|
||||||
|
|
||||||
uart_change_pm(state, 0);
|
uart_change_pm(state, 0);
|
||||||
uport->ops->set_termios(uport, &termios, NULL);
|
uport->ops->set_termios(uport, &termios, NULL);
|
||||||
console_start(uport->cons);
|
console_start(uport->cons);
|
||||||
|
@ -2283,6 +2291,7 @@ static const struct tty_operations uart_ops = {
|
||||||
#endif
|
#endif
|
||||||
.tiocmget = uart_tiocmget,
|
.tiocmget = uart_tiocmget,
|
||||||
.tiocmset = uart_tiocmset,
|
.tiocmset = uart_tiocmset,
|
||||||
|
.get_icount = uart_get_icount,
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
.poll_init = uart_poll_init,
|
.poll_init = uart_poll_init,
|
||||||
.poll_get_char = uart_poll_get_char,
|
.poll_get_char = uart_poll_get_char,
|
||||||
|
|
|
@ -322,6 +322,26 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
static int ulite_get_poll_char(struct uart_port *port)
|
||||||
|
{
|
||||||
|
if (!(ioread32be(port->membase + ULITE_STATUS)
|
||||||
|
& ULITE_STATUS_RXVALID))
|
||||||
|
return NO_POLL_CHAR;
|
||||||
|
|
||||||
|
return ioread32be(port->membase + ULITE_RX);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ulite_put_poll_char(struct uart_port *port, unsigned char ch)
|
||||||
|
{
|
||||||
|
while (ioread32be(port->membase + ULITE_STATUS) & ULITE_STATUS_TXFULL)
|
||||||
|
cpu_relax();
|
||||||
|
|
||||||
|
/* write char to device */
|
||||||
|
iowrite32be(ch, port->membase + ULITE_TX);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct uart_ops ulite_ops = {
|
static struct uart_ops ulite_ops = {
|
||||||
.tx_empty = ulite_tx_empty,
|
.tx_empty = ulite_tx_empty,
|
||||||
.set_mctrl = ulite_set_mctrl,
|
.set_mctrl = ulite_set_mctrl,
|
||||||
|
@ -338,7 +358,11 @@ static struct uart_ops ulite_ops = {
|
||||||
.release_port = ulite_release_port,
|
.release_port = ulite_release_port,
|
||||||
.request_port = ulite_request_port,
|
.request_port = ulite_request_port,
|
||||||
.config_port = ulite_config_port,
|
.config_port = ulite_config_port,
|
||||||
.verify_port = ulite_verify_port
|
.verify_port = ulite_verify_port,
|
||||||
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
|
.poll_get_char = ulite_get_poll_char,
|
||||||
|
.poll_put_char = ulite_put_poll_char,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
|
|
|
@ -411,6 +411,26 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ark3116_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct ark3116_private *priv = usb_get_serial_port_data(port);
|
||||||
|
struct async_icount cnow = priv->icount;
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
|
static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -460,25 +480,6 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TIOCGICOUNT: {
|
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
struct async_icount cnow = priv->icount;
|
|
||||||
memset(&icount, 0, sizeof(icount));
|
|
||||||
icount.cts = cnow.cts;
|
|
||||||
icount.dsr = cnow.dsr;
|
|
||||||
icount.rng = cnow.rng;
|
|
||||||
icount.dcd = cnow.dcd;
|
|
||||||
icount.rx = cnow.rx;
|
|
||||||
icount.tx = cnow.tx;
|
|
||||||
icount.frame = cnow.frame;
|
|
||||||
icount.overrun = cnow.overrun;
|
|
||||||
icount.parity = cnow.parity;
|
|
||||||
icount.brk = cnow.brk;
|
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
|
||||||
if (copy_to_user(user_arg, &icount, sizeof(icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -736,6 +737,7 @@ static struct usb_serial_driver ark3116_device = {
|
||||||
.ioctl = ark3116_ioctl,
|
.ioctl = ark3116_ioctl,
|
||||||
.tiocmget = ark3116_tiocmget,
|
.tiocmget = ark3116_tiocmget,
|
||||||
.tiocmset = ark3116_tiocmset,
|
.tiocmset = ark3116_tiocmset,
|
||||||
|
.get_icount = ark3116_get_icount,
|
||||||
.open = ark3116_open,
|
.open = ark3116_open,
|
||||||
.close = ark3116_close,
|
.close = ark3116_close,
|
||||||
.break_ctl = ark3116_break_ctl,
|
.break_ctl = ark3116_break_ctl,
|
||||||
|
|
|
@ -2168,6 +2168,7 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
* - mask passed in arg for lines of interest
|
* - mask passed in arg for lines of interest
|
||||||
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
|
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
|
||||||
* Caller should use TIOCGICOUNT to see which one it was.
|
* Caller should use TIOCGICOUNT to see which one it was.
|
||||||
|
* (except that the driver doesn't support it !)
|
||||||
*
|
*
|
||||||
* This code is borrowed from linux/drivers/char/serial.c
|
* This code is borrowed from linux/drivers/char/serial.c
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -222,6 +222,8 @@ static void edge_break(struct tty_struct *tty, int break_state);
|
||||||
static int edge_tiocmget(struct tty_struct *tty, struct file *file);
|
static int edge_tiocmget(struct tty_struct *tty, struct file *file);
|
||||||
static int edge_tiocmset(struct tty_struct *tty, struct file *file,
|
static int edge_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
|
static int edge_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount);
|
||||||
static int edge_startup(struct usb_serial *serial);
|
static int edge_startup(struct usb_serial *serial);
|
||||||
static void edge_disconnect(struct usb_serial *serial);
|
static void edge_disconnect(struct usb_serial *serial);
|
||||||
static void edge_release(struct usb_serial *serial);
|
static void edge_release(struct usb_serial *serial);
|
||||||
|
@ -1624,6 +1626,31 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int edge_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
|
||||||
|
struct async_icount cnow;
|
||||||
|
cnow = edge_port->icount;
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
|
||||||
|
__func__, port->number, icount->rx, icount->tx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_serial_info(struct edgeport_port *edge_port,
|
static int get_serial_info(struct edgeport_port *edge_port,
|
||||||
struct serial_struct __user *retinfo)
|
struct serial_struct __user *retinfo)
|
||||||
{
|
{
|
||||||
|
@ -1650,7 +1677,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* SerialIoctl
|
* SerialIoctl
|
||||||
* this function handles any ioctl calls to the driver
|
* this function handles any ioctl calls to the driver
|
||||||
|
@ -1663,7 +1689,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
|
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
|
||||||
struct async_icount cnow;
|
struct async_icount cnow;
|
||||||
struct async_icount cprev;
|
struct async_icount cprev;
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
|
|
||||||
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
|
dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
|
||||||
|
|
||||||
|
@ -1702,26 +1727,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
cnow = edge_port->icount;
|
|
||||||
memset(&icount, 0, sizeof(icount));
|
|
||||||
icount.cts = cnow.cts;
|
|
||||||
icount.dsr = cnow.dsr;
|
|
||||||
icount.rng = cnow.rng;
|
|
||||||
icount.dcd = cnow.dcd;
|
|
||||||
icount.rx = cnow.rx;
|
|
||||||
icount.tx = cnow.tx;
|
|
||||||
icount.frame = cnow.frame;
|
|
||||||
icount.overrun = cnow.overrun;
|
|
||||||
icount.parity = cnow.parity;
|
|
||||||
icount.brk = cnow.brk;
|
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
|
||||||
|
|
||||||
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
|
|
||||||
__func__, port->number, icount.rx, icount.tx);
|
|
||||||
if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ static struct usb_serial_driver edgeport_2port_device = {
|
||||||
.set_termios = edge_set_termios,
|
.set_termios = edge_set_termios,
|
||||||
.tiocmget = edge_tiocmget,
|
.tiocmget = edge_tiocmget,
|
||||||
.tiocmset = edge_tiocmset,
|
.tiocmset = edge_tiocmset,
|
||||||
|
.get_icount = edge_get_icount,
|
||||||
.write = edge_write,
|
.write = edge_write,
|
||||||
.write_room = edge_write_room,
|
.write_room = edge_write_room,
|
||||||
.chars_in_buffer = edge_chars_in_buffer,
|
.chars_in_buffer = edge_chars_in_buffer,
|
||||||
|
@ -152,6 +153,7 @@ static struct usb_serial_driver edgeport_4port_device = {
|
||||||
.set_termios = edge_set_termios,
|
.set_termios = edge_set_termios,
|
||||||
.tiocmget = edge_tiocmget,
|
.tiocmget = edge_tiocmget,
|
||||||
.tiocmset = edge_tiocmset,
|
.tiocmset = edge_tiocmset,
|
||||||
|
.get_icount = edge_get_icount,
|
||||||
.write = edge_write,
|
.write = edge_write,
|
||||||
.write_room = edge_write_room,
|
.write_room = edge_write_room,
|
||||||
.chars_in_buffer = edge_chars_in_buffer,
|
.chars_in_buffer = edge_chars_in_buffer,
|
||||||
|
@ -181,6 +183,7 @@ static struct usb_serial_driver edgeport_8port_device = {
|
||||||
.set_termios = edge_set_termios,
|
.set_termios = edge_set_termios,
|
||||||
.tiocmget = edge_tiocmget,
|
.tiocmget = edge_tiocmget,
|
||||||
.tiocmset = edge_tiocmset,
|
.tiocmset = edge_tiocmset,
|
||||||
|
.get_icount = edge_get_icount,
|
||||||
.write = edge_write,
|
.write = edge_write,
|
||||||
.write_room = edge_write_room,
|
.write_room = edge_write_room,
|
||||||
.chars_in_buffer = edge_chars_in_buffer,
|
.chars_in_buffer = edge_chars_in_buffer,
|
||||||
|
@ -209,6 +212,7 @@ static struct usb_serial_driver epic_device = {
|
||||||
.set_termios = edge_set_termios,
|
.set_termios = edge_set_termios,
|
||||||
.tiocmget = edge_tiocmget,
|
.tiocmget = edge_tiocmget,
|
||||||
.tiocmset = edge_tiocmset,
|
.tiocmset = edge_tiocmset,
|
||||||
|
.get_icount = edge_get_icount,
|
||||||
.write = edge_write,
|
.write = edge_write,
|
||||||
.write_room = edge_write_room,
|
.write_room = edge_write_room,
|
||||||
.chars_in_buffer = edge_chars_in_buffer,
|
.chars_in_buffer = edge_chars_in_buffer,
|
||||||
|
|
|
@ -2510,6 +2510,27 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int edge_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
|
||||||
|
struct async_icount *ic = &edge_port->icount;
|
||||||
|
|
||||||
|
icount->cts = ic->cts;
|
||||||
|
icount->dsr = ic->dsr;
|
||||||
|
icount->rng = ic->rng;
|
||||||
|
icount->dcd = ic->dcd;
|
||||||
|
icount->tx = ic->tx;
|
||||||
|
icount->rx = ic->rx;
|
||||||
|
icount->frame = ic->frame;
|
||||||
|
icount->parity = ic->parity;
|
||||||
|
icount->overrun = ic->overrun;
|
||||||
|
icount->brk = ic->brk;
|
||||||
|
icount->buf_overrun = ic->buf_overrun;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_serial_info(struct edgeport_port *edge_port,
|
static int get_serial_info(struct edgeport_port *edge_port,
|
||||||
struct serial_struct __user *retinfo)
|
struct serial_struct __user *retinfo)
|
||||||
{
|
{
|
||||||
|
@ -2572,13 +2593,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
}
|
}
|
||||||
/* not reached */
|
/* not reached */
|
||||||
break;
|
break;
|
||||||
case TIOCGICOUNT:
|
|
||||||
dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
|
|
||||||
port->number, edge_port->icount.rx, edge_port->icount.tx);
|
|
||||||
if (copy_to_user((void __user *)arg, &edge_port->icount,
|
|
||||||
sizeof(edge_port->icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
@ -2758,6 +2772,7 @@ static struct usb_serial_driver edgeport_1port_device = {
|
||||||
.set_termios = edge_set_termios,
|
.set_termios = edge_set_termios,
|
||||||
.tiocmget = edge_tiocmget,
|
.tiocmget = edge_tiocmget,
|
||||||
.tiocmset = edge_tiocmset,
|
.tiocmset = edge_tiocmset,
|
||||||
|
.get_icount = edge_get_icount,
|
||||||
.write = edge_write,
|
.write = edge_write,
|
||||||
.write_room = edge_write_room,
|
.write_room = edge_write_room,
|
||||||
.chars_in_buffer = edge_chars_in_buffer,
|
.chars_in_buffer = edge_chars_in_buffer,
|
||||||
|
|
|
@ -1896,10 +1896,37 @@ static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mos7720_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct moschip_port *mos7720_port;
|
||||||
|
struct async_icount cnow;
|
||||||
|
|
||||||
|
mos7720_port = usb_get_serial_port_data(port);
|
||||||
|
cnow = mos7720_port->icount;
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
|
||||||
|
port->number, icount->rx, icount->tx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
|
static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
|
||||||
unsigned int __user *value)
|
unsigned int __user *value)
|
||||||
{
|
{
|
||||||
unsigned int mcr ;
|
unsigned int mcr;
|
||||||
unsigned int arg;
|
unsigned int arg;
|
||||||
|
|
||||||
struct usb_serial_port *port;
|
struct usb_serial_port *port;
|
||||||
|
@ -1973,7 +2000,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
struct moschip_port *mos7720_port;
|
struct moschip_port *mos7720_port;
|
||||||
struct async_icount cnow;
|
struct async_icount cnow;
|
||||||
struct async_icount cprev;
|
struct async_icount cprev;
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
|
|
||||||
mos7720_port = usb_get_serial_port_data(port);
|
mos7720_port = usb_get_serial_port_data(port);
|
||||||
if (mos7720_port == NULL)
|
if (mos7720_port == NULL)
|
||||||
|
@ -2021,29 +2047,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
cnow = mos7720_port->icount;
|
|
||||||
|
|
||||||
memset(&icount, 0, sizeof(struct serial_icounter_struct));
|
|
||||||
|
|
||||||
icount.cts = cnow.cts;
|
|
||||||
icount.dsr = cnow.dsr;
|
|
||||||
icount.rng = cnow.rng;
|
|
||||||
icount.dcd = cnow.dcd;
|
|
||||||
icount.rx = cnow.rx;
|
|
||||||
icount.tx = cnow.tx;
|
|
||||||
icount.frame = cnow.frame;
|
|
||||||
icount.overrun = cnow.overrun;
|
|
||||||
icount.parity = cnow.parity;
|
|
||||||
icount.brk = cnow.brk;
|
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
|
||||||
|
|
||||||
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
|
|
||||||
port->number, icount.rx, icount.tx);
|
|
||||||
if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -2212,6 +2215,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
|
||||||
.ioctl = mos7720_ioctl,
|
.ioctl = mos7720_ioctl,
|
||||||
.tiocmget = mos7720_tiocmget,
|
.tiocmget = mos7720_tiocmget,
|
||||||
.tiocmset = mos7720_tiocmset,
|
.tiocmset = mos7720_tiocmset,
|
||||||
|
.get_icount = mos7720_get_icount,
|
||||||
.set_termios = mos7720_set_termios,
|
.set_termios = mos7720_set_termios,
|
||||||
.write = mos7720_write,
|
.write = mos7720_write,
|
||||||
.write_room = mos7720_write_room,
|
.write_room = mos7720_write_room,
|
||||||
|
|
|
@ -2209,6 +2209,34 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mos7840_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct moschip_port *mos7840_port;
|
||||||
|
struct async_icount cnow;
|
||||||
|
|
||||||
|
mos7840_port = mos7840_get_port_private(port);
|
||||||
|
cnow = mos7840_port->icount;
|
||||||
|
|
||||||
|
smp_rmb();
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
|
||||||
|
port->number, icount->rx, icount->tx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* SerialIoctl
|
* SerialIoctl
|
||||||
* this function handles any ioctl calls to the driver
|
* this function handles any ioctl calls to the driver
|
||||||
|
@ -2223,7 +2251,6 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
|
||||||
struct async_icount cnow;
|
struct async_icount cnow;
|
||||||
struct async_icount cprev;
|
struct async_icount cprev;
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
|
|
||||||
if (mos7840_port_paranoia_check(port, __func__)) {
|
if (mos7840_port_paranoia_check(port, __func__)) {
|
||||||
dbg("%s", "Invalid port");
|
dbg("%s", "Invalid port");
|
||||||
|
@ -2282,29 +2309,6 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
cnow = mos7840_port->icount;
|
|
||||||
smp_rmb();
|
|
||||||
|
|
||||||
memset(&icount, 0, sizeof(struct serial_icounter_struct));
|
|
||||||
|
|
||||||
icount.cts = cnow.cts;
|
|
||||||
icount.dsr = cnow.dsr;
|
|
||||||
icount.rng = cnow.rng;
|
|
||||||
icount.dcd = cnow.dcd;
|
|
||||||
icount.rx = cnow.rx;
|
|
||||||
icount.tx = cnow.tx;
|
|
||||||
icount.frame = cnow.frame;
|
|
||||||
icount.overrun = cnow.overrun;
|
|
||||||
icount.parity = cnow.parity;
|
|
||||||
icount.brk = cnow.brk;
|
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
|
||||||
|
|
||||||
dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
|
|
||||||
port->number, icount.rx, icount.tx);
|
|
||||||
if (copy_to_user(argp, &icount, sizeof(icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2674,6 +2678,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
|
||||||
.break_ctl = mos7840_break,
|
.break_ctl = mos7840_break,
|
||||||
.tiocmget = mos7840_tiocmget,
|
.tiocmget = mos7840_tiocmget,
|
||||||
.tiocmset = mos7840_tiocmset,
|
.tiocmset = mos7840_tiocmset,
|
||||||
|
.get_icount = mos7840_get_icount,
|
||||||
.attach = mos7840_startup,
|
.attach = mos7840_startup,
|
||||||
.disconnect = mos7840_disconnect,
|
.disconnect = mos7840_disconnect,
|
||||||
.release = mos7840_release,
|
.release = mos7840_release,
|
||||||
|
|
|
@ -416,12 +416,34 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ssu100_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct ssu100_port_private *priv = usb_get_serial_port_data(port);
|
||||||
|
struct async_icount cnow = priv->icount;
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
|
static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
struct ssu100_port_private *priv = usb_get_serial_port_data(port);
|
|
||||||
void __user *user_arg = (void __user *)arg;
|
|
||||||
|
|
||||||
dbg("%s cmd 0x%04x", __func__, cmd);
|
dbg("%s cmd 0x%04x", __func__, cmd);
|
||||||
|
|
||||||
|
@ -433,27 +455,6 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
case TIOCMIWAIT:
|
case TIOCMIWAIT:
|
||||||
return wait_modem_info(port, arg);
|
return wait_modem_info(port, arg);
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
{
|
|
||||||
struct serial_icounter_struct icount;
|
|
||||||
struct async_icount cnow = priv->icount;
|
|
||||||
memset(&icount, 0, sizeof(icount));
|
|
||||||
icount.cts = cnow.cts;
|
|
||||||
icount.dsr = cnow.dsr;
|
|
||||||
icount.rng = cnow.rng;
|
|
||||||
icount.dcd = cnow.dcd;
|
|
||||||
icount.rx = cnow.rx;
|
|
||||||
icount.tx = cnow.tx;
|
|
||||||
icount.frame = cnow.frame;
|
|
||||||
icount.overrun = cnow.overrun;
|
|
||||||
icount.parity = cnow.parity;
|
|
||||||
icount.brk = cnow.brk;
|
|
||||||
icount.buf_overrun = cnow.buf_overrun;
|
|
||||||
if (copy_to_user(user_arg, &icount, sizeof(icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -726,6 +727,7 @@ static struct usb_serial_driver ssu100_device = {
|
||||||
.process_read_urb = ssu100_process_read_urb,
|
.process_read_urb = ssu100_process_read_urb,
|
||||||
.tiocmget = ssu100_tiocmget,
|
.tiocmget = ssu100_tiocmget,
|
||||||
.tiocmset = ssu100_tiocmset,
|
.tiocmset = ssu100_tiocmset,
|
||||||
|
.get_icount = ssu100_get_icount,
|
||||||
.ioctl = ssu100_ioctl,
|
.ioctl = ssu100_ioctl,
|
||||||
.set_termios = ssu100_set_termios,
|
.set_termios = ssu100_set_termios,
|
||||||
.disconnect = usb_serial_generic_disconnect,
|
.disconnect = usb_serial_generic_disconnect,
|
||||||
|
|
|
@ -108,6 +108,8 @@ static void ti_throttle(struct tty_struct *tty);
|
||||||
static void ti_unthrottle(struct tty_struct *tty);
|
static void ti_unthrottle(struct tty_struct *tty);
|
||||||
static int ti_ioctl(struct tty_struct *tty, struct file *file,
|
static int ti_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg);
|
unsigned int cmd, unsigned long arg);
|
||||||
|
static int ti_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount);
|
||||||
static void ti_set_termios(struct tty_struct *tty,
|
static void ti_set_termios(struct tty_struct *tty,
|
||||||
struct usb_serial_port *port, struct ktermios *old_termios);
|
struct usb_serial_port *port, struct ktermios *old_termios);
|
||||||
static int ti_tiocmget(struct tty_struct *tty, struct file *file);
|
static int ti_tiocmget(struct tty_struct *tty, struct file *file);
|
||||||
|
@ -237,6 +239,7 @@ static struct usb_serial_driver ti_1port_device = {
|
||||||
.set_termios = ti_set_termios,
|
.set_termios = ti_set_termios,
|
||||||
.tiocmget = ti_tiocmget,
|
.tiocmget = ti_tiocmget,
|
||||||
.tiocmset = ti_tiocmset,
|
.tiocmset = ti_tiocmset,
|
||||||
|
.get_icount = ti_get_icount,
|
||||||
.break_ctl = ti_break,
|
.break_ctl = ti_break,
|
||||||
.read_int_callback = ti_interrupt_callback,
|
.read_int_callback = ti_interrupt_callback,
|
||||||
.read_bulk_callback = ti_bulk_in_callback,
|
.read_bulk_callback = ti_bulk_in_callback,
|
||||||
|
@ -265,6 +268,7 @@ static struct usb_serial_driver ti_2port_device = {
|
||||||
.set_termios = ti_set_termios,
|
.set_termios = ti_set_termios,
|
||||||
.tiocmget = ti_tiocmget,
|
.tiocmget = ti_tiocmget,
|
||||||
.tiocmset = ti_tiocmset,
|
.tiocmset = ti_tiocmset,
|
||||||
|
.get_icount = ti_get_icount,
|
||||||
.break_ctl = ti_break,
|
.break_ctl = ti_break,
|
||||||
.read_int_callback = ti_interrupt_callback,
|
.read_int_callback = ti_interrupt_callback,
|
||||||
.read_bulk_callback = ti_bulk_in_callback,
|
.read_bulk_callback = ti_bulk_in_callback,
|
||||||
|
@ -788,6 +792,31 @@ static void ti_unthrottle(struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ti_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
struct ti_port *tport = usb_get_serial_port_data(port);
|
||||||
|
struct async_icount cnow = tport->tp_icount;
|
||||||
|
|
||||||
|
dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
|
||||||
|
__func__, port->number,
|
||||||
|
cnow.rx, cnow.tx);
|
||||||
|
|
||||||
|
icount->cts = cnow.cts;
|
||||||
|
icount->dsr = cnow.dsr;
|
||||||
|
icount->rng = cnow.rng;
|
||||||
|
icount->dcd = cnow.dcd;
|
||||||
|
icount->rx = cnow.rx;
|
||||||
|
icount->tx = cnow.tx;
|
||||||
|
icount->frame = cnow.frame;
|
||||||
|
icount->overrun = cnow.overrun;
|
||||||
|
icount->parity = cnow.parity;
|
||||||
|
icount->brk = cnow.brk;
|
||||||
|
icount->buf_overrun = cnow.buf_overrun;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ti_ioctl(struct tty_struct *tty, struct file *file,
|
static int ti_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
|
@ -830,14 +859,6 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
cprev = cnow;
|
cprev = cnow;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TIOCGICOUNT:
|
|
||||||
dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
|
|
||||||
__func__, port->number,
|
|
||||||
tport->tp_icount.rx, tport->tp_icount.tx);
|
|
||||||
if (copy_to_user((void __user *)arg, &tport->tp_icount,
|
|
||||||
sizeof(tport->tp_icount)))
|
|
||||||
return -EFAULT;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int serial_get_icount(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
|
|
||||||
|
dbg("%s - port %d", __func__, port->number);
|
||||||
|
|
||||||
|
if (port->serial->type->get_icount)
|
||||||
|
return port->serial->type->get_icount(tty, icount);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We would be calling tty_wakeup here, but unfortunately some line
|
* We would be calling tty_wakeup here, but unfortunately some line
|
||||||
* disciplines have an annoying habit of calling tty->write from
|
* disciplines have an annoying habit of calling tty->write from
|
||||||
|
@ -1195,6 +1207,7 @@ static const struct tty_operations serial_ops = {
|
||||||
.chars_in_buffer = serial_chars_in_buffer,
|
.chars_in_buffer = serial_chars_in_buffer,
|
||||||
.tiocmget = serial_tiocmget,
|
.tiocmget = serial_tiocmget,
|
||||||
.tiocmset = serial_tiocmset,
|
.tiocmset = serial_tiocmset,
|
||||||
|
.get_icount = serial_get_icount,
|
||||||
.cleanup = serial_cleanup,
|
.cleanup = serial_cleanup,
|
||||||
.install = serial_install,
|
.install = serial_install,
|
||||||
.proc_fops = &serial_proc_fops,
|
.proc_fops = &serial_proc_fops,
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
|
#include <linux/tty_driver.h>
|
||||||
|
#include <linux/console.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
#include <linux/fdtable.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -136,6 +139,160 @@ static const struct file_operations proc_tty_drivers_operations = {
|
||||||
.release = seq_release,
|
.release = seq_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The device ID of file descriptor 0 of the current reading
|
||||||
|
* task if a character device...
|
||||||
|
*/
|
||||||
|
static dev_t current_dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the handler for /proc/tty/consoles
|
||||||
|
*/
|
||||||
|
static int show_console_dev(struct seq_file *m, void *v)
|
||||||
|
{
|
||||||
|
const struct tty_driver *driver;
|
||||||
|
struct console *con;
|
||||||
|
int index, len;
|
||||||
|
char flags[10];
|
||||||
|
dev_t dev;
|
||||||
|
|
||||||
|
if (v == SEQ_START_TOKEN)
|
||||||
|
return 0;
|
||||||
|
con = (struct console *)v;
|
||||||
|
if (!con)
|
||||||
|
return 0;
|
||||||
|
driver = con->device(con, &index);
|
||||||
|
if (!driver)
|
||||||
|
return 0;
|
||||||
|
dev = MKDEV(driver->major, driver->minor_start) + index;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
if (con->flags & CON_ENABLED)
|
||||||
|
flags[index++] = 'E';
|
||||||
|
if (con->flags & CON_CONSDEV)
|
||||||
|
flags[index++] = 'C';
|
||||||
|
if (con->flags & CON_BOOT)
|
||||||
|
flags[index++] = 'B';
|
||||||
|
if (con->flags & CON_PRINTBUFFER)
|
||||||
|
flags[index++] = 'p';
|
||||||
|
if (con->flags & CON_BRL)
|
||||||
|
flags[index++] = 'b';
|
||||||
|
if (con->flags & CON_ANYTIME)
|
||||||
|
flags[index++] = 'a';
|
||||||
|
if (current_dev == dev)
|
||||||
|
flags[index++] = '*';
|
||||||
|
flags[index] = 0;
|
||||||
|
|
||||||
|
seq_printf(m, "%s%d%n", con->name, con->index, &len);
|
||||||
|
len = 21 - len;
|
||||||
|
if (len < 1)
|
||||||
|
len = 1;
|
||||||
|
seq_printf(m, "%*c", len, ' ');
|
||||||
|
seq_printf(m, "%c%c%c (%s)%n", con->read ? 'R' : '-',
|
||||||
|
con->write ? 'W' : '-', con->unblank ? 'U' : '-',
|
||||||
|
flags, &len);
|
||||||
|
len = 13 - len;
|
||||||
|
if (len < 1)
|
||||||
|
len = 1;
|
||||||
|
seq_printf(m, "%*c%4d:%d\n", len, ' ', MAJOR(dev), MINOR(dev));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iterator for consoles */
|
||||||
|
static void *c_start(struct seq_file *m, loff_t *pos)
|
||||||
|
{
|
||||||
|
struct console *con;
|
||||||
|
loff_t off = 0;
|
||||||
|
|
||||||
|
if (*pos == 0)
|
||||||
|
return SEQ_START_TOKEN;
|
||||||
|
|
||||||
|
acquire_console_sem();
|
||||||
|
for (con = console_drivers; con; con = con->next) {
|
||||||
|
if (!con->device)
|
||||||
|
continue;
|
||||||
|
if (++off == *pos)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
release_console_sem();
|
||||||
|
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
||||||
|
{
|
||||||
|
struct console *con;
|
||||||
|
|
||||||
|
acquire_console_sem();
|
||||||
|
if (v == SEQ_START_TOKEN)
|
||||||
|
con = console_drivers;
|
||||||
|
else
|
||||||
|
con = ((struct console *)v)->next;
|
||||||
|
for (; con; con = con->next) {
|
||||||
|
if (!con->device)
|
||||||
|
continue;
|
||||||
|
++*pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
release_console_sem();
|
||||||
|
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void c_stop(struct seq_file *m, void *v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct seq_operations tty_consoles_op = {
|
||||||
|
.start = c_start,
|
||||||
|
.next = c_next,
|
||||||
|
.stop = c_stop,
|
||||||
|
.show = show_console_dev
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used for open /proc/tty/consoles. Before this detect
|
||||||
|
* the device ID of file descriptor 0 of the current
|
||||||
|
* reading task if a character device...
|
||||||
|
*/
|
||||||
|
static int tty_consoles_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct files_struct *curfiles;
|
||||||
|
|
||||||
|
current_dev = 0;
|
||||||
|
curfiles = get_files_struct(current);
|
||||||
|
if (curfiles) {
|
||||||
|
const struct file *curfp;
|
||||||
|
spin_lock(&curfiles->file_lock);
|
||||||
|
curfp = fcheck_files(curfiles, 0);
|
||||||
|
if (curfp && curfp->private_data) {
|
||||||
|
const struct inode *inode;
|
||||||
|
dget(curfp->f_dentry);
|
||||||
|
inode = curfp->f_dentry->d_inode;
|
||||||
|
if (S_ISCHR(inode->i_mode)) {
|
||||||
|
struct tty_struct *tty;
|
||||||
|
tty = (struct tty_struct *)curfp->private_data;
|
||||||
|
if (tty && tty->magic == TTY_MAGIC) {
|
||||||
|
tty = tty_pair_get_tty(tty);
|
||||||
|
current_dev = tty_devnum(tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dput(curfp->f_dentry);
|
||||||
|
}
|
||||||
|
spin_unlock(&curfiles->file_lock);
|
||||||
|
put_files_struct(curfiles);
|
||||||
|
}
|
||||||
|
return seq_open(file, &tty_consoles_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations proc_tty_consoles_operations = {
|
||||||
|
.open = tty_consoles_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = seq_release,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called by tty_register_driver() to handle
|
* This function is called by tty_register_driver() to handle
|
||||||
* registering the driver's /proc handler into /proc/tty/driver/<foo>
|
* registering the driver's /proc handler into /proc/tty/driver/<foo>
|
||||||
|
@ -186,4 +343,5 @@ void __init proc_tty_init(void)
|
||||||
proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
|
proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
|
||||||
proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
|
proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
|
||||||
proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
|
proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
|
||||||
|
proc_create("tty/consoles", 0, NULL, &proc_tty_consoles_operations);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,9 @@
|
||||||
#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
|
#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
|
||||||
#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
|
#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
|
||||||
#define TIOCGRS485 0x542E
|
#define TIOCGRS485 0x542E
|
||||||
|
#ifndef TIOCSRS485
|
||||||
#define TIOCSRS485 0x542F
|
#define TIOCSRS485 0x542F
|
||||||
|
#endif
|
||||||
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
||||||
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
|
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
|
||||||
#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
|
#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
|
||||||
|
|
|
@ -5,10 +5,15 @@
|
||||||
#ifndef __ALTUART_H
|
#ifndef __ALTUART_H
|
||||||
#define __ALTUART_H
|
#define __ALTUART_H
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
struct altera_uart_platform_uart {
|
struct altera_uart_platform_uart {
|
||||||
unsigned long mapbase; /* Physical address base */
|
unsigned long mapbase; /* Physical address base */
|
||||||
unsigned int irq; /* Interrupt vector */
|
unsigned int irq; /* Interrupt vector */
|
||||||
unsigned int uartclk; /* UART clock rate */
|
unsigned int uartclk; /* UART clock rate */
|
||||||
|
unsigned int bus_shift; /* Bus shift (address stride) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp);
|
||||||
|
|
||||||
#endif /* __ALTUART_H */
|
#endif /* __ALTUART_H */
|
||||||
|
|
|
@ -39,5 +39,6 @@ extern void putconsxy(struct vc_data *vc, unsigned char *p);
|
||||||
|
|
||||||
extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
|
extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org);
|
||||||
extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
|
extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
|
||||||
|
extern void vcs_scr_updated(struct vc_data *vc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,8 @@ struct plat_serial8250_port {
|
||||||
void (*set_termios)(struct uart_port *,
|
void (*set_termios)(struct uart_port *,
|
||||||
struct ktermios *new,
|
struct ktermios *new,
|
||||||
struct ktermios *old);
|
struct ktermios *old);
|
||||||
|
void (*pm)(struct uart_port *, unsigned int state,
|
||||||
|
unsigned old);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -76,5 +78,11 @@ extern int serial8250_find_port_for_earlycon(void);
|
||||||
extern int setup_early_serial8250_console(char *cmdline);
|
extern int setup_early_serial8250_console(char *cmdline);
|
||||||
extern void serial8250_do_set_termios(struct uart_port *port,
|
extern void serial8250_do_set_termios(struct uart_port *port,
|
||||||
struct ktermios *termios, struct ktermios *old);
|
struct ktermios *termios, struct ktermios *old);
|
||||||
|
extern void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
||||||
|
unsigned int oldstate);
|
||||||
|
|
||||||
|
extern void serial8250_set_isa_configurator(void (*v)
|
||||||
|
(int port, struct uart_port *up,
|
||||||
|
unsigned short *capabilities));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -289,6 +289,8 @@ struct uart_port {
|
||||||
void (*set_termios)(struct uart_port *,
|
void (*set_termios)(struct uart_port *,
|
||||||
struct ktermios *new,
|
struct ktermios *new,
|
||||||
struct ktermios *old);
|
struct ktermios *old);
|
||||||
|
void (*pm)(struct uart_port *, unsigned int state,
|
||||||
|
unsigned int old);
|
||||||
unsigned int irq; /* irq number */
|
unsigned int irq; /* irq number */
|
||||||
unsigned long irqflags; /* irq flags */
|
unsigned long irqflags; /* irq flags */
|
||||||
unsigned int uartclk; /* base uart clock */
|
unsigned int uartclk; /* base uart clock */
|
||||||
|
@ -411,6 +413,14 @@ unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios
|
||||||
unsigned int max);
|
unsigned int max);
|
||||||
unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
|
unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud);
|
||||||
|
|
||||||
|
/* Base timer interval for polling */
|
||||||
|
static inline int uart_poll_timeout(struct uart_port *port)
|
||||||
|
{
|
||||||
|
int timeout = port->timeout;
|
||||||
|
|
||||||
|
return timeout > 6 ? (timeout / 2 - 2) : 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Console helpers.
|
* Console helpers.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -256,6 +256,7 @@ struct tty_operations;
|
||||||
struct tty_struct {
|
struct tty_struct {
|
||||||
int magic;
|
int magic;
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
|
struct device *dev;
|
||||||
struct tty_driver *driver;
|
struct tty_driver *driver;
|
||||||
const struct tty_operations *ops;
|
const struct tty_operations *ops;
|
||||||
int index;
|
int index;
|
||||||
|
@ -465,7 +466,7 @@ extern void proc_clear_tty(struct task_struct *p);
|
||||||
extern struct tty_struct *get_current_tty(void);
|
extern struct tty_struct *get_current_tty(void);
|
||||||
extern void tty_default_fops(struct file_operations *fops);
|
extern void tty_default_fops(struct file_operations *fops);
|
||||||
extern struct tty_struct *alloc_tty_struct(void);
|
extern struct tty_struct *alloc_tty_struct(void);
|
||||||
extern void tty_add_file(struct tty_struct *tty, struct file *file);
|
extern int tty_add_file(struct tty_struct *tty, struct file *file);
|
||||||
extern void free_tty_struct(struct tty_struct *tty);
|
extern void free_tty_struct(struct tty_struct *tty);
|
||||||
extern void initialize_tty_struct(struct tty_struct *tty,
|
extern void initialize_tty_struct(struct tty_struct *tty,
|
||||||
struct tty_driver *driver, int idx);
|
struct tty_driver *driver, int idx);
|
||||||
|
|
|
@ -224,6 +224,12 @@
|
||||||
* unless the tty also has a valid tty->termiox pointer.
|
* unless the tty also has a valid tty->termiox pointer.
|
||||||
*
|
*
|
||||||
* Optional: Called under the termios lock
|
* Optional: Called under the termios lock
|
||||||
|
*
|
||||||
|
* int (*get_icount)(struct tty_struct *tty, struct serial_icounter *icount);
|
||||||
|
*
|
||||||
|
* Called when the device receives a TIOCGICOUNT ioctl. Passed a kernel
|
||||||
|
* structure to complete. This method is optional and will only be called
|
||||||
|
* if provided (otherwise EINVAL will be returned).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -232,6 +238,7 @@
|
||||||
|
|
||||||
struct tty_struct;
|
struct tty_struct;
|
||||||
struct tty_driver;
|
struct tty_driver;
|
||||||
|
struct serial_icounter_struct;
|
||||||
|
|
||||||
struct tty_operations {
|
struct tty_operations {
|
||||||
struct tty_struct * (*lookup)(struct tty_driver *driver,
|
struct tty_struct * (*lookup)(struct tty_driver *driver,
|
||||||
|
@ -268,6 +275,8 @@ struct tty_operations {
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
int (*resize)(struct tty_struct *tty, struct winsize *ws);
|
int (*resize)(struct tty_struct *tty, struct winsize *ws);
|
||||||
int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
|
int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
|
||||||
|
int (*get_icount)(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount);
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
int (*poll_init)(struct tty_driver *driver, int line, char *options);
|
int (*poll_init)(struct tty_driver *driver, int line, char *options);
|
||||||
int (*poll_get_char)(struct tty_driver *driver, int line);
|
int (*poll_get_char)(struct tty_driver *driver, int line);
|
||||||
|
|
|
@ -271,6 +271,8 @@ struct usb_serial_driver {
|
||||||
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
int (*tiocmget)(struct tty_struct *tty, struct file *file);
|
||||||
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
int (*tiocmset)(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int set, unsigned int clear);
|
unsigned int set, unsigned int clear);
|
||||||
|
int (*get_icount)(struct tty_struct *tty,
|
||||||
|
struct serial_icounter_struct *icount);
|
||||||
/* Called by the tty layer for port level work. There may or may not
|
/* Called by the tty layer for port level work. There may or may not
|
||||||
be an attached tty at this point */
|
be an attached tty at this point */
|
||||||
void (*dtr_rts)(struct usb_serial_port *port, int on);
|
void (*dtr_rts)(struct usb_serial_port *port, int on);
|
||||||
|
|
|
@ -844,10 +844,6 @@ static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned
|
||||||
BT_DBG("TIOCMIWAIT");
|
BT_DBG("TIOCMIWAIT");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCGICOUNT:
|
|
||||||
BT_DBG("TIOCGICOUNT");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TIOCGSERIAL:
|
case TIOCGSERIAL:
|
||||||
BT_ERR("TIOCGSERIAL is not supported");
|
BT_ERR("TIOCGSERIAL is not supported");
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
|
Loading…
Reference in a new issue