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 46static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf) 47{ 48 return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); 49} 50static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL); 51 52 53static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf) 54{ 55 return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards); 56} 57static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL); 58 59 60static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf) 61{ 62 return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); 63} 64static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL); 65 66static 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 71static 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} 80static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgnc_driver_debug_show, dgnc_driver_debug_store); 81 82 83static 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 88static 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} 97static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgnc_driver_rawreadok_show, dgnc_driver_rawreadok_store); 98 99 100static 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 105static 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} 114static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store); 115 116 117void 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 133void 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 160static 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} 178static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL); 179 180static 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} 194static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL); 195 196 197static 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} 212static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL); 213 214 215static 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} 229static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL); 230 231 232static 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} 257static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL); 258 259 260static 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} 274static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL); 275 276 277static 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} 291static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL); 292 293 294static 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} 308static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL); 309 310 311static 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} 325static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL); 326 327 328static 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} 342static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL); 343 344 345static 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} 359static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL); 360 361 362static 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} 376static 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 */ 382void 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 */ 405void 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 422static 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} 444static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL); 445 446 447static 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} 469static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL); 470 471 472static 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} 503static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL); 504 505 506static 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} 528static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL); 529 530 531static 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} 553static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL); 554 555 556static 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} 578static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL); 579 580 581static 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} 603static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL); 604 605 606static 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} 628static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL); 629 630 631static 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} 653static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL); 654 655 656static 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} 678static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL); 679 680 681static 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} 705static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL); 706 707 708static 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 724static struct attribute_group dgnc_tty_attribute_group = { 725 .name = NULL, 726 .attrs = dgnc_sysfs_tty_entries, 727}; 728 729 730void 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 746void dgnc_remove_tty_sysfs(struct device *c) 747{ 748 sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group); 749} 750 751