These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / dgnc / dgnc_sysfs.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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 */
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
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
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
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
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
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
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
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
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
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
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
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
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
700 void dgnc_remove_tty_sysfs(struct device *c)
701 {
702         sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group);
703 }
704