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