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