Commit | Line | Data |
---|---|---|
0b99d589 LL |
1 | /* |
2 | * Copyright 2004 Digi International (www.digi.com) | |
3 | * Scott H Kilau <Scott_Kilau at digi dot com> | |
7a97deb2 | 4 | * |
0b99d589 LL |
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 | |
7a97deb2 | 12 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
0b99d589 | 13 | * PURPOSE. See the GNU General Public License for more details. |
0b99d589 LL |
14 | */ |
15 | ||
16 | ||
17 | #include <linux/kernel.h> | |
0b99d589 LL |
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> | |
7a97deb2 | 25 | |
0b99d589 | 26 | #include "dgnc_driver.h" |
0b99d589 LL |
27 | #include "dgnc_mgmt.h" |
28 | ||
29 | ||
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 | ||
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 | ||
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 | ||
0b99d589 | 50 | |
0b99d589 LL |
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 | ||
56 | static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count) | |
57 | { | |
fb33aa47 RD |
58 | int ret; |
59 | ||
60 | ret = sscanf(buf, "%d\n", &dgnc_poll_tick); | |
61 | if (ret != 1) | |
62 | return -EINVAL; | |
0b99d589 LL |
63 | return count; |
64 | } | |
65 | static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store); | |
66 | ||
67 | ||
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); | |
0b99d589 | 76 | rc |= driver_create_file(driverfs, &driver_attr_pollrate); |
77b55d84 | 77 | if (rc) |
c471c989 | 78 | pr_err("DGNC: sysfs driver_create_file failed!\n"); |
0b99d589 LL |
79 | } |
80 | ||
81 | ||
82 | void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver) | |
83 | { | |
84 | struct device_driver *driverfs = &dgnc_driver->driver; | |
e8756d4a | 85 | |
0b99d589 LL |
86 | driver_remove_file(driverfs, &driver_attr_version); |
87 | driver_remove_file(driverfs, &driver_attr_boards); | |
88 | driver_remove_file(driverfs, &driver_attr_maxboards); | |
0b99d589 | 89 | driver_remove_file(driverfs, &driver_attr_pollrate); |
0b99d589 LL |
90 | } |
91 | ||
92 | ||
635c4efa JM |
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) | |
0b99d589 LL |
104 | |
105 | ||
106 | ||
107 | static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf) | |
108 | { | |
03425f55 | 109 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
127 | static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf) | |
128 | { | |
03425f55 | 129 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
144 | static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf) | |
145 | { | |
03425f55 | 146 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
162 | static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf) | |
163 | { | |
03425f55 | 164 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
179 | static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf) | |
180 | { | |
03425f55 | 181 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
207 | static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf) | |
208 | { | |
03425f55 | 209 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
224 | static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf) | |
225 | { | |
03425f55 | 226 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
241 | static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf) | |
242 | { | |
03425f55 | 243 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
258 | static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf) | |
259 | { | |
03425f55 | 260 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
275 | static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf) | |
276 | { | |
03425f55 | 277 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
292 | static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf) | |
293 | { | |
03425f55 | 294 | struct dgnc_board *bd; |
0b99d589 LL |
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 | ||
309 | static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf) | |
310 | { | |
03425f55 | 311 | struct dgnc_board *bd; |
0b99d589 LL |
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 | */ | |
03425f55 | 329 | void dgnc_create_ports_sysfiles(struct dgnc_board *bd) |
0b99d589 LL |
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); | |
77b55d84 | 346 | if (rc) |
c28645e3 | 347 | dev_err(&bd->pdev->dev, "dgnc: sysfs device_create_file failed!\n"); |
0b99d589 LL |
348 | } |
349 | ||
350 | ||
351 | /* removes all the sys files created for that port */ | |
03425f55 | 352 | void dgnc_remove_ports_sysfiles(struct dgnc_board *bd) |
0b99d589 LL |
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 | ||
369 | static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf) | |
370 | { | |
03425f55 | 371 | struct dgnc_board *bd; |
0b99d589 LL |
372 | struct channel_t *ch; |
373 | struct un_t *un; | |
374 | ||
375 | if (!d) | |
8f90ef80 | 376 | return 0; |
0e4f66b4 | 377 | un = dev_get_drvdata(d); |
0b99d589 | 378 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 379 | return 0; |
0b99d589 LL |
380 | ch = un->un_ch; |
381 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 382 | return 0; |
0b99d589 LL |
383 | bd = ch->ch_bd; |
384 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 385 | return 0; |
0b99d589 | 386 | if (bd->state != BOARD_READY) |
8f90ef80 | 387 | return 0; |
0b99d589 LL |
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 | ||
394 | static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf) | |
395 | { | |
03425f55 | 396 | struct dgnc_board *bd; |
0b99d589 LL |
397 | struct channel_t *ch; |
398 | struct un_t *un; | |
399 | ||
400 | if (!d) | |
8f90ef80 | 401 | return 0; |
0e4f66b4 | 402 | un = dev_get_drvdata(d); |
0b99d589 | 403 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 404 | return 0; |
0b99d589 LL |
405 | ch = un->un_ch; |
406 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 407 | return 0; |
0b99d589 LL |
408 | bd = ch->ch_bd; |
409 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 410 | return 0; |
0b99d589 | 411 | if (bd->state != BOARD_READY) |
8f90ef80 | 412 | return 0; |
0b99d589 LL |
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 | ||
419 | static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf) | |
420 | { | |
03425f55 | 421 | struct dgnc_board *bd; |
0b99d589 LL |
422 | struct channel_t *ch; |
423 | struct un_t *un; | |
424 | ||
425 | if (!d) | |
8f90ef80 | 426 | return 0; |
0e4f66b4 | 427 | un = dev_get_drvdata(d); |
0b99d589 | 428 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 429 | return 0; |
0b99d589 LL |
430 | ch = un->un_ch; |
431 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 432 | return 0; |
0b99d589 LL |
433 | bd = ch->ch_bd; |
434 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 435 | return 0; |
0b99d589 | 436 | if (bd->state != BOARD_READY) |
8f90ef80 | 437 | return 0; |
0b99d589 LL |
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 | ||
453 | static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf) | |
454 | { | |
03425f55 | 455 | struct dgnc_board *bd; |
0b99d589 LL |
456 | struct channel_t *ch; |
457 | struct un_t *un; | |
458 | ||
459 | if (!d) | |
8f90ef80 | 460 | return 0; |
0e4f66b4 | 461 | un = dev_get_drvdata(d); |
0b99d589 | 462 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 463 | return 0; |
0b99d589 LL |
464 | ch = un->un_ch; |
465 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 466 | return 0; |
0b99d589 LL |
467 | bd = ch->ch_bd; |
468 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 469 | return 0; |
0b99d589 | 470 | if (bd->state != BOARD_READY) |
8f90ef80 | 471 | return 0; |
0b99d589 LL |
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 | ||
478 | static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf) | |
479 | { | |
03425f55 | 480 | struct dgnc_board *bd; |
0b99d589 LL |
481 | struct channel_t *ch; |
482 | struct un_t *un; | |
483 | ||
484 | if (!d) | |
8f90ef80 | 485 | return 0; |
0e4f66b4 | 486 | un = dev_get_drvdata(d); |
0b99d589 | 487 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 488 | return 0; |
0b99d589 LL |
489 | ch = un->un_ch; |
490 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 491 | return 0; |
0b99d589 LL |
492 | bd = ch->ch_bd; |
493 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 494 | return 0; |
0b99d589 | 495 | if (bd->state != BOARD_READY) |
8f90ef80 | 496 | return 0; |
0b99d589 LL |
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 | ||
503 | static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf) | |
504 | { | |
03425f55 | 505 | struct dgnc_board *bd; |
0b99d589 LL |
506 | struct channel_t *ch; |
507 | struct un_t *un; | |
508 | ||
509 | if (!d) | |
8f90ef80 | 510 | return 0; |
0e4f66b4 | 511 | un = dev_get_drvdata(d); |
0b99d589 | 512 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 513 | return 0; |
0b99d589 LL |
514 | ch = un->un_ch; |
515 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 516 | return 0; |
0b99d589 LL |
517 | bd = ch->ch_bd; |
518 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 519 | return 0; |
0b99d589 | 520 | if (bd->state != BOARD_READY) |
8f90ef80 | 521 | return 0; |
0b99d589 LL |
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 | ||
528 | static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf) | |
529 | { | |
03425f55 | 530 | struct dgnc_board *bd; |
0b99d589 LL |
531 | struct channel_t *ch; |
532 | struct un_t *un; | |
533 | ||
534 | if (!d) | |
8f90ef80 | 535 | return 0; |
0e4f66b4 | 536 | un = dev_get_drvdata(d); |
0b99d589 | 537 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 538 | return 0; |
0b99d589 LL |
539 | ch = un->un_ch; |
540 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 541 | return 0; |
0b99d589 LL |
542 | bd = ch->ch_bd; |
543 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 544 | return 0; |
0b99d589 | 545 | if (bd->state != BOARD_READY) |
8f90ef80 | 546 | return 0; |
0b99d589 LL |
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 | ||
553 | static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf) | |
554 | { | |
03425f55 | 555 | struct dgnc_board *bd; |
0b99d589 LL |
556 | struct channel_t *ch; |
557 | struct un_t *un; | |
558 | ||
559 | if (!d) | |
8f90ef80 | 560 | return 0; |
0e4f66b4 | 561 | un = dev_get_drvdata(d); |
0b99d589 | 562 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 563 | return 0; |
0b99d589 LL |
564 | ch = un->un_ch; |
565 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 566 | return 0; |
0b99d589 LL |
567 | bd = ch->ch_bd; |
568 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 569 | return 0; |
0b99d589 | 570 | if (bd->state != BOARD_READY) |
8f90ef80 | 571 | return 0; |
0b99d589 LL |
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 | ||
578 | static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf) | |
579 | { | |
03425f55 | 580 | struct dgnc_board *bd; |
0b99d589 LL |
581 | struct channel_t *ch; |
582 | struct un_t *un; | |
583 | ||
584 | if (!d) | |
8f90ef80 | 585 | return 0; |
0e4f66b4 | 586 | un = dev_get_drvdata(d); |
0b99d589 | 587 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 588 | return 0; |
0b99d589 LL |
589 | ch = un->un_ch; |
590 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 591 | return 0; |
0b99d589 LL |
592 | bd = ch->ch_bd; |
593 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 594 | return 0; |
0b99d589 | 595 | if (bd->state != BOARD_READY) |
8f90ef80 | 596 | return 0; |
0b99d589 LL |
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 | ||
603 | static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf) | |
604 | { | |
03425f55 | 605 | struct dgnc_board *bd; |
0b99d589 LL |
606 | struct channel_t *ch; |
607 | struct un_t *un; | |
608 | ||
609 | if (!d) | |
8f90ef80 | 610 | return 0; |
0e4f66b4 | 611 | un = dev_get_drvdata(d); |
0b99d589 | 612 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 613 | return 0; |
0b99d589 LL |
614 | ch = un->un_ch; |
615 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 616 | return 0; |
0b99d589 LL |
617 | bd = ch->ch_bd; |
618 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 619 | return 0; |
0b99d589 | 620 | if (bd->state != BOARD_READY) |
8f90ef80 | 621 | return 0; |
0b99d589 LL |
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 | ||
628 | static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf) | |
629 | { | |
03425f55 | 630 | struct dgnc_board *bd; |
0b99d589 LL |
631 | struct channel_t *ch; |
632 | struct un_t *un; | |
633 | ||
634 | if (!d) | |
8f90ef80 | 635 | return 0; |
0e4f66b4 | 636 | un = dev_get_drvdata(d); |
0b99d589 | 637 | if (!un || un->magic != DGNC_UNIT_MAGIC) |
8f90ef80 | 638 | return 0; |
0b99d589 LL |
639 | ch = un->un_ch; |
640 | if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) | |
8f90ef80 | 641 | return 0; |
0b99d589 LL |
642 | bd = ch->ch_bd; |
643 | if (!bd || bd->magic != DGNC_BOARD_MAGIC) | |
8f90ef80 | 644 | return 0; |
0b99d589 | 645 | if (bd->state != BOARD_READY) |
8f90ef80 | 646 | return 0; |
0b99d589 LL |
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, | |
7a97deb2 | 661 | &dev_attr_oflag.attr, |
0b99d589 LL |
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 = { | |
0a60eb33 LL |
672 | .name = NULL, |
673 | .attrs = dgnc_sysfs_tty_entries, | |
0b99d589 LL |
674 | }; |
675 | ||
676 | ||
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) { | |
0f33ae1e | 683 | dev_err(c, "dgnc: failed to create sysfs tty device attributes.\n"); |
0b99d589 LL |
684 | sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group); |
685 | return; | |
686 | } | |
687 | ||
688 | dev_set_drvdata(c, un); | |
689 | ||
690 | } | |
691 | ||
7a97deb2 | 692 | |
0b99d589 LL |
693 | void dgnc_remove_tty_sysfs(struct device *c) |
694 | { | |
695 | sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group); | |
696 | } | |
697 |