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
|
||||
1 = /dev/console System console
|
||||
2 = /dev/ptmx PTY master multiplex
|
||||
3 = /dev/ttyprintk User messages via printk TTY device
|
||||
64 = /dev/cua0 Callout device for ttyS0
|
||||
...
|
||||
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
|
||||
ldiscs registered line disciplines
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
-------------------------------------------------
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -157,9 +157,11 @@ S: Maintained
|
|||
F: drivers/net/r8169.c
|
||||
|
||||
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
||||
M: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
L: linux-serial@vger.kernel.org
|
||||
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: include/linux/serial_8250.h
|
||||
|
||||
|
@ -3353,6 +3355,12 @@ F: fs/jbd*/
|
|||
F: include/linux/ext*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
|
||||
M: Rudolf Marek <r.marek@assembler.cz>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
|
|
|
@ -1,89 +1,8 @@
|
|||
#ifndef __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
|
||||
|
||||
/* 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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,90 +1,6 @@
|
|||
#ifndef __ASM_AVR32_IOCTLS_H
|
||||
#define __ASM_AVR32_IOCTLS_H
|
||||
|
||||
#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 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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif /* __ASM_AVR32_IOCTLS_H */
|
||||
|
|
|
@ -1,93 +1,11 @@
|
|||
#ifndef __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 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 TIOCSERWRRS485 0x5462 /* write rs-485 */
|
||||
#define TIOCSRS485 0x5463 /* enable rs-485 */
|
||||
#define TIOCGRS485 0x542E /* get rs-485 */
|
||||
|
||||
/* 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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,88 +1,10 @@
|
|||
#ifndef __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 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
|
||||
|
||||
/* 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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif /* __ASM_IOCTLS_H__ */
|
||||
|
||||
|
|
|
@ -1,87 +1,8 @@
|
|||
#ifndef __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
|
||||
|
||||
/* 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 */
|
||||
#include <asm-generic/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) &&
|
||||
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
|
||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -433,16 +433,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
|||
case TIOCMIWAIT:
|
||||
printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
|
||||
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 TIOCSERSWILD:
|
||||
/* "setserial -W" is called in Debian boot */
|
||||
|
|
|
@ -1,93 +1,6 @@
|
|||
#ifndef _ASM_IA64_IOCTLS_H
|
||||
#define _ASM_IA64_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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif /* _ASM_IA64_IOCTLS_H */
|
||||
|
|
|
@ -1,87 +1,6 @@
|
|||
#ifndef __ARCH_M32R_IOCTLS_H__
|
||||
#define __ARCH_M32R_IOCTLS_H__
|
||||
|
||||
#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 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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif /* __ARCH_M32R_IOCTLS_H__ */
|
||||
|
|
|
@ -24,6 +24,33 @@
|
|||
|
||||
#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) \
|
||||
{ \
|
||||
.mapbase = _base, \
|
||||
|
@ -33,6 +60,7 @@
|
|||
.flags = UPF_SKIP_TEST | UPF_IOREMAP | \
|
||||
UPF_FIXED_TYPE, \
|
||||
.type = PORT_16550A, \
|
||||
.pm = alchemy_8250_pm, \
|
||||
}
|
||||
|
||||
static struct plat_serial8250_port au1x00_uart_data[] = {
|
||||
|
|
|
@ -49,11 +49,6 @@
|
|||
* We only have to save/restore registers that aren't otherwise
|
||||
* 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_sys_clocks[5];
|
||||
static unsigned int sleep_sys_pinfunc;
|
||||
|
@ -62,22 +57,6 @@ static unsigned int sleep_static_memctlr[4][3];
|
|||
|
||||
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
|
||||
/* Shutdown USB host/device. */
|
||||
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][1], MEM_STTIME3);
|
||||
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)
|
||||
|
|
|
@ -1,88 +1,6 @@
|
|||
#ifndef _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 - 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 */
|
||||
#include <asm-generic/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__
|
||||
#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
|
||||
|
||||
/* 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 */
|
||||
#include <asm-generic/ioctls.h>
|
||||
|
||||
#endif
|
||||
|
|
|
@ -493,6 +493,21 @@ config LEGACY_PTY_COUNT
|
|||
When not in use, each legacy PTY occupies 12 bytes on 32-bit
|
||||
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
|
||||
tristate 'Total Impact briQ front panel driver'
|
||||
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-$(CONFIG_LEGACY_PTYS) += pty.o
|
||||
obj-$(CONFIG_UNIX98_PTYS) += pty.o
|
||||
obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
|
||||
obj-y += misc.o
|
||||
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
|
@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
|||
}
|
||||
/* 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 TIOCSERSWILD:
|
||||
/* "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,
|
||||
.tiocmget = rs_tiocmget,
|
||||
.tiocmset = rs_tiocmset,
|
||||
.get_icount = rs_get_icount,
|
||||
.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
|
||||
* 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:
|
||||
ret_val = -ENOIOCTLCMD;
|
||||
}
|
||||
|
@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return ret_val;
|
||||
} /* cy_ioctl */
|
||||
|
||||
static int cy_get_icount(struct tty_struct *tty,
|
||||
struct serial_icounter_struct *sic)
|
||||
{
|
||||
struct cyclades_port *info = tty->driver_data;
|
||||
struct cyclades_icount cnow; /* Used to snapshot */
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&info->card->card_lock, flags);
|
||||
cnow = info->icount;
|
||||
spin_unlock_irqrestore(&info->card->card_lock, flags);
|
||||
|
||||
sic->cts = cnow.cts;
|
||||
sic->dsr = cnow.dsr;
|
||||
sic->rng = cnow.rng;
|
||||
sic->dcd = cnow.dcd;
|
||||
sic->rx = cnow.rx;
|
||||
sic->tx = cnow.tx;
|
||||
sic->frame = cnow.frame;
|
||||
sic->overrun = cnow.overrun;
|
||||
sic->parity = cnow.parity;
|
||||
sic->brk = cnow.brk;
|
||||
sic->buf_overrun = cnow.buf_overrun;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine allows the tty driver to be notified when
|
||||
* device's termios settings have changed. Note that a
|
||||
|
@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
|
|||
.wait_until_sent = cy_wait_until_sent,
|
||||
.tiocmget = cy_tiocmget,
|
||||
.tiocmset = cy_tiocmset,
|
||||
.get_icount = cy_get_icount,
|
||||
.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_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
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 ip2_interrupt_bh(struct work_struct *work);
|
||||
|
@ -456,6 +458,7 @@ static const struct tty_operations ip2_ops = {
|
|||
.hangup = ip2_hangup,
|
||||
.tiocmget = ip2_tiocmget,
|
||||
.tiocmset = ip2_tiocmset,
|
||||
.get_icount = ip2_get_icount,
|
||||
.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];
|
||||
i2eBordStrPtr pB;
|
||||
struct async_icount cprev, cnow; /* kernel counter temps */
|
||||
struct serial_icounter_struct __user *p_cuser;
|
||||
int rc = 0;
|
||||
unsigned long flags;
|
||||
void __user *argp = (void __user *)arg;
|
||||
|
@ -2298,34 +2300,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
|
|||
return rc;
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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() */
|
||||
/* Parameters: Pointer to channel structure */
|
||||
|
|
|
@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
|
||||
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
|
||||
test_bit(TTY_IO_ERROR, &tty->flags))
|
||||
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,
|
||||
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:
|
||||
return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
|
||||
case MOXA_SDS_RSTICOUNTER:
|
||||
|
@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
|||
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)
|
||||
{
|
||||
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,
|
||||
.tiocmget = mxser_tiocmget,
|
||||
.tiocmset = mxser_tiocmset,
|
||||
.get_icount = mxser_get_icount,
|
||||
};
|
||||
|
||||
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!
|
||||
*/
|
||||
|
||||
static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
|
||||
unsigned int irq)
|
||||
static void mxser_release_ISA_res(struct mxser_board *brd)
|
||||
{
|
||||
if (irq)
|
||||
free_irq(brd->irq, brd);
|
||||
if (pdev != NULL) { /* PCI */
|
||||
#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);
|
||||
}
|
||||
free_irq(brd->irq, brd);
|
||||
release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
|
||||
release_region(brd->vector, 1);
|
||||
}
|
||||
|
||||
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",
|
||||
brd);
|
||||
if (retval) {
|
||||
if (retval)
|
||||
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
|
||||
"conflict with another device.\n",
|
||||
brd->info->name, brd->irq);
|
||||
/* We hold resources, we need to release them. */
|
||||
mxser_release_res(brd, pdev, 0);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
|||
ioaddress = pci_resource_start(pdev, 2);
|
||||
retval = pci_request_region(pdev, 2, "mxser(IO)");
|
||||
if (retval)
|
||||
goto err;
|
||||
goto err_dis;
|
||||
|
||||
brd->info = &mxser_cards[ent->driver_data];
|
||||
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);
|
||||
retval = pci_request_region(pdev, 3, "mxser(vector)");
|
||||
if (retval)
|
||||
goto err_relio;
|
||||
goto err_zero;
|
||||
brd->vector = ioaddress;
|
||||
|
||||
/* irq */
|
||||
|
@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
|||
/* mxser_initbrd will hook ISR. */
|
||||
retval = mxser_initbrd(brd, pdev);
|
||||
if (retval)
|
||||
goto err_null;
|
||||
goto err_rel3;
|
||||
|
||||
for (i = 0; i < brd->info->nports; i++)
|
||||
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);
|
||||
|
||||
return 0;
|
||||
err_relio:
|
||||
pci_release_region(pdev, 2);
|
||||
err_null:
|
||||
err_rel3:
|
||||
pci_release_region(pdev, 3);
|
||||
err_zero:
|
||||
brd->info = NULL;
|
||||
pci_release_region(pdev, 2);
|
||||
err_dis:
|
||||
pci_disable_device(pdev);
|
||||
err:
|
||||
return retval;
|
||||
#else
|
||||
|
@ -2629,14 +2629,19 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
|
|||
|
||||
static void __devexit mxser_remove(struct pci_dev *pdev)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
struct mxser_board *brd = pci_get_drvdata(pdev);
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < brd->info->nports; 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;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct pci_driver mxser_driver = {
|
||||
|
@ -2741,7 +2746,7 @@ static void __exit mxser_module_exit(void)
|
|||
|
||||
for (i = 0; i < MXSER_BOARDS; i++)
|
||||
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);
|
||||
|
|
|
@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
|
|||
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;
|
||||
struct serial_icounter_struct 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 copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
|
||||
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 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,
|
||||
ntty_cflags_changed(port, arg, &cprev));
|
||||
break;
|
||||
} case TIOCGICOUNT:
|
||||
rval = ntty_ioctl_tiocgicount(port, argp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DBG1("ERR: 0x%08X, %d", cmd, cmd);
|
||||
break;
|
||||
|
@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
|
|||
.chars_in_buffer = ntty_chars_in_buffer,
|
||||
.tiocmget = ntty_tiocmget,
|
||||
.tiocmset = ntty_tiocmset,
|
||||
.get_icount = ntty_tiocgicount,
|
||||
.install = ntty_install,
|
||||
.cleanup = ntty_cleanup,
|
||||
};
|
||||
|
|
|
@ -2191,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
|
|||
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
|
||||
*
|
||||
* Arguments:
|
||||
|
@ -2206,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
|
|||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
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;
|
||||
unsigned long flags;
|
||||
|
||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||
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;
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -2250,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
|
|||
return wait_events(info, argp);
|
||||
case TIOCMIWAIT:
|
||||
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:
|
||||
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 */
|
||||
|
||||
tty_add_file(tty, filp);
|
||||
retval = tty_add_file(tty, filp);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
retval = devpts_pty_new(inode, tty->link);
|
||||
if (retval)
|
||||
|
|
|
@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
|
|||
|
||||
} /* 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
|
||||
*
|
||||
* Arguments:
|
||||
|
@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
|
|||
return -ENODEV;
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||
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)
|
||||
{
|
||||
int error;
|
||||
struct mgsl_icount cnow; /* kernel counter temps */
|
||||
void __user *argp = (void __user *)arg;
|
||||
struct serial_icounter_struct __user *p_cuser; /* user space */
|
||||
unsigned long flags;
|
||||
|
||||
switch (cmd) {
|
||||
case MGSL_IOCGPARAMS:
|
||||
|
@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
|
|||
case TIOCMIWAIT:
|
||||
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:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
|
|||
.hangup = mgsl_hangup,
|
||||
.tiocmget = tiocmget,
|
||||
.tiocmset = tiocmset,
|
||||
.get_icount = msgl_get_icount,
|
||||
.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)
|
||||
{
|
||||
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;
|
||||
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));
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
|||
return wait_mgsl_event(info, argp);
|
||||
case TIOCMIWAIT:
|
||||
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:
|
||||
return set_gpio(info, argp);
|
||||
case MGSL_IOCGGPIO:
|
||||
|
@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
|||
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
|
||||
*/
|
||||
|
@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
|
|||
case MGSL_IOCSGPIO:
|
||||
case MGSL_IOCGGPIO:
|
||||
case MGSL_IOCWAITGPIO:
|
||||
case TIOCGICOUNT:
|
||||
rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
|
||||
break;
|
||||
|
||||
case MGSL_IOCSTXIDLE:
|
||||
case MGSL_IOCTXENABLE:
|
||||
case MGSL_IOCRXENABLE:
|
||||
|
@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
|
|||
.hangup = hangup,
|
||||
.tiocmget = tiocmget,
|
||||
.tiocmset = tiocmset,
|
||||
.get_icount = get_icount,
|
||||
.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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (debug_level >= DEBUG_LEVEL_INFO)
|
||||
|
@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
|
|||
return -ENODEV;
|
||||
|
||||
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
|
||||
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
(cmd != TIOCMIWAIT)) {
|
||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||
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
|
||||
* 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:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
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....
|
||||
*/
|
||||
|
@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
|
|||
.hangup = hangup,
|
||||
.tiocmget = tiocmget,
|
||||
.tiocmset = tiocmset,
|
||||
.get_icount = get_icount,
|
||||
.proc_fops = &synclinkmp_proc_fops,
|
||||
};
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
|
@ -183,6 +184,8 @@ struct tty_struct *alloc_tty_struct(void)
|
|||
|
||||
void free_tty_struct(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->dev)
|
||||
put_device(tty->dev);
|
||||
kfree(tty->write_buf);
|
||||
tty_buffer_free_all(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 */
|
||||
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;
|
||||
|
||||
/* XXX: must implement proper error handling in callers */
|
||||
priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL);
|
||||
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->tty = tty;
|
||||
priv->file = file;
|
||||
|
@ -208,6 +212,8 @@ void tty_add_file(struct tty_struct *tty, struct file *file)
|
|||
spin_lock(&tty_files_lock);
|
||||
list_add(&priv->list, &tty->tty_files);
|
||||
spin_unlock(&tty_files_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Delete file from its tty */
|
||||
|
@ -1875,7 +1881,11 @@ static int tty_open(struct inode *inode, struct file *filp)
|
|||
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");
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 TIOCMBIS:
|
||||
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:
|
||||
switch (arg) {
|
||||
case TCIFLUSH:
|
||||
|
@ -2783,6 +2813,20 @@ void do_SAK(struct tty_struct *tty)
|
|||
|
||||
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
|
||||
* @tty: tty to initialize
|
||||
|
@ -2823,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty,
|
|||
tty->ops = driver->ops;
|
||||
tty->index = idx;
|
||||
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;
|
||||
dev_t dev;
|
||||
void **p = NULL;
|
||||
struct device *d;
|
||||
|
||||
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
|
||||
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);
|
||||
|
||||
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
|
||||
for (i = 0; i < driver->num; i++)
|
||||
tty_register_device(driver, i, NULL);
|
||||
for (i = 0; i < driver->num; i++) {
|
||||
d = tty_register_device(driver, i, NULL);
|
||||
if (IS_ERR(d)) {
|
||||
error = PTR_ERR(d);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
proc_tty_register_driver(driver);
|
||||
driver->flags |= TTY_DRIVER_INSTALLED;
|
||||
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);
|
||||
|
|
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/device.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/byteorder.h>
|
||||
|
@ -45,6 +51,86 @@
|
|||
#undef addr
|
||||
#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
|
||||
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;
|
||||
unsigned int currcons = iminor(inode);
|
||||
struct vc_data *vc;
|
||||
struct vcs_poll_data *poll;
|
||||
long pos;
|
||||
long viewed, attr, read;
|
||||
int col, maxcol;
|
||||
|
@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
|||
ret = -EINVAL;
|
||||
if (pos < 0)
|
||||
goto unlock_out;
|
||||
poll = file->private_data;
|
||||
if (count && poll)
|
||||
poll->seen_last_update = true;
|
||||
read = 0;
|
||||
ret = 0;
|
||||
while (count) {
|
||||
|
@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
|||
}
|
||||
*ppos += written;
|
||||
ret = written;
|
||||
if (written)
|
||||
vcs_scr_updated(vc);
|
||||
|
||||
unlock_out:
|
||||
release_console_sem();
|
||||
|
@ -457,6 +549,37 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
|||
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
|
||||
vcs_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
|
@ -470,11 +593,23 @@ vcs_open(struct inode *inode, struct file *filp)
|
|||
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 = {
|
||||
.llseek = vcs_lseek,
|
||||
.read = vcs_read,
|
||||
.write = vcs_write,
|
||||
.poll = vcs_poll,
|
||||
.fasync = vcs_fasync,
|
||||
.open = vcs_open,
|
||||
.release = vcs_release,
|
||||
};
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -165,6 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
|
|||
serio->open = serport_serio_open;
|
||||
serio->close = serport_serio_close;
|
||||
serio->port_data = serport;
|
||||
serio->dev.parent = tty->dev;
|
||||
|
||||
serio_register_port(serport->serio);
|
||||
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
|
||||
* RI where only 0->1 is counted.
|
||||
*/
|
||||
static int hso_get_count(struct hso_serial *serial,
|
||||
struct serial_icounter_struct __user *icnt)
|
||||
static int hso_get_count(struct tty_struct *tty,
|
||||
struct serial_icounter_struct *icount)
|
||||
{
|
||||
struct serial_icounter_struct icount;
|
||||
struct uart_icount cnow;
|
||||
struct hso_serial *serial = get_serial_by_tty(tty);
|
||||
struct hso_tiocmget *tiocmget = serial->tiocmget;
|
||||
|
||||
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));
|
||||
spin_unlock_irq(&serial->serial_lock);
|
||||
|
||||
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;
|
||||
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 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:
|
||||
ret = hso_wait_modem_status(serial, arg);
|
||||
break;
|
||||
|
||||
case TIOCGICOUNT:
|
||||
ret = hso_get_count(serial, uarg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
|
@ -3300,6 +3296,7 @@ static const struct tty_operations hso_serial_ops = {
|
|||
.chars_in_buffer = hso_serial_chars_in_buffer,
|
||||
.tiocmget = hso_serial_tiocmget,
|
||||
.tiocmset = hso_serial_tiocmset,
|
||||
.get_icount = hso_get_count,
|
||||
.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,
|
||||
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"))
|
||||
return -ENODEV;
|
||||
|
||||
if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
|
||||
if (cmd != TIOCMIWAIT) {
|
||||
if (tty->flags & (1 << TTY_IO_ERROR))
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1477,31 +1501,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
|
|||
return 0;
|
||||
#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:
|
||||
return -ENOIOCTLCMD;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
@ -154,12 +155,6 @@ struct uart_8250_port {
|
|||
unsigned char lsr_saved_flags;
|
||||
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
|
||||
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 {
|
||||
|
@ -1606,8 +1601,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
|
|||
|
||||
if (l == i->head && pass_counter++ > PASS_LIMIT) {
|
||||
/* If we hit this, we're dead. */
|
||||
printk(KERN_ERR "serial8250: too much work for "
|
||||
"irq%d\n", irq);
|
||||
printk_ratelimited(KERN_ERR
|
||||
"serial8250: too much work for irq%d\n", irq);
|
||||
break;
|
||||
}
|
||||
} while (l != end);
|
||||
|
@ -1722,12 +1717,6 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up)
|
|||
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
|
||||
* 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);
|
||||
if (!(iir & UART_IIR_NO_INT))
|
||||
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)
|
||||
|
@ -1787,7 +1776,7 @@ static void serial8250_backup_timeout(unsigned long data)
|
|||
|
||||
/* Standard timer interval plus 0.2s to keep the port running */
|
||||
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)
|
||||
|
@ -1867,15 +1856,17 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
|
|||
unsigned int status, tmout = 10000;
|
||||
|
||||
/* Wait up to 10ms for the character(s) to be sent. */
|
||||
do {
|
||||
for (;;) {
|
||||
status = serial_in(up, UART_LSR);
|
||||
|
||||
up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
|
||||
|
||||
if ((status & bits) == bits)
|
||||
break;
|
||||
if (--tmout == 0)
|
||||
break;
|
||||
udelay(1);
|
||||
} while ((status & bits) != bits);
|
||||
}
|
||||
|
||||
/* Wait up to 1s for flow control if necessary */
|
||||
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.data = (unsigned long)up;
|
||||
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)) {
|
||||
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 {
|
||||
retval = serial_link_irq_chain(up);
|
||||
if (retval)
|
||||
|
@ -2440,16 +2431,24 @@ serial8250_set_ldisc(struct uart_port *port, int new)
|
|||
port->flags &= ~UPF_HARDPPS_CD;
|
||||
}
|
||||
|
||||
static void
|
||||
serial8250_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
|
||||
void serial8250_do_pm(struct uart_port *port, unsigned int state,
|
||||
unsigned int oldstate)
|
||||
{
|
||||
struct uart_8250_port *p = (struct uart_8250_port *)port;
|
||||
|
||||
serial8250_set_sleep(p, state != 0);
|
||||
}
|
||||
EXPORT_SYMBOL(serial8250_do_pm);
|
||||
|
||||
if (p->pm)
|
||||
p->pm(port, state, oldstate);
|
||||
static void
|
||||
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)
|
||||
|
@ -2674,6 +2673,16 @@ static struct uart_ops serial8250_pops = {
|
|||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
set_io_from_upio(&up->port);
|
||||
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_out = p->serial_out;
|
||||
port.set_termios = p->set_termios;
|
||||
port.pm = p->pm;
|
||||
port.dev = &dev->dev;
|
||||
port.irqflags |= irqflag;
|
||||
ret = serial8250_register_port(&port);
|
||||
|
@ -3176,6 +3189,12 @@ int serial8250_register_port(struct uart_port *port)
|
|||
/* Possibly override set_termios call */
|
||||
if (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);
|
||||
if (ret == 0)
|
||||
|
|
|
@ -718,13 +718,6 @@ config SERIAL_MRST_MAX3110
|
|||
the Intel Moorestown platform. On other systems use the max3100
|
||||
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
|
||||
tristate "Medfield High Speed UART support"
|
||||
depends on PCI
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/console.h>
|
||||
|
@ -27,6 +28,8 @@
|
|||
#include <linux/altera_uart.h>
|
||||
|
||||
#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:
|
||||
|
@ -76,13 +79,28 @@
|
|||
*/
|
||||
struct altera_uart {
|
||||
struct uart_port port;
|
||||
struct timer_list tmr;
|
||||
unsigned int sigs; /* Local copy of line sigs */
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
unsigned int sigs;
|
||||
|
||||
sigs =
|
||||
(readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||
sigs = (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||
ALTERA_UART_STATUS_CTS_MSK) ? TIOCM_CTS : 0;
|
||||
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;
|
||||
else
|
||||
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)
|
||||
|
@ -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);
|
||||
|
||||
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)
|
||||
|
@ -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);
|
||||
|
||||
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)
|
||||
|
@ -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);
|
||||
|
||||
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)
|
||||
|
@ -145,7 +162,7 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state)
|
|||
pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -168,7 +185,8 @@ static void altera_uart_set_termios(struct uart_port *port,
|
|||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -178,14 +196,15 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
|
|||
unsigned char ch, flag;
|
||||
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) {
|
||||
ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
|
||||
ch = altera_uart_readl(port, ALTERA_UART_RXDATA_REG);
|
||||
flag = TTY_NORMAL;
|
||||
port->icount.rx++;
|
||||
|
||||
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) {
|
||||
port->icount.brk++;
|
||||
|
@ -225,18 +244,18 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
|
|||
|
||||
if (port->x_char) {
|
||||
/* 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->icount.tx++;
|
||||
return;
|
||||
}
|
||||
|
||||
while (readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||
while (altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||
ALTERA_UART_STATUS_TRDY_MSK) {
|
||||
if (xmit->head == xmit->tail)
|
||||
break;
|
||||
writel(xmit->buf[xmit->tail],
|
||||
port->membase + ALTERA_UART_TXDATA_REG);
|
||||
altera_uart_writel(port, xmit->buf[xmit->tail],
|
||||
ALTERA_UART_TXDATA_REG);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
port->icount.tx++;
|
||||
}
|
||||
|
@ -246,7 +265,7 @@ static void altera_uart_tx_chars(struct altera_uart *pp)
|
|||
|
||||
if (xmit->head == xmit->tail) {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
port->type = PORT_ALTERA_UART;
|
||||
|
||||
/* 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 */
|
||||
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)
|
||||
|
@ -284,6 +312,12 @@ static int altera_uart_startup(struct uart_port *port)
|
|||
unsigned long flags;
|
||||
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,
|
||||
DRV_NAME, port);
|
||||
if (ret) {
|
||||
|
@ -316,7 +350,10 @@ static void altera_uart_shutdown(struct uart_port *port)
|
|||
|
||||
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)
|
||||
|
@ -384,8 +421,9 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp)
|
|||
port->iotype = SERIAL_IO_MEM;
|
||||
port->irq = platp[i].irq;
|
||||
port->uartclk = platp[i].uartclk;
|
||||
port->flags = ASYNC_BOOT_AUTOCONF;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->ops = &altera_uart_ops;
|
||||
port->private_data = platp;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
while (!(readl(port->membase + ALTERA_UART_STATUS_REG) &
|
||||
while (!(altera_uart_readl(port, ALTERA_UART_STATUS_REG) &
|
||||
ALTERA_UART_STATUS_TRDY_MSK))
|
||||
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)
|
||||
return -EINVAL;
|
||||
port = &altera_uart_ports[co->index].port;
|
||||
if (port->membase == 0)
|
||||
if (!port->membase)
|
||||
return -ENODEV;
|
||||
|
||||
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 console altera_uart_console = {
|
||||
.name = "ttyS",
|
||||
.name = "ttyAL",
|
||||
.write = altera_uart_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = altera_uart_console_setup,
|
||||
|
@ -466,9 +504,9 @@ console_initcall(altera_uart_console_init);
|
|||
static struct uart_driver altera_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = DRV_NAME,
|
||||
.dev_name = "ttyS",
|
||||
.major = TTY_MAJOR,
|
||||
.minor = 64,
|
||||
.dev_name = "ttyAL",
|
||||
.major = SERIAL_ALTERA_MAJOR,
|
||||
.minor = SERIAL_ALTERA_MINOR,
|
||||
.nr = CONFIG_SERIAL_ALTERA_UART_MAXPORTS,
|
||||
.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 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++) {
|
||||
port = &altera_uart_ports[i].port;
|
||||
/* -1 emphasizes that the platform must have one port, no .N suffix */
|
||||
if (i == -1)
|
||||
i = 0;
|
||||
|
||||
port->line = i;
|
||||
port->type = PORT_ALTERA_UART;
|
||||
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;
|
||||
if (i >= CONFIG_SERIAL_ALTERA_UART_MAXPORTS)
|
||||
return -EINVAL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int __devexit altera_uart_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *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);
|
||||
}
|
||||
struct uart_port *port = &altera_uart_ports[pdev->id].port;
|
||||
|
||||
uart_remove_one_port(&altera_uart_driver, port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -550,3 +605,4 @@ MODULE_DESCRIPTION("Altera UART driver");
|
|||
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
|
||||
MODULE_LICENSE("GPL");
|
||||
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));
|
||||
|
||||
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_RCLKDIV(up, rclkdiv);
|
||||
SSYNC();
|
||||
|
|
|
@ -327,14 +327,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
|
|||
{
|
||||
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]
|
||||
* out the port here */
|
||||
writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
sport->port.icount.tx++;
|
||||
if (uart_circ_empty(xmit))
|
||||
break;
|
||||
}
|
||||
|
||||
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! */
|
||||
dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
|
||||
rc = -ENOMEM;
|
||||
goto out_free_irq;
|
||||
goto out_free_uart;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, brd);
|
||||
pci_save_state(pdev);
|
||||
|
||||
return 0;
|
||||
out_free_uart:
|
||||
jsm_remove_uart_port(brd);
|
||||
out_free_irq:
|
||||
jsm_remove_uart_port(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);
|
||||
if (!s->rxbuf) {
|
||||
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);
|
||||
if (!s->rxstr) {
|
||||
pr_err("Allocating RX buffer failed\n");
|
||||
return -ENOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto err_free3;
|
||||
}
|
||||
/* SPI Tx 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);
|
||||
if (!s->txbuf) {
|
||||
pr_err("Allocating TX buffer failed\n");
|
||||
return -ENOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto err_free2;
|
||||
}
|
||||
/* Initialize shared 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;
|
||||
if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
|
||||
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 &&
|
||||
(buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) {
|
||||
dev_err(&s->spi->dev, "REVID %x does not match\n",
|
||||
(buf[0] & MAX3107_SPI_RX_DATA_MASK));
|
||||
return -ENODEV;
|
||||
retval = -ENODEV;
|
||||
goto err_free1;
|
||||
}
|
||||
|
||||
/* Disable all interrupts */
|
||||
|
@ -1047,7 +1052,8 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
|||
/* Perform SPI transfer */
|
||||
if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
|
||||
dev_err(&s->spi->dev, "SPI transfer for init failed\n");
|
||||
return -EIO;
|
||||
retval = -EIO;
|
||||
goto err_free1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (retval) {
|
||||
dev_err(&s->spi->dev, "Registering UART driver failed\n");
|
||||
return retval;
|
||||
goto err_free1;
|
||||
}
|
||||
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);
|
||||
if (retval < 0) {
|
||||
dev_err(&s->spi->dev, "Adding UART port failed\n");
|
||||
return retval;
|
||||
goto err_free1;
|
||||
}
|
||||
|
||||
if (pdata->configure) {
|
||||
retval = pdata->configure(s);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
goto err_free1;
|
||||
}
|
||||
|
||||
/* Go to suspend mode */
|
||||
|
@ -1088,6 +1094,16 @@ int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata)
|
|||
pdata->hw_suspend(s, 1);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
"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);
|
||||
kfree(buf);
|
||||
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,
|
||||
"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);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
@ -925,39 +931,52 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
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
|
||||
* scalar from 2746800, like 115200 = 2746800/24, for those
|
||||
* higher baud rate, we have to handle them case by case,
|
||||
* but DIV reg is never touched as its default value 0x3d09
|
||||
* scalar from 2746800, like 115200 = 2746800/24. For those
|
||||
* higher baud rate, we handle them case by case, mainly by
|
||||
* 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);
|
||||
quot = uart_get_divisor(port, baud);
|
||||
|
||||
quot = 1;
|
||||
switch (baud) {
|
||||
case 3500000:
|
||||
mul = 0x3345;
|
||||
ps = 0xC;
|
||||
quot = 1;
|
||||
break;
|
||||
case 3000000:
|
||||
mul = 0x2EE0;
|
||||
break;
|
||||
case 2500000:
|
||||
mul = 0x2710;
|
||||
ps = 0x10;
|
||||
quot = 1;
|
||||
break;
|
||||
case 18432000:
|
||||
case 2000000:
|
||||
mul = 0x1F40;
|
||||
break;
|
||||
case 1843200:
|
||||
mul = 0x2400;
|
||||
ps = 0x10;
|
||||
quot = 1;
|
||||
break;
|
||||
case 1500000:
|
||||
mul = 0x1D4C;
|
||||
ps = 0xc;
|
||||
quot = 1;
|
||||
mul = 0x1770;
|
||||
break;
|
||||
case 1000000:
|
||||
mul = 0xFA0;
|
||||
break;
|
||||
case 500000:
|
||||
mul = 0x7D0;
|
||||
break;
|
||||
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))
|
||||
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
|
||||
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
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -32,18 +32,13 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/dw_spi.h>
|
||||
|
||||
#include "mrst_max3110.h"
|
||||
|
||||
|
@ -56,7 +51,7 @@
|
|||
struct uart_max3110 {
|
||||
struct uart_port port;
|
||||
struct spi_device *spi;
|
||||
char *name;
|
||||
char name[24];
|
||||
|
||||
wait_queue_head_t wq;
|
||||
struct task_struct *main_thread;
|
||||
|
@ -67,35 +62,30 @@ struct uart_max3110 {
|
|||
u16 cur_conf;
|
||||
u8 clock;
|
||||
u8 parity, word_7bits;
|
||||
u16 irq;
|
||||
|
||||
unsigned long uart_flags;
|
||||
|
||||
/* console related */
|
||||
struct circ_buf con_xmit;
|
||||
|
||||
/* irq related */
|
||||
u16 irq;
|
||||
};
|
||||
|
||||
/* global data structure, may need be removed */
|
||||
struct uart_max3110 *pmax;
|
||||
static inline void receive_char(struct uart_max3110 *max, u8 ch);
|
||||
static struct uart_max3110 *pmax;
|
||||
|
||||
static void receive_chars(struct uart_max3110 *max,
|
||||
unsigned char *str, int len);
|
||||
static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf);
|
||||
static void max3110_console_receive(struct uart_max3110 *max);
|
||||
static int max3110_read_multi(struct uart_max3110 *max, u8 *buf);
|
||||
static void max3110_con_receive(struct uart_max3110 *max);
|
||||
|
||||
int max3110_write_then_read(struct uart_max3110 *max,
|
||||
const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast)
|
||||
static int max3110_write_then_read(struct uart_max3110 *max,
|
||||
const void *txbuf, void *rxbuf, unsigned len, int always_fast)
|
||||
{
|
||||
struct spi_device *spi = max->spi;
|
||||
struct spi_message message;
|
||||
struct spi_transfer x;
|
||||
int ret;
|
||||
|
||||
if (!txbuf || !rxbuf)
|
||||
return -EINVAL;
|
||||
|
||||
spi_message_init(&message);
|
||||
memset(&x, 0, sizeof x);
|
||||
x.len = len;
|
||||
|
@ -104,7 +94,7 @@ int max3110_write_then_read(struct uart_max3110 *max,
|
|||
spi_message_add_tail(&x, &message);
|
||||
|
||||
if (always_fast)
|
||||
x.speed_hz = 3125000;
|
||||
x.speed_hz = spi->max_speed_hz;
|
||||
else if (max->baud)
|
||||
x.speed_hz = max->baud;
|
||||
|
||||
|
@ -113,58 +103,80 @@ int max3110_write_then_read(struct uart_max3110 *max,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Write a u16 to the device, and return one u16 read back */
|
||||
int max3110_out(struct uart_max3110 *max, const u16 out)
|
||||
/* Write a 16b word to the device */
|
||||
static int max3110_out(struct uart_max3110 *max, const u16 out)
|
||||
{
|
||||
u16 tmp;
|
||||
void *buf;
|
||||
u16 *obuf, *ibuf;
|
||||
u8 ch;
|
||||
int ret;
|
||||
|
||||
ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
buf = kzalloc(8, GFP_KERNEL | GFP_DMA);
|
||||
if (!buf)
|
||||
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 (tmp & MAX3110_READ_DATA_AVAILABLE)
|
||||
receive_char(max, (tmp & 0xff));
|
||||
if (*ibuf & MAX3110_READ_DATA_AVAILABLE) {
|
||||
ch = *ibuf & 0xff;
|
||||
receive_chars(max, &ch, 1);
|
||||
}
|
||||
|
||||
exit:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_READ_LEN 20
|
||||
/*
|
||||
* 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
|
||||
* valide bytes are read back
|
||||
* need any delay like flushing character out.
|
||||
*
|
||||
* 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];
|
||||
u8 *pbuf, valid_str[MAX_READ_LEN];
|
||||
int i, j, bytelen;
|
||||
void *buf;
|
||||
u16 *obuf, *ibuf;
|
||||
u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH];
|
||||
int i, j, blen;
|
||||
|
||||
if (len > MAX_READ_LEN) {
|
||||
pr_err(PR_FMT "read len %d is too large\n", len);
|
||||
blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
|
||||
buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
|
||||
if (!buf) {
|
||||
pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytelen = len * 2;
|
||||
memset(out, 0, bytelen);
|
||||
memset(in, 0, bytelen);
|
||||
/* tx/rx always have the same length */
|
||||
obuf = buf;
|
||||
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;
|
||||
}
|
||||
|
||||
/* If caller don't provide a buffer, then handle received char */
|
||||
pbuf = buf ? buf : valid_str;
|
||||
/* If caller doesn't provide a buffer, then handle received char */
|
||||
pbuf = rxbuf ? rxbuf : valid_str;
|
||||
|
||||
for (i = 0, j = 0; i < len; i++) {
|
||||
if (in[i] & MAX3110_READ_DATA_AVAILABLE)
|
||||
pbuf[j++] = (u8)(in[i] & 0xff);
|
||||
for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) {
|
||||
if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
|
||||
pbuf[j++] = ibuf[i] & 0xff;
|
||||
}
|
||||
|
||||
if (j && (pbuf == valid_str))
|
||||
receive_chars(max, valid_str, j);
|
||||
|
||||
kfree(buf);
|
||||
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->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;
|
||||
|
||||
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
|
||||
|
@ -210,6 +221,9 @@ serial_m3110_con_setup(struct console *co, char *options)
|
|||
|
||||
pr_info(PR_FMT "setting up console\n");
|
||||
|
||||
if (co->index == -1)
|
||||
co->index = 0;
|
||||
|
||||
if (!max) {
|
||||
pr_err(PR_FMT "pmax is NULL, return");
|
||||
return -ENODEV;
|
||||
|
@ -240,8 +254,6 @@ static struct console serial_m3110_console = {
|
|||
.data = &serial_m3110_reg,
|
||||
};
|
||||
|
||||
#define MRST_CONSOLE (&serial_m3110_console)
|
||||
|
||||
static unsigned int serial_m3110_tx_empty(struct uart_port *port)
|
||||
{
|
||||
return 1;
|
||||
|
@ -259,32 +271,44 @@ static void serial_m3110_stop_rx(struct uart_port *port)
|
|||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
int len, left = 0;
|
||||
u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER];
|
||||
void *buf;
|
||||
u16 *obuf, *ibuf;
|
||||
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)) {
|
||||
left = uart_circ_chars_pending(xmit);
|
||||
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++) {
|
||||
obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG;
|
||||
xmit->tail = (xmit->tail + 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++) {
|
||||
if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE)
|
||||
valid_str[j++] = (u8)(ibuf[i] & 0xff);
|
||||
valid_str[j++] = ibuf[i] & 0xff;
|
||||
}
|
||||
|
||||
if (j)
|
||||
|
@ -294,6 +318,8 @@ static inline void send_circ_buf(struct uart_max3110 *max,
|
|||
left -= len;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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;
|
||||
if (!tty)
|
||||
return; /* receive some char before the tty is opened */
|
||||
return;
|
||||
|
||||
while (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);
|
||||
str += usable;
|
||||
port->icount.rx += usable;
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
len -= usable;
|
||||
}
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
static inline void receive_char(struct uart_max3110 *max, u8 ch)
|
||||
{
|
||||
receive_chars(max, &ch, 1);
|
||||
}
|
||||
|
||||
static void max3110_console_receive(struct uart_max3110 *max)
|
||||
/*
|
||||
* This routine will be used in read_thread or RX IRQ handling,
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
u8 recv_buf[512], *pbuf;
|
||||
|
||||
pbuf = recv_buf;
|
||||
do {
|
||||
num = max3110_read_multi(max, 8, pbuf);
|
||||
num = max3110_read_multi(max, pbuf);
|
||||
|
||||
if (num) {
|
||||
loop = 10;
|
||||
loop = 5;
|
||||
pbuf += num;
|
||||
total += num;
|
||||
|
||||
if (total >= 500) {
|
||||
if (total >= 504) {
|
||||
receive_chars(max, recv_buf, total);
|
||||
pbuf = recv_buf;
|
||||
total = 0;
|
||||
|
@ -397,7 +430,7 @@ static int max3110_main_thread(void *_max)
|
|||
mutex_lock(&max->thread_mutex);
|
||||
|
||||
if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags))
|
||||
max3110_console_receive(max);
|
||||
max3110_con_receive(max);
|
||||
|
||||
/* first handle console output */
|
||||
if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags))
|
||||
|
@ -414,7 +447,6 @@ static int max3110_main_thread(void *_max)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MRST_MAX3110_IRQ
|
||||
static irqreturn_t serial_m3110_irq(int irq, void *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;
|
||||
}
|
||||
#else
|
||||
|
||||
/* if don't use RX IRQ, then need a thread to polling read */
|
||||
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");
|
||||
do {
|
||||
mutex_lock(&max->thread_mutex);
|
||||
max3110_console_receive(max);
|
||||
mutex_unlock(&max->thread_mutex);
|
||||
/*
|
||||
* If can't acquire the mutex, it means the main thread
|
||||
* 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);
|
||||
schedule_timeout(HZ / 20);
|
||||
|
@ -444,7 +481,6 @@ static int max3110_read_thread(void *_max)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
int ret = 0;
|
||||
|
||||
if (port->line != 0)
|
||||
if (port->line != 0) {
|
||||
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
|
||||
| WC_1_STOPBITS
|
||||
| WC_8BIT_WORD
|
||||
| WC_BAUD_DR2;
|
||||
ret = max3110_out(max, config);
|
||||
|
||||
/* as we use thread to handle tx/rx, need set low latency */
|
||||
port->state->port.tty->low_latency = 1;
|
||||
|
||||
#ifdef CONFIG_MRST_MAX3110_IRQ
|
||||
ret = request_irq(max->irq, serial_m3110_irq,
|
||||
if (max->irq) {
|
||||
max->read_thread = NULL;
|
||||
ret = request_irq(max->irq, serial_m3110_irq,
|
||||
IRQ_TYPE_EDGE_FALLING, "max3110", max);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (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 */
|
||||
config |= WC_RXA_IRQ_ENABLE;
|
||||
max3110_out(max, config);
|
||||
#else
|
||||
/* if IRQ is disabled, start a read thread for input data */
|
||||
max->read_thread =
|
||||
kthread_run(max3110_read_thread, max, "max3110_read");
|
||||
#endif
|
||||
if (max->irq == 0) {
|
||||
/* If IRQ is disabled, start a read thread for input data */
|
||||
max->read_thread =
|
||||
kthread_run(max3110_read_thread, max, "max3110_read");
|
||||
if (IS_ERR(max->read_thread)) {
|
||||
ret = PTR_ERR(max->read_thread);
|
||||
max->read_thread = NULL;
|
||||
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;
|
||||
return 0;
|
||||
|
@ -496,9 +553,8 @@ static void serial_m3110_shutdown(struct uart_port *port)
|
|||
max->read_thread = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MRST_MAX3110_IRQ
|
||||
free_irq(max->irq, max);
|
||||
#endif
|
||||
if (max->irq)
|
||||
free_irq(max->irq, max);
|
||||
|
||||
/* Disable interrupts from this port */
|
||||
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)
|
||||
{
|
||||
/* give it fake type */
|
||||
port->type = PORT_PXA;
|
||||
port->type = PORT_MAX3100;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -552,6 +607,9 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
new_conf |= WC_7BIT_WORD;
|
||||
break;
|
||||
default:
|
||||
/* We only support CS7 & CS8 */
|
||||
termios->c_cflag &= ~CSIZE;
|
||||
termios->c_cflag |= CS8;
|
||||
case CS8:
|
||||
cval = UART_LCR_WLEN8;
|
||||
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);
|
||||
|
||||
/* first calc the div for 1.8MHZ clock case */
|
||||
/* First calc the div for 1.8MHZ clock case */
|
||||
switch (baud) {
|
||||
case 300:
|
||||
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)
|
||||
break;
|
||||
default:
|
||||
/* pick the previous baud rate */
|
||||
/* Pick the previous baud rate */
|
||||
baud = max->baud;
|
||||
clk_div = max->cur_conf & WC_BAUD_DIV_MASK;
|
||||
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) {
|
||||
clk_div += 1;
|
||||
/* high clk version max3110 doesn't support B300 */
|
||||
if (baud == 300)
|
||||
/* High clk version max3110 doesn't support B300 */
|
||||
if (baud == 300) {
|
||||
baud = 600;
|
||||
clk_div = WC_BAUD_DR384;
|
||||
}
|
||||
if (baud == 230400)
|
||||
clk_div = WC_BAUD_DR1;
|
||||
tty_termios_encode_baud_rate(termios, baud, baud);
|
||||
}
|
||||
|
||||
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)
|
||||
new_conf |= WC_2_STOPBITS;
|
||||
else
|
||||
|
@ -632,13 +696,14 @@ serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
|
||||
new_conf |= WC_TAG;
|
||||
if (new_conf != max->cur_conf) {
|
||||
max3110_out(max, new_conf);
|
||||
max->cur_conf = new_conf;
|
||||
max->baud = baud;
|
||||
if (!max3110_out(max, new_conf)) {
|
||||
max->cur_conf = new_conf;
|
||||
max->baud = baud;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* don't handle hw handshaking */
|
||||
/* Don't handle hw handshaking */
|
||||
static unsigned int serial_m3110_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR;
|
||||
|
@ -672,7 +737,7 @@ struct uart_ops serial_m3110_ops = {
|
|||
.break_ctl = serial_m3110_break_ctl,
|
||||
.startup = serial_m3110_startup,
|
||||
.shutdown = serial_m3110_shutdown,
|
||||
.set_termios = serial_m3110_set_termios, /* must have */
|
||||
.set_termios = serial_m3110_set_termios,
|
||||
.pm = serial_m3110_pm,
|
||||
.type = serial_m3110_type,
|
||||
.release_port = serial_m3110_release_port,
|
||||
|
@ -688,52 +753,60 @@ static struct uart_driver serial_m3110_reg = {
|
|||
.major = TTY_MAJOR,
|
||||
.minor = 64,
|
||||
.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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#else
|
||||
#define serial_m3110_suspend NULL
|
||||
#define serial_m3110_resume NULL
|
||||
#endif
|
||||
|
||||
static struct dw_spi_chip spi0_uart = {
|
||||
.poll_mode = 1,
|
||||
.enable_dma = 0,
|
||||
.type = SPI_FRF_SPI,
|
||||
};
|
||||
|
||||
static int serial_m3110_probe(struct spi_device *spi)
|
||||
static int __devinit serial_m3110_probe(struct spi_device *spi)
|
||||
{
|
||||
struct uart_max3110 *max;
|
||||
int ret;
|
||||
unsigned char *buffer;
|
||||
void *buffer;
|
||||
u16 res;
|
||||
int ret = 0;
|
||||
|
||||
max = kzalloc(sizeof(*max), GFP_KERNEL);
|
||||
if (!max)
|
||||
return -ENOMEM;
|
||||
|
||||
/* set spi info */
|
||||
spi->mode = SPI_MODE_0;
|
||||
/* Set spi info */
|
||||
spi->bits_per_word = 16;
|
||||
max->clock = MAX3110_HIGH_CLK;
|
||||
spi->controller_data = &spi0_uart;
|
||||
|
||||
spi_setup(spi);
|
||||
|
||||
max->port.type = PORT_PXA; /* need apply for a max3110 type */
|
||||
max->port.fifosize = 2; /* only have 16b buffer */
|
||||
max->port.type = PORT_MAX3100;
|
||||
max->port.fifosize = 2; /* Only have 16b buffer */
|
||||
max->port.ops = &serial_m3110_ops;
|
||||
max->port.line = 0;
|
||||
max->port.dev = &spi->dev;
|
||||
max->port.uartclk = 115200;
|
||||
|
||||
max->spi = spi;
|
||||
max->name = spi->modalias; /* use spi name as the name */
|
||||
strcpy(max->name, spi->modalias);
|
||||
max->irq = (u16)spi->irq;
|
||||
|
||||
mutex_init(&max->thread_mutex);
|
||||
|
@ -755,13 +828,15 @@ static int serial_m3110_probe(struct spi_device *spi)
|
|||
ret = -ENODEV;
|
||||
goto err_get_page;
|
||||
}
|
||||
buffer = (unsigned char *)__get_free_page(GFP_KERNEL);
|
||||
|
||||
buffer = (void *)__get_free_page(GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto err_get_page;
|
||||
}
|
||||
max->con_xmit.buf = (unsigned char *)buffer;
|
||||
max->con_xmit.head = max->con_xmit.tail = 0;
|
||||
max->con_xmit.buf = buffer;
|
||||
max->con_xmit.head = 0;
|
||||
max->con_xmit.tail = 0;
|
||||
|
||||
max->main_thread = kthread_run(max3110_main_thread,
|
||||
max, "max3110_main");
|
||||
|
@ -770,8 +845,10 @@ static int serial_m3110_probe(struct spi_device *spi)
|
|||
goto err_kthread;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, 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;
|
||||
uart_add_one_port(&serial_m3110_reg, &max->port);
|
||||
|
||||
|
@ -780,19 +857,17 @@ static int serial_m3110_probe(struct spi_device *spi)
|
|||
err_kthread:
|
||||
free_page((unsigned long)buffer);
|
||||
err_get_page:
|
||||
pmax = NULL;
|
||||
kfree(max);
|
||||
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;
|
||||
|
||||
pmax = NULL;
|
||||
uart_remove_one_port(&serial_m3110_reg, &max->port);
|
||||
|
||||
free_page((unsigned long)max->con_xmit.buf);
|
||||
|
@ -811,13 +886,12 @@ static struct spi_driver uart_max3110_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = serial_m3110_probe,
|
||||
.remove = __devexit_p(max3110_remove),
|
||||
.remove = __devexit_p(serial_m3110_remove),
|
||||
.suspend = serial_m3110_suspend,
|
||||
.resume = serial_m3110_resume,
|
||||
};
|
||||
|
||||
|
||||
int __init serial_m3110_init(void)
|
||||
static int __init serial_m3110_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -832,7 +906,7 @@ int __init serial_m3110_init(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void __exit serial_m3110_exit(void)
|
||||
static void __exit serial_m3110_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&uart_max3110_driver);
|
||||
uart_unregister_driver(&serial_m3110_reg);
|
||||
|
@ -841,5 +915,5 @@ void __exit serial_m3110_exit(void)
|
|||
module_init(serial_m3110_init);
|
||||
module_exit(serial_m3110_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("max3110-uart");
|
||||
|
|
|
@ -56,4 +56,5 @@
|
|||
#define WC_BAUD_DR192 (0xE)
|
||||
#define WC_BAUD_DR384 (0xF)
|
||||
|
||||
#define M3110_RX_FIFO_DEPTH 8
|
||||
#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
|
||||
* RI where only 0->1 is counted.
|
||||
*/
|
||||
static int uart_get_count(struct uart_state *state,
|
||||
struct serial_icounter_struct __user *icnt)
|
||||
static int uart_get_icount(struct tty_struct *tty,
|
||||
struct serial_icounter_struct *icount)
|
||||
{
|
||||
struct serial_icounter_struct icount;
|
||||
struct uart_state *state = tty->driver_data;
|
||||
struct uart_icount cnow;
|
||||
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));
|
||||
spin_unlock_irq(&uport->lock);
|
||||
|
||||
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;
|
||||
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 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:
|
||||
ret = uart_wait_modem_status(state, arg);
|
||||
break;
|
||||
|
||||
case TIOCGICOUNT:
|
||||
ret = uart_get_count(state, uarg);
|
||||
break;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
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);
|
||||
uport->ops->set_termios(uport, &termios, NULL);
|
||||
console_start(uport->cons);
|
||||
|
@ -2283,6 +2291,7 @@ static const struct tty_operations uart_ops = {
|
|||
#endif
|
||||
.tiocmget = uart_tiocmget,
|
||||
.tiocmset = uart_tiocmset,
|
||||
.get_icount = uart_get_icount,
|
||||
#ifdef CONFIG_CONSOLE_POLL
|
||||
.poll_init = uart_poll_init,
|
||||
.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;
|
||||
}
|
||||
|
||||
#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 = {
|
||||
.tx_empty = ulite_tx_empty,
|
||||
.set_mctrl = ulite_set_mctrl,
|
||||
|
@ -338,7 +358,11 @@ static struct uart_ops ulite_ops = {
|
|||
.release_port = ulite_release_port,
|
||||
.request_port = ulite_request_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;
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
|
@ -460,25 +480,6 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return 0;
|
||||
}
|
||||
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;
|
||||
|
@ -736,6 +737,7 @@ static struct usb_serial_driver ark3116_device = {
|
|||
.ioctl = ark3116_ioctl,
|
||||
.tiocmget = ark3116_tiocmget,
|
||||
.tiocmset = ark3116_tiocmset,
|
||||
.get_icount = ark3116_get_icount,
|
||||
.open = ark3116_open,
|
||||
.close = ark3116_close,
|
||||
.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
|
||||
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -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_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
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 void edge_disconnect(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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct serial_struct __user *retinfo)
|
||||
{
|
||||
|
@ -1650,7 +1677,6 @@ static int get_serial_info(struct edgeport_port *edge_port,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* SerialIoctl
|
||||
* 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 async_icount cnow;
|
||||
struct async_icount cprev;
|
||||
struct serial_icounter_struct icount;
|
||||
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ static struct usb_serial_driver edgeport_2port_device = {
|
|||
.set_termios = edge_set_termios,
|
||||
.tiocmget = edge_tiocmget,
|
||||
.tiocmset = edge_tiocmset,
|
||||
.get_icount = edge_get_icount,
|
||||
.write = edge_write,
|
||||
.write_room = edge_write_room,
|
||||
.chars_in_buffer = edge_chars_in_buffer,
|
||||
|
@ -152,6 +153,7 @@ static struct usb_serial_driver edgeport_4port_device = {
|
|||
.set_termios = edge_set_termios,
|
||||
.tiocmget = edge_tiocmget,
|
||||
.tiocmset = edge_tiocmset,
|
||||
.get_icount = edge_get_icount,
|
||||
.write = edge_write,
|
||||
.write_room = edge_write_room,
|
||||
.chars_in_buffer = edge_chars_in_buffer,
|
||||
|
@ -181,6 +183,7 @@ static struct usb_serial_driver edgeport_8port_device = {
|
|||
.set_termios = edge_set_termios,
|
||||
.tiocmget = edge_tiocmget,
|
||||
.tiocmset = edge_tiocmset,
|
||||
.get_icount = edge_get_icount,
|
||||
.write = edge_write,
|
||||
.write_room = edge_write_room,
|
||||
.chars_in_buffer = edge_chars_in_buffer,
|
||||
|
@ -209,6 +212,7 @@ static struct usb_serial_driver epic_device = {
|
|||
.set_termios = edge_set_termios,
|
||||
.tiocmget = edge_tiocmget,
|
||||
.tiocmset = edge_tiocmset,
|
||||
.get_icount = edge_get_icount,
|
||||
.write = edge_write,
|
||||
.write_room = edge_write_room,
|
||||
.chars_in_buffer = edge_chars_in_buffer,
|
||||
|
|
|
@ -2510,6 +2510,27 @@ static int edge_tiocmget(struct tty_struct *tty, struct file *file)
|
|||
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,
|
||||
struct serial_struct __user *retinfo)
|
||||
{
|
||||
|
@ -2572,13 +2593,6 @@ static int edge_ioctl(struct tty_struct *tty, struct file *file,
|
|||
}
|
||||
/* not reached */
|
||||
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;
|
||||
}
|
||||
|
@ -2758,6 +2772,7 @@ static struct usb_serial_driver edgeport_1port_device = {
|
|||
.set_termios = edge_set_termios,
|
||||
.tiocmget = edge_tiocmget,
|
||||
.tiocmset = edge_tiocmset,
|
||||
.get_icount = edge_get_icount,
|
||||
.write = edge_write,
|
||||
.write_room = edge_write_room,
|
||||
.chars_in_buffer = edge_chars_in_buffer,
|
||||
|
|
|
@ -1896,10 +1896,37 @@ static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
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,
|
||||
unsigned int __user *value)
|
||||
{
|
||||
unsigned int mcr ;
|
||||
unsigned int mcr;
|
||||
unsigned int arg;
|
||||
|
||||
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 async_icount cnow;
|
||||
struct async_icount cprev;
|
||||
struct serial_icounter_struct icount;
|
||||
|
||||
mos7720_port = usb_get_serial_port_data(port);
|
||||
if (mos7720_port == NULL)
|
||||
|
@ -2021,29 +2047,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
|
|||
}
|
||||
/* NOTREACHED */
|
||||
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;
|
||||
|
@ -2212,6 +2215,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
|
|||
.ioctl = mos7720_ioctl,
|
||||
.tiocmget = mos7720_tiocmget,
|
||||
.tiocmset = mos7720_tiocmset,
|
||||
.get_icount = mos7720_get_icount,
|
||||
.set_termios = mos7720_set_termios,
|
||||
.write = mos7720_write,
|
||||
.write_room = mos7720_write_room,
|
||||
|
|
|
@ -2209,6 +2209,34 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
|
|||
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
|
||||
* 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 cprev;
|
||||
struct serial_icounter_struct icount;
|
||||
|
||||
if (mos7840_port_paranoia_check(port, __func__)) {
|
||||
dbg("%s", "Invalid port");
|
||||
|
@ -2282,29 +2309,6 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
|
|||
/* NOTREACHED */
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -2674,6 +2678,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
|
|||
.break_ctl = mos7840_break,
|
||||
.tiocmget = mos7840_tiocmget,
|
||||
.tiocmset = mos7840_tiocmset,
|
||||
.get_icount = mos7840_get_icount,
|
||||
.attach = mos7840_startup,
|
||||
.disconnect = mos7840_disconnect,
|
||||
.release = mos7840_release,
|
||||
|
|
|
@ -416,12 +416,34 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
|
|||
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,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -433,27 +455,6 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
|
|||
case TIOCMIWAIT:
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -726,6 +727,7 @@ static struct usb_serial_driver ssu100_device = {
|
|||
.process_read_urb = ssu100_process_read_urb,
|
||||
.tiocmget = ssu100_tiocmget,
|
||||
.tiocmset = ssu100_tiocmset,
|
||||
.get_icount = ssu100_get_icount,
|
||||
.ioctl = ssu100_ioctl,
|
||||
.set_termios = ssu100_set_termios,
|
||||
.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 int ti_ioctl(struct tty_struct *tty, struct file *file,
|
||||
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,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios);
|
||||
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,
|
||||
.tiocmget = ti_tiocmget,
|
||||
.tiocmset = ti_tiocmset,
|
||||
.get_icount = ti_get_icount,
|
||||
.break_ctl = ti_break,
|
||||
.read_int_callback = ti_interrupt_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,
|
||||
.tiocmget = ti_tiocmget,
|
||||
.tiocmset = ti_tiocmset,
|
||||
.get_icount = ti_get_icount,
|
||||
.break_ctl = ti_break,
|
||||
.read_int_callback = ti_interrupt_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,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
|
@ -830,14 +859,6 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file,
|
|||
cprev = cnow;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
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
|
||||
* 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,
|
||||
.tiocmget = serial_tiocmget,
|
||||
.tiocmset = serial_tiocmset,
|
||||
.get_icount = serial_get_icount,
|
||||
.cleanup = serial_cleanup,
|
||||
.install = serial_install,
|
||||
.proc_fops = &serial_proc_fops,
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/fdtable.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
/*
|
||||
|
@ -136,6 +139,160 @@ static const struct file_operations proc_tty_drivers_operations = {
|
|||
.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
|
||||
* 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_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
|
||||
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 TCSETSF2 _IOW('T', 0x2D, struct termios2)
|
||||
#define TIOCGRS485 0x542E
|
||||
#ifndef TIOCSRS485
|
||||
#define TIOCSRS485 0x542F
|
||||
#endif
|
||||
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
||||
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
|
||||
#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
|
||||
|
|
|
@ -5,10 +5,15 @@
|
|||
#ifndef __ALTUART_H
|
||||
#define __ALTUART_H
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
struct altera_uart_platform_uart {
|
||||
unsigned long mapbase; /* Physical address base */
|
||||
unsigned int irq; /* Interrupt vector */
|
||||
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 */
|
||||
|
|
|
@ -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 void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org);
|
||||
extern void vcs_scr_updated(struct vc_data *vc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,8 @@ struct plat_serial8250_port {
|
|||
void (*set_termios)(struct uart_port *,
|
||||
struct ktermios *new,
|
||||
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 void serial8250_do_set_termios(struct uart_port *port,
|
||||
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
|
||||
|
|
|
@ -289,6 +289,8 @@ struct uart_port {
|
|||
void (*set_termios)(struct uart_port *,
|
||||
struct ktermios *new,
|
||||
struct ktermios *old);
|
||||
void (*pm)(struct uart_port *, unsigned int state,
|
||||
unsigned int old);
|
||||
unsigned int irq; /* irq number */
|
||||
unsigned long irqflags; /* irq flags */
|
||||
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 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.
|
||||
*/
|
||||
|
|
|
@ -256,6 +256,7 @@ struct tty_operations;
|
|||
struct tty_struct {
|
||||
int magic;
|
||||
struct kref kref;
|
||||
struct device *dev;
|
||||
struct tty_driver *driver;
|
||||
const struct tty_operations *ops;
|
||||
int index;
|
||||
|
@ -465,7 +466,7 @@ extern void proc_clear_tty(struct task_struct *p);
|
|||
extern struct tty_struct *get_current_tty(void);
|
||||
extern void tty_default_fops(struct file_operations *fops);
|
||||
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 initialize_tty_struct(struct tty_struct *tty,
|
||||
struct tty_driver *driver, int idx);
|
||||
|
|
|
@ -224,6 +224,12 @@
|
|||
* unless the tty also has a valid tty->termiox pointer.
|
||||
*
|
||||
* 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>
|
||||
|
@ -232,6 +238,7 @@
|
|||
|
||||
struct tty_struct;
|
||||
struct tty_driver;
|
||||
struct serial_icounter_struct;
|
||||
|
||||
struct tty_operations {
|
||||
struct tty_struct * (*lookup)(struct tty_driver *driver,
|
||||
|
@ -268,6 +275,8 @@ struct tty_operations {
|
|||
unsigned int set, unsigned int clear);
|
||||
int (*resize)(struct tty_struct *tty, struct winsize *ws);
|
||||
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
|
||||
int (*poll_init)(struct tty_driver *driver, int line, char *options);
|
||||
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 (*tiocmset)(struct tty_struct *tty, struct file *file,
|
||||
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
|
||||
be an attached tty at this point */
|
||||
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");
|
||||
break;
|
||||
|
||||
case TIOCGICOUNT:
|
||||
BT_DBG("TIOCGICOUNT");
|
||||
break;
|
||||
|
||||
case TIOCGSERIAL:
|
||||
BT_ERR("TIOCGSERIAL is not supported");
|
||||
return -ENOIOCTLCMD;
|
||||
|
|
Loading…
Reference in a new issue