1 /*
2  * Copyright 2004 Digi International (www.digi.com)
3  *      Scott H Kilau <Scott_Kilau at digi dot com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  * PURPOSE.  See the GNU General Public License for more details.
14  */
15 
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/ctype.h>
19 #include <linux/string.h>
20 #include <linux/serial_reg.h>
21 #include <linux/device.h>
22 #include <linux/pci.h>
23 #include <linux/kdev_t.h>
24 
25 #include "dgnc_driver.h"
26 #include "dgnc_mgmt.h"
27 
dgnc_driver_version_show(struct device_driver * ddp,char * buf)28 static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf)
29 {
30 	return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
31 }
32 static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL);
33 
dgnc_driver_boards_show(struct device_driver * ddp,char * buf)34 static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf)
35 {
36 	return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards);
37 }
38 static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL);
39 
dgnc_driver_maxboards_show(struct device_driver * ddp,char * buf)40 static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf)
41 {
42 	return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
43 }
44 static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL);
45 
dgnc_driver_pollrate_show(struct device_driver * ddp,char * buf)46 static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf)
47 {
48 	return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick);
49 }
50 
dgnc_driver_pollrate_store(struct device_driver * ddp,const char * buf,size_t count)51 static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp,
52 					  const char *buf, size_t count)
53 {
54 	unsigned long flags;
55 	int tick;
56 	int ret;
57 
58 	ret = sscanf(buf, "%d\n", &tick);
59 	if (ret != 1)
60 		return -EINVAL;
61 
62 	spin_lock_irqsave(&dgnc_poll_lock, flags);
63 	dgnc_poll_tick = tick;
64 	spin_unlock_irqrestore(&dgnc_poll_lock, flags);
65 
66 	return count;
67 }
68 static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show,
69 		   dgnc_driver_pollrate_store);
70 
dgnc_create_driver_sysfiles(struct pci_driver * dgnc_driver)71 void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver)
72 {
73 	int rc = 0;
74 	struct device_driver *driverfs = &dgnc_driver->driver;
75 
76 	rc |= driver_create_file(driverfs, &driver_attr_version);
77 	rc |= driver_create_file(driverfs, &driver_attr_boards);
78 	rc |= driver_create_file(driverfs, &driver_attr_maxboards);
79 	rc |= driver_create_file(driverfs, &driver_attr_pollrate);
80 	if (rc)
81 		pr_err("DGNC: sysfs driver_create_file failed!\n");
82 }
83 
dgnc_remove_driver_sysfiles(struct pci_driver * dgnc_driver)84 void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
85 {
86 	struct device_driver *driverfs = &dgnc_driver->driver;
87 
88 	driver_remove_file(driverfs, &driver_attr_version);
89 	driver_remove_file(driverfs, &driver_attr_boards);
90 	driver_remove_file(driverfs, &driver_attr_maxboards);
91 	driver_remove_file(driverfs, &driver_attr_pollrate);
92 }
93 
94 #define DGNC_VERIFY_BOARD(p, bd)				\
95 	do {							\
96 		if (!p)						\
97 			return 0;				\
98 								\
99 		bd = dev_get_drvdata(p);			\
100 		if (!bd || bd->magic != DGNC_BOARD_MAGIC)	\
101 			return 0;				\
102 		if (bd->state != BOARD_READY)			\
103 			return 0;				\
104 	} while (0)
105 
dgnc_vpd_show(struct device * p,struct device_attribute * attr,char * buf)106 static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr,
107 			     char *buf)
108 {
109 	struct dgnc_board *bd;
110 	int count = 0;
111 	int i = 0;
112 
113 	DGNC_VERIFY_BOARD(p, bd);
114 
115 	count += sprintf(buf + count,
116 		"\n      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F");
117 	for (i = 0; i < 0x40 * 2; i++) {
118 		if (!(i % 16))
119 			count += sprintf(buf + count, "\n%04X ", i * 2);
120 		count += sprintf(buf + count, "%02X ", bd->vpd[i]);
121 	}
122 	count += sprintf(buf + count, "\n");
123 
124 	return count;
125 }
126 static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL);
127 
dgnc_serial_number_show(struct device * p,struct device_attribute * attr,char * buf)128 static ssize_t dgnc_serial_number_show(struct device *p,
129 				       struct device_attribute *attr, char *buf)
130 {
131 	struct dgnc_board *bd;
132 	int count = 0;
133 
134 	DGNC_VERIFY_BOARD(p, bd);
135 
136 	if (bd->serial_num[0] == '\0')
137 		count += sprintf(buf + count, "<UNKNOWN>\n");
138 	else
139 		count += sprintf(buf + count, "%s\n", bd->serial_num);
140 
141 	return count;
142 }
143 static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL);
144 
dgnc_ports_state_show(struct device * p,struct device_attribute * attr,char * buf)145 static ssize_t dgnc_ports_state_show(struct device *p,
146 				     struct device_attribute *attr, char *buf)
147 {
148 	struct dgnc_board *bd;
149 	int count = 0;
150 	int i = 0;
151 
152 	DGNC_VERIFY_BOARD(p, bd);
153 
154 	for (i = 0; i < bd->nasync; i++) {
155 		count += snprintf(buf + count, PAGE_SIZE - count,
156 			"%d %s\n", bd->channels[i]->ch_portnum,
157 			bd->channels[i]->ch_open_count ? "Open" : "Closed");
158 	}
159 	return count;
160 }
161 static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL);
162 
dgnc_ports_baud_show(struct device * p,struct device_attribute * attr,char * buf)163 static ssize_t dgnc_ports_baud_show(struct device *p,
164 				    struct device_attribute *attr, char *buf)
165 {
166 	struct dgnc_board *bd;
167 	int count = 0;
168 	int i = 0;
169 
170 	DGNC_VERIFY_BOARD(p, bd);
171 
172 	for (i = 0; i < bd->nasync; i++) {
173 		count +=  snprintf(buf + count, PAGE_SIZE - count,
174 			"%d %d\n", bd->channels[i]->ch_portnum,
175 			bd->channels[i]->ch_old_baud);
176 	}
177 	return count;
178 }
179 static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL);
180 
dgnc_ports_msignals_show(struct device * p,struct device_attribute * attr,char * buf)181 static ssize_t dgnc_ports_msignals_show(struct device *p,
182 					struct device_attribute *attr,
183 					char *buf)
184 {
185 	struct dgnc_board *bd;
186 	int count = 0;
187 	int i = 0;
188 
189 	DGNC_VERIFY_BOARD(p, bd);
190 
191 	for (i = 0; i < bd->nasync; i++) {
192 		if (bd->channels[i]->ch_open_count) {
193 			count += snprintf(buf + count, PAGE_SIZE - count,
194 				"%d %s %s %s %s %s %s\n",
195 				bd->channels[i]->ch_portnum,
196 				(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
197 				(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
198 				(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
199 				(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
200 				(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
201 				(bd->channels[i]->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
202 		} else {
203 			count += snprintf(buf + count, PAGE_SIZE - count,
204 				"%d\n", bd->channels[i]->ch_portnum);
205 		}
206 	}
207 	return count;
208 }
209 static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL);
210 
dgnc_ports_iflag_show(struct device * p,struct device_attribute * attr,char * buf)211 static ssize_t dgnc_ports_iflag_show(struct device *p,
212 				     struct device_attribute *attr, char *buf)
213 {
214 	struct dgnc_board *bd;
215 	int count = 0;
216 	int i = 0;
217 
218 	DGNC_VERIFY_BOARD(p, bd);
219 
220 	for (i = 0; i < bd->nasync; i++) {
221 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
222 			bd->channels[i]->ch_portnum,
223 			bd->channels[i]->ch_c_iflag);
224 	}
225 	return count;
226 }
227 static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL);
228 
dgnc_ports_cflag_show(struct device * p,struct device_attribute * attr,char * buf)229 static ssize_t dgnc_ports_cflag_show(struct device *p,
230 				     struct device_attribute *attr, char *buf)
231 {
232 	struct dgnc_board *bd;
233 	int count = 0;
234 	int i = 0;
235 
236 	DGNC_VERIFY_BOARD(p, bd);
237 
238 	for (i = 0; i < bd->nasync; i++) {
239 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
240 			bd->channels[i]->ch_portnum,
241 			bd->channels[i]->ch_c_cflag);
242 	}
243 	return count;
244 }
245 static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL);
246 
dgnc_ports_oflag_show(struct device * p,struct device_attribute * attr,char * buf)247 static ssize_t dgnc_ports_oflag_show(struct device *p,
248 				     struct device_attribute *attr, char *buf)
249 {
250 	struct dgnc_board *bd;
251 	int count = 0;
252 	int i = 0;
253 
254 	DGNC_VERIFY_BOARD(p, bd);
255 
256 	for (i = 0; i < bd->nasync; i++) {
257 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
258 			bd->channels[i]->ch_portnum,
259 			bd->channels[i]->ch_c_oflag);
260 	}
261 	return count;
262 }
263 static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL);
264 
dgnc_ports_lflag_show(struct device * p,struct device_attribute * attr,char * buf)265 static ssize_t dgnc_ports_lflag_show(struct device *p,
266 				     struct device_attribute *attr, char *buf)
267 {
268 	struct dgnc_board *bd;
269 	int count = 0;
270 	int i = 0;
271 
272 	DGNC_VERIFY_BOARD(p, bd);
273 
274 	for (i = 0; i < bd->nasync; i++) {
275 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
276 			bd->channels[i]->ch_portnum,
277 			bd->channels[i]->ch_c_lflag);
278 	}
279 	return count;
280 }
281 static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL);
282 
dgnc_ports_digi_flag_show(struct device * p,struct device_attribute * attr,char * buf)283 static ssize_t dgnc_ports_digi_flag_show(struct device *p,
284 					 struct device_attribute *attr,
285 					 char *buf)
286 {
287 	struct dgnc_board *bd;
288 	int count = 0;
289 	int i = 0;
290 
291 	DGNC_VERIFY_BOARD(p, bd);
292 
293 	for (i = 0; i < bd->nasync; i++) {
294 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
295 			bd->channels[i]->ch_portnum,
296 			bd->channels[i]->ch_digi.digi_flags);
297 	}
298 	return count;
299 }
300 static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL);
301 
dgnc_ports_rxcount_show(struct device * p,struct device_attribute * attr,char * buf)302 static ssize_t dgnc_ports_rxcount_show(struct device *p,
303 				       struct device_attribute *attr, char *buf)
304 {
305 	struct dgnc_board *bd;
306 	int count = 0;
307 	int i = 0;
308 
309 	DGNC_VERIFY_BOARD(p, bd);
310 
311 	for (i = 0; i < bd->nasync; i++) {
312 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
313 			bd->channels[i]->ch_portnum,
314 			bd->channels[i]->ch_rxcount);
315 	}
316 	return count;
317 }
318 static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL);
319 
dgnc_ports_txcount_show(struct device * p,struct device_attribute * attr,char * buf)320 static ssize_t dgnc_ports_txcount_show(struct device *p,
321 				       struct device_attribute *attr, char *buf)
322 {
323 	struct dgnc_board *bd;
324 	int count = 0;
325 	int i = 0;
326 
327 	DGNC_VERIFY_BOARD(p, bd);
328 
329 	for (i = 0; i < bd->nasync; i++) {
330 		count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
331 			bd->channels[i]->ch_portnum,
332 			bd->channels[i]->ch_txcount);
333 	}
334 	return count;
335 }
336 static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL);
337 
338 /* this function creates the sys files that will export each signal status
339  * to sysfs each value will be put in a separate filename
340  */
dgnc_create_ports_sysfiles(struct dgnc_board * bd)341 void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
342 {
343 	int rc = 0;
344 
345 	dev_set_drvdata(&bd->pdev->dev, bd);
346 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_state);
347 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_baud);
348 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals);
349 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag);
350 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag);
351 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag);
352 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag);
353 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
354 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
355 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount);
356 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_vpd);
357 	rc |= device_create_file(&bd->pdev->dev, &dev_attr_serial_number);
358 	if (rc)
359 		dev_err(&bd->pdev->dev, "dgnc: sysfs device_create_file failed!\n");
360 }
361 
362 /* removes all the sys files created for that port */
dgnc_remove_ports_sysfiles(struct dgnc_board * bd)363 void dgnc_remove_ports_sysfiles(struct dgnc_board *bd)
364 {
365 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_state);
366 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud);
367 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals);
368 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag);
369 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag);
370 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag);
371 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag);
372 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
373 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
374 	device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount);
375 	device_remove_file(&bd->pdev->dev, &dev_attr_vpd);
376 	device_remove_file(&bd->pdev->dev, &dev_attr_serial_number);
377 }
378 
dgnc_tty_state_show(struct device * d,struct device_attribute * attr,char * buf)379 static ssize_t dgnc_tty_state_show(struct device *d,
380 				   struct device_attribute *attr, char *buf)
381 {
382 	struct dgnc_board *bd;
383 	struct channel_t *ch;
384 	struct un_t *un;
385 
386 	if (!d)
387 		return 0;
388 	un = dev_get_drvdata(d);
389 	if (!un || un->magic != DGNC_UNIT_MAGIC)
390 		return 0;
391 	ch = un->un_ch;
392 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
393 		return 0;
394 	bd = ch->ch_bd;
395 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
396 		return 0;
397 	if (bd->state != BOARD_READY)
398 		return 0;
399 
400 	return snprintf(buf, PAGE_SIZE, "%s",
401 			un->un_open_count ? "Open" : "Closed");
402 }
403 static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL);
404 
dgnc_tty_baud_show(struct device * d,struct device_attribute * attr,char * buf)405 static ssize_t dgnc_tty_baud_show(struct device *d,
406 				  struct device_attribute *attr, char *buf)
407 {
408 	struct dgnc_board *bd;
409 	struct channel_t *ch;
410 	struct un_t *un;
411 
412 	if (!d)
413 		return 0;
414 	un = dev_get_drvdata(d);
415 	if (!un || un->magic != DGNC_UNIT_MAGIC)
416 		return 0;
417 	ch = un->un_ch;
418 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
419 		return 0;
420 	bd = ch->ch_bd;
421 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
422 		return 0;
423 	if (bd->state != BOARD_READY)
424 		return 0;
425 
426 	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
427 }
428 static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL);
429 
dgnc_tty_msignals_show(struct device * d,struct device_attribute * attr,char * buf)430 static ssize_t dgnc_tty_msignals_show(struct device *d,
431 				      struct device_attribute *attr, char *buf)
432 {
433 	struct dgnc_board *bd;
434 	struct channel_t *ch;
435 	struct un_t *un;
436 
437 	if (!d)
438 		return 0;
439 	un = dev_get_drvdata(d);
440 	if (!un || un->magic != DGNC_UNIT_MAGIC)
441 		return 0;
442 	ch = un->un_ch;
443 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
444 		return 0;
445 	bd = ch->ch_bd;
446 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
447 		return 0;
448 	if (bd->state != BOARD_READY)
449 		return 0;
450 
451 	if (ch->ch_open_count) {
452 		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
453 			(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
454 			(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
455 			(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
456 			(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
457 			(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
458 			(ch->ch_mistat & UART_MSR_RI)  ? "RI"  : "");
459 	}
460 	return 0;
461 }
462 static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL);
463 
dgnc_tty_iflag_show(struct device * d,struct device_attribute * attr,char * buf)464 static ssize_t dgnc_tty_iflag_show(struct device *d,
465 				   struct device_attribute *attr, char *buf)
466 {
467 	struct dgnc_board *bd;
468 	struct channel_t *ch;
469 	struct un_t *un;
470 
471 	if (!d)
472 		return 0;
473 	un = dev_get_drvdata(d);
474 	if (!un || un->magic != DGNC_UNIT_MAGIC)
475 		return 0;
476 	ch = un->un_ch;
477 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
478 		return 0;
479 	bd = ch->ch_bd;
480 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
481 		return 0;
482 	if (bd->state != BOARD_READY)
483 		return 0;
484 
485 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
486 }
487 static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL);
488 
dgnc_tty_cflag_show(struct device * d,struct device_attribute * attr,char * buf)489 static ssize_t dgnc_tty_cflag_show(struct device *d,
490 				   struct device_attribute *attr, char *buf)
491 {
492 	struct dgnc_board *bd;
493 	struct channel_t *ch;
494 	struct un_t *un;
495 
496 	if (!d)
497 		return 0;
498 	un = dev_get_drvdata(d);
499 	if (!un || un->magic != DGNC_UNIT_MAGIC)
500 		return 0;
501 	ch = un->un_ch;
502 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
503 		return 0;
504 	bd = ch->ch_bd;
505 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
506 		return 0;
507 	if (bd->state != BOARD_READY)
508 		return 0;
509 
510 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
511 }
512 static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL);
513 
dgnc_tty_oflag_show(struct device * d,struct device_attribute * attr,char * buf)514 static ssize_t dgnc_tty_oflag_show(struct device *d,
515 				   struct device_attribute *attr, char *buf)
516 {
517 	struct dgnc_board *bd;
518 	struct channel_t *ch;
519 	struct un_t *un;
520 
521 	if (!d)
522 		return 0;
523 	un = dev_get_drvdata(d);
524 	if (!un || un->magic != DGNC_UNIT_MAGIC)
525 		return 0;
526 	ch = un->un_ch;
527 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
528 		return 0;
529 	bd = ch->ch_bd;
530 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
531 		return 0;
532 	if (bd->state != BOARD_READY)
533 		return 0;
534 
535 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
536 }
537 static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL);
538 
dgnc_tty_lflag_show(struct device * d,struct device_attribute * attr,char * buf)539 static ssize_t dgnc_tty_lflag_show(struct device *d,
540 				   struct device_attribute *attr, char *buf)
541 {
542 	struct dgnc_board *bd;
543 	struct channel_t *ch;
544 	struct un_t *un;
545 
546 	if (!d)
547 		return 0;
548 	un = dev_get_drvdata(d);
549 	if (!un || un->magic != DGNC_UNIT_MAGIC)
550 		return 0;
551 	ch = un->un_ch;
552 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
553 		return 0;
554 	bd = ch->ch_bd;
555 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
556 		return 0;
557 	if (bd->state != BOARD_READY)
558 		return 0;
559 
560 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
561 }
562 static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL);
563 
dgnc_tty_digi_flag_show(struct device * d,struct device_attribute * attr,char * buf)564 static ssize_t dgnc_tty_digi_flag_show(struct device *d,
565 				       struct device_attribute *attr, char *buf)
566 {
567 	struct dgnc_board *bd;
568 	struct channel_t *ch;
569 	struct un_t *un;
570 
571 	if (!d)
572 		return 0;
573 	un = dev_get_drvdata(d);
574 	if (!un || un->magic != DGNC_UNIT_MAGIC)
575 		return 0;
576 	ch = un->un_ch;
577 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
578 		return 0;
579 	bd = ch->ch_bd;
580 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
581 		return 0;
582 	if (bd->state != BOARD_READY)
583 		return 0;
584 
585 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
586 }
587 static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL);
588 
dgnc_tty_rxcount_show(struct device * d,struct device_attribute * attr,char * buf)589 static ssize_t dgnc_tty_rxcount_show(struct device *d,
590 				     struct device_attribute *attr, char *buf)
591 {
592 	struct dgnc_board *bd;
593 	struct channel_t *ch;
594 	struct un_t *un;
595 
596 	if (!d)
597 		return 0;
598 	un = dev_get_drvdata(d);
599 	if (!un || un->magic != DGNC_UNIT_MAGIC)
600 		return 0;
601 	ch = un->un_ch;
602 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
603 		return 0;
604 	bd = ch->ch_bd;
605 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
606 		return 0;
607 	if (bd->state != BOARD_READY)
608 		return 0;
609 
610 	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
611 }
612 static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL);
613 
dgnc_tty_txcount_show(struct device * d,struct device_attribute * attr,char * buf)614 static ssize_t dgnc_tty_txcount_show(struct device *d,
615 				     struct device_attribute *attr, char *buf)
616 {
617 	struct dgnc_board *bd;
618 	struct channel_t *ch;
619 	struct un_t *un;
620 
621 	if (!d)
622 		return 0;
623 	un = dev_get_drvdata(d);
624 	if (!un || un->magic != DGNC_UNIT_MAGIC)
625 		return 0;
626 	ch = un->un_ch;
627 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
628 		return 0;
629 	bd = ch->ch_bd;
630 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
631 		return 0;
632 	if (bd->state != BOARD_READY)
633 		return 0;
634 
635 	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
636 }
637 static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL);
638 
dgnc_tty_name_show(struct device * d,struct device_attribute * attr,char * buf)639 static ssize_t dgnc_tty_name_show(struct device *d,
640 				  struct device_attribute *attr, char *buf)
641 {
642 	struct dgnc_board *bd;
643 	struct channel_t *ch;
644 	struct un_t *un;
645 
646 	if (!d)
647 		return 0;
648 	un = dev_get_drvdata(d);
649 	if (!un || un->magic != DGNC_UNIT_MAGIC)
650 		return 0;
651 	ch = un->un_ch;
652 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
653 		return 0;
654 	bd = ch->ch_bd;
655 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
656 		return 0;
657 	if (bd->state != BOARD_READY)
658 		return 0;
659 
660 	return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
661 		(un->un_type == DGNC_PRINT) ? "pr" : "tty",
662 		bd->boardnum + 1, 'a' + ch->ch_portnum);
663 }
664 static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL);
665 
666 static struct attribute *dgnc_sysfs_tty_entries[] = {
667 	&dev_attr_state.attr,
668 	&dev_attr_baud.attr,
669 	&dev_attr_msignals.attr,
670 	&dev_attr_iflag.attr,
671 	&dev_attr_cflag.attr,
672 	&dev_attr_oflag.attr,
673 	&dev_attr_lflag.attr,
674 	&dev_attr_digi_flag.attr,
675 	&dev_attr_rxcount.attr,
676 	&dev_attr_txcount.attr,
677 	&dev_attr_custom_name.attr,
678 	NULL
679 };
680 
681 static struct attribute_group dgnc_tty_attribute_group = {
682 	.name = NULL,
683 	.attrs = dgnc_sysfs_tty_entries,
684 };
685 
dgnc_create_tty_sysfs(struct un_t * un,struct device * c)686 void dgnc_create_tty_sysfs(struct un_t *un, struct device *c)
687 {
688 	int ret;
689 
690 	ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group);
691 	if (ret) {
692 		dev_err(c, "dgnc: failed to create sysfs tty device attributes.\n");
693 		sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
694 		return;
695 	}
696 
697 	dev_set_drvdata(c, un);
698 }
699 
dgnc_remove_tty_sysfs(struct device * c)700 void dgnc_remove_tty_sysfs(struct device *c)
701 {
702 	sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
703 }
704 
705