fmc-dump.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * Copyright (C) 2013 CERN (www.cern.ch)
  3. * Author: Alessandro Rubini <rubini@gnudd.com>
  4. *
  5. * Released according to the GNU GPL, version 2 or any later version.
  6. *
  7. * This work is part of the White Rabbit project, a research effort led
  8. * by CERN, the European Institute for Nuclear Research.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/moduleparam.h>
  12. #include <linux/device.h>
  13. #include <linux/fmc.h>
  14. #include <linux/fmc-sdb.h>
  15. static int fmc_must_dump_eeprom;
  16. module_param_named(dump_eeprom, fmc_must_dump_eeprom, int, 0644);
  17. static int fmc_must_dump_sdb;
  18. module_param_named(dump_sdb, fmc_must_dump_sdb, int, 0644);
  19. #define LINELEN 16
  20. /* Dumping 8k takes oh so much: avoid duplicate lines */
  21. static const uint8_t *dump_line(int addr, const uint8_t *line,
  22. const uint8_t *prev)
  23. {
  24. int i;
  25. if (!prev || memcmp(line, prev, LINELEN)) {
  26. pr_info("%04x: ", addr);
  27. for (i = 0; i < LINELEN; ) {
  28. printk(KERN_CONT "%02x", line[i]);
  29. i++;
  30. printk(i & 3 ? " " : i & (LINELEN - 1) ? " " : "\n");
  31. }
  32. return line;
  33. }
  34. /* repeated line */
  35. if (line == prev + LINELEN)
  36. pr_info("[...]\n");
  37. return prev;
  38. }
  39. void fmc_dump_eeprom(const struct fmc_device *fmc)
  40. {
  41. const uint8_t *line, *prev;
  42. int i;
  43. if (!fmc_must_dump_eeprom)
  44. return;
  45. pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
  46. fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
  47. pr_info("FMC: dumping eeprom 0x%x (%i) bytes\n", fmc->eeprom_len,
  48. fmc->eeprom_len);
  49. line = fmc->eeprom;
  50. prev = NULL;
  51. for (i = 0; i < fmc->eeprom_len; i += LINELEN, line += LINELEN)
  52. prev = dump_line(i, line, prev);
  53. }
  54. void fmc_dump_sdb(const struct fmc_device *fmc)
  55. {
  56. const uint8_t *line, *prev;
  57. int i, len;
  58. if (!fmc->sdb)
  59. return;
  60. if (!fmc_must_dump_sdb)
  61. return;
  62. /* If the argument is not-zero, do simple dump (== show) */
  63. if (fmc_must_dump_sdb > 0)
  64. fmc_show_sdb_tree(fmc);
  65. if (fmc_must_dump_sdb == 1)
  66. return;
  67. /* If bigger than 1, dump it seriously, to help debugging */
  68. /*
  69. * Here we should really use libsdbfs (which is designed to
  70. * work in kernel space as well) , but it doesn't support
  71. * directories yet, and it requires better intergration (it
  72. * should be used instead of fmc-specific code).
  73. *
  74. * So, lazily, just dump the top-level array
  75. */
  76. pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
  77. fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
  78. pr_info("FMC: poor dump of sdb first level:\n");
  79. len = fmc->sdb->len * sizeof(union sdb_record);
  80. line = (void *)fmc->sdb->record;
  81. prev = NULL;
  82. for (i = 0; i < len; i += LINELEN, line += LINELEN)
  83. prev = dump_line(i, line, prev);
  84. return;
  85. }