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