xref: /linux/drivers/tty/vcc.c (revision ce808b746325975192d8cd1d29f1ec03d5b6b0fc)
155bd2133SJag Raman /* vcc.c: sun4v virtual channel concentrator
255bd2133SJag Raman  *
355bd2133SJag Raman  * Copyright (C) 2017 Oracle. All rights reserved.
455bd2133SJag Raman  */
555bd2133SJag Raman 
655bd2133SJag Raman #include <linux/module.h>
7*ce808b74SJag Raman #include <linux/tty.h>
855bd2133SJag Raman 
9f283ebd5SJag Raman #define DRV_MODULE_NAME		"vcc"
10f283ebd5SJag Raman #define DRV_MODULE_VERSION	"1.1"
11f283ebd5SJag Raman #define DRV_MODULE_RELDATE	"July 1, 2017"
12f283ebd5SJag Raman 
13*ce808b74SJag Raman static char version[] =
14*ce808b74SJag Raman 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
15*ce808b74SJag Raman 
16f283ebd5SJag Raman MODULE_DESCRIPTION("Sun LDOM virtual console concentrator driver");
17f283ebd5SJag Raman MODULE_LICENSE("GPL");
18f283ebd5SJag Raman MODULE_VERSION(DRV_MODULE_VERSION);
19f283ebd5SJag Raman 
20*ce808b74SJag Raman #define VCC_MAX_PORTS		1024
21*ce808b74SJag Raman #define VCC_MINOR_START		0	/* must be zero */
22*ce808b74SJag Raman 
23*ce808b74SJag Raman static const char vcc_driver_name[] = "vcc";
24*ce808b74SJag Raman static const char vcc_device_node[] = "vcc";
25*ce808b74SJag Raman static struct tty_driver *vcc_tty_driver;
26*ce808b74SJag Raman 
27f283ebd5SJag Raman int vcc_dbg;
28f283ebd5SJag Raman int vcc_dbg_ldc;
29f283ebd5SJag Raman int vcc_dbg_vio;
30f283ebd5SJag Raman 
31f283ebd5SJag Raman module_param(vcc_dbg, uint, 0664);
32f283ebd5SJag Raman module_param(vcc_dbg_ldc, uint, 0664);
33f283ebd5SJag Raman module_param(vcc_dbg_vio, uint, 0664);
34f283ebd5SJag Raman 
35f283ebd5SJag Raman #define VCC_DBG_DRV	0x1
36f283ebd5SJag Raman #define VCC_DBG_LDC	0x2
37f283ebd5SJag Raman #define VCC_DBG_PKT	0x4
38f283ebd5SJag Raman 
39f283ebd5SJag Raman #define vccdbg(f, a...)						\
40f283ebd5SJag Raman 	do {							\
41f283ebd5SJag Raman 		if (vcc_dbg & VCC_DBG_DRV)			\
42f283ebd5SJag Raman 			pr_info(f, ## a);			\
43f283ebd5SJag Raman 	} while (0)						\
44f283ebd5SJag Raman 
45f283ebd5SJag Raman #define vccdbgl(l)						\
46f283ebd5SJag Raman 	do {							\
47f283ebd5SJag Raman 		if (vcc_dbg & VCC_DBG_LDC)			\
48f283ebd5SJag Raman 			ldc_print(l);				\
49f283ebd5SJag Raman 	} while (0)						\
50f283ebd5SJag Raman 
51f283ebd5SJag Raman #define vccdbgp(pkt)						\
52f283ebd5SJag Raman 	do {							\
53f283ebd5SJag Raman 		if (vcc_dbg & VCC_DBG_PKT) {			\
54f283ebd5SJag Raman 			int i;					\
55f283ebd5SJag Raman 			for (i = 0; i < pkt.tag.stype; i++)	\
56f283ebd5SJag Raman 				pr_info("[%c]", pkt.data[i]);	\
57f283ebd5SJag Raman 		}						\
58f283ebd5SJag Raman 	} while (0)						\
59f283ebd5SJag Raman 
60*ce808b74SJag Raman /* Note: Be careful when adding flags to this line discipline.  Don't
61*ce808b74SJag Raman  * add anything that will cause echoing or we'll go into recursive
62*ce808b74SJag Raman  * loop echoing chars back and forth with the console drivers.
63*ce808b74SJag Raman  */
64*ce808b74SJag Raman static struct ktermios vcc_tty_termios = {
65*ce808b74SJag Raman 	.c_iflag = IGNBRK | IGNPAR,
66*ce808b74SJag Raman 	.c_oflag = OPOST,
67*ce808b74SJag Raman 	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
68*ce808b74SJag Raman 	.c_cc = INIT_C_CC,
69*ce808b74SJag Raman 	.c_ispeed = 38400,
70*ce808b74SJag Raman 	.c_ospeed = 38400
71*ce808b74SJag Raman };
72*ce808b74SJag Raman 
73*ce808b74SJag Raman static const struct tty_operations vcc_ops;
74*ce808b74SJag Raman 
75*ce808b74SJag Raman #define VCC_TTY_FLAGS   (TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_REAL_RAW)
76*ce808b74SJag Raman 
77*ce808b74SJag Raman static int vcc_tty_init(void)
78*ce808b74SJag Raman {
79*ce808b74SJag Raman 	int rv;
80*ce808b74SJag Raman 
81*ce808b74SJag Raman 	pr_info("VCC: %s\n", version);
82*ce808b74SJag Raman 
83*ce808b74SJag Raman 	vcc_tty_driver = tty_alloc_driver(VCC_MAX_PORTS, VCC_TTY_FLAGS);
84*ce808b74SJag Raman 	if (!vcc_tty_driver) {
85*ce808b74SJag Raman 		pr_err("VCC: TTY driver alloc failed\n");
86*ce808b74SJag Raman 		return -ENOMEM;
87*ce808b74SJag Raman 	}
88*ce808b74SJag Raman 
89*ce808b74SJag Raman 	vcc_tty_driver->driver_name = vcc_driver_name;
90*ce808b74SJag Raman 	vcc_tty_driver->name = vcc_device_node;
91*ce808b74SJag Raman 
92*ce808b74SJag Raman 	vcc_tty_driver->minor_start = VCC_MINOR_START;
93*ce808b74SJag Raman 	vcc_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
94*ce808b74SJag Raman 	vcc_tty_driver->init_termios = vcc_tty_termios;
95*ce808b74SJag Raman 
96*ce808b74SJag Raman 	tty_set_operations(vcc_tty_driver, &vcc_ops);
97*ce808b74SJag Raman 
98*ce808b74SJag Raman 	rv = tty_register_driver(vcc_tty_driver);
99*ce808b74SJag Raman 	if (rv) {
100*ce808b74SJag Raman 		pr_err("VCC: TTY driver registration failed\n");
101*ce808b74SJag Raman 		put_tty_driver(vcc_tty_driver);
102*ce808b74SJag Raman 		vcc_tty_driver = NULL;
103*ce808b74SJag Raman 		return rv;
104*ce808b74SJag Raman 	}
105*ce808b74SJag Raman 
106*ce808b74SJag Raman 	vccdbg("VCC: TTY driver registered\n");
107*ce808b74SJag Raman 
108*ce808b74SJag Raman 	return 0;
109*ce808b74SJag Raman }
110*ce808b74SJag Raman 
111*ce808b74SJag Raman static void vcc_tty_exit(void)
112*ce808b74SJag Raman {
113*ce808b74SJag Raman 	tty_unregister_driver(vcc_tty_driver);
114*ce808b74SJag Raman 	put_tty_driver(vcc_tty_driver);
115*ce808b74SJag Raman 	vccdbg("VCC: TTY driver unregistered\n");
116*ce808b74SJag Raman 
117*ce808b74SJag Raman 	vcc_tty_driver = NULL;
118*ce808b74SJag Raman }
119*ce808b74SJag Raman 
12055bd2133SJag Raman static int __init vcc_init(void)
12155bd2133SJag Raman {
122*ce808b74SJag Raman 	int rv;
123*ce808b74SJag Raman 
124*ce808b74SJag Raman 	rv = vcc_tty_init();
125*ce808b74SJag Raman 	if (rv) {
126*ce808b74SJag Raman 		pr_err("VCC: TTY init failed\n");
127*ce808b74SJag Raman 		return rv;
128*ce808b74SJag Raman 	}
129*ce808b74SJag Raman 
130*ce808b74SJag Raman 	return rv;
13155bd2133SJag Raman }
13255bd2133SJag Raman 
13355bd2133SJag Raman static void __exit vcc_exit(void)
13455bd2133SJag Raman {
135*ce808b74SJag Raman 	vcc_tty_exit();
136*ce808b74SJag Raman 	vccdbg("VCC: TTY driver unregistered\n");
13755bd2133SJag Raman }
13855bd2133SJag Raman 
13955bd2133SJag Raman module_init(vcc_init);
14055bd2133SJag Raman module_exit(vcc_exit);
141