altera-comp.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * altera-comp.c
  4. *
  5. * altera FPGA driver
  6. *
  7. * Copyright (C) Altera Corporation 1998-2001
  8. * Copyright (C) 2010 NetUP Inc.
  9. * Copyright (C) 2010 Igor M. Liplianin <[email protected]>
  10. */
  11. #include <linux/kernel.h>
  12. #include "altera-exprt.h"
  13. #define SHORT_BITS 16
  14. #define CHAR_BITS 8
  15. #define DATA_BLOB_LENGTH 3
  16. #define MATCH_DATA_LENGTH 8192
  17. #define ALTERA_REQUEST_SIZE 1024
  18. #define ALTERA_BUFFER_SIZE (MATCH_DATA_LENGTH + ALTERA_REQUEST_SIZE)
  19. static u32 altera_bits_req(u32 n)
  20. {
  21. u32 result = SHORT_BITS;
  22. if (n == 0)
  23. result = 1;
  24. else {
  25. /* Look for the highest non-zero bit position */
  26. while ((n & (1 << (SHORT_BITS - 1))) == 0) {
  27. n <<= 1;
  28. --result;
  29. }
  30. }
  31. return result;
  32. }
  33. static u32 altera_read_packed(u8 *buffer, u32 bits, u32 *bits_avail,
  34. u32 *in_index)
  35. {
  36. u32 result = 0;
  37. u32 shift = 0;
  38. u32 databyte = 0;
  39. while (bits > 0) {
  40. databyte = buffer[*in_index];
  41. result |= (((databyte >> (CHAR_BITS - *bits_avail))
  42. & (0xff >> (CHAR_BITS - *bits_avail))) << shift);
  43. if (bits <= *bits_avail) {
  44. result &= (0xffff >> (SHORT_BITS - (bits + shift)));
  45. *bits_avail -= bits;
  46. bits = 0;
  47. } else {
  48. ++(*in_index);
  49. shift += *bits_avail;
  50. bits -= *bits_avail;
  51. *bits_avail = CHAR_BITS;
  52. }
  53. }
  54. return result;
  55. }
  56. u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version)
  57. {
  58. u32 i, j, data_length = 0L;
  59. u32 offset, length;
  60. u32 match_data_length = MATCH_DATA_LENGTH;
  61. u32 bits_avail = CHAR_BITS;
  62. u32 in_index = 0L;
  63. if (version > 0)
  64. --match_data_length;
  65. for (i = 0; i < out_length; ++i)
  66. out[i] = 0;
  67. /* Read number of bytes in data. */
  68. for (i = 0; i < sizeof(in_length); ++i) {
  69. data_length = data_length | (
  70. altera_read_packed(in,
  71. CHAR_BITS,
  72. &bits_avail,
  73. &in_index) << (i * CHAR_BITS));
  74. }
  75. if (data_length > out_length) {
  76. data_length = 0L;
  77. return data_length;
  78. }
  79. i = 0;
  80. while (i < data_length) {
  81. /* A 0 bit indicates literal data. */
  82. if (altera_read_packed(in, 1, &bits_avail,
  83. &in_index) == 0) {
  84. for (j = 0; j < DATA_BLOB_LENGTH; ++j) {
  85. if (i < data_length) {
  86. out[i] = (u8)altera_read_packed(in,
  87. CHAR_BITS,
  88. &bits_avail,
  89. &in_index);
  90. i++;
  91. }
  92. }
  93. } else {
  94. /* A 1 bit indicates offset/length to follow. */
  95. offset = altera_read_packed(in, altera_bits_req((s16)
  96. (i > match_data_length ?
  97. match_data_length : i)),
  98. &bits_avail,
  99. &in_index);
  100. length = altera_read_packed(in, CHAR_BITS,
  101. &bits_avail,
  102. &in_index);
  103. for (j = 0; j < length; ++j) {
  104. if (i < data_length) {
  105. out[i] = out[i - offset];
  106. i++;
  107. }
  108. }
  109. }
  110. }
  111. return data_length;
  112. }