Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * altera-comp.c
0004  *
0005  * altera FPGA driver
0006  *
0007  * Copyright (C) Altera Corporation 1998-2001
0008  * Copyright (C) 2010 NetUP Inc.
0009  * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include "altera-exprt.h"
0014 
0015 #define SHORT_BITS      16
0016 #define CHAR_BITS       8
0017 #define DATA_BLOB_LENGTH    3
0018 #define MATCH_DATA_LENGTH   8192
0019 #define ALTERA_REQUEST_SIZE 1024
0020 #define ALTERA_BUFFER_SIZE  (MATCH_DATA_LENGTH + ALTERA_REQUEST_SIZE)
0021 
0022 static u32 altera_bits_req(u32 n)
0023 {
0024     u32 result = SHORT_BITS;
0025 
0026     if (n == 0)
0027         result = 1;
0028     else {
0029         /* Look for the highest non-zero bit position */
0030         while ((n & (1 << (SHORT_BITS - 1))) == 0) {
0031             n <<= 1;
0032             --result;
0033         }
0034     }
0035 
0036     return result;
0037 }
0038 
0039 static u32 altera_read_packed(u8 *buffer, u32 bits, u32 *bits_avail,
0040                             u32 *in_index)
0041 {
0042     u32 result = 0;
0043     u32 shift = 0;
0044     u32 databyte = 0;
0045 
0046     while (bits > 0) {
0047         databyte = buffer[*in_index];
0048         result |= (((databyte >> (CHAR_BITS - *bits_avail))
0049             & (0xff >> (CHAR_BITS - *bits_avail))) << shift);
0050 
0051         if (bits <= *bits_avail) {
0052             result &= (0xffff >> (SHORT_BITS - (bits + shift)));
0053             *bits_avail -= bits;
0054             bits = 0;
0055         } else {
0056             ++(*in_index);
0057             shift += *bits_avail;
0058             bits -= *bits_avail;
0059             *bits_avail = CHAR_BITS;
0060         }
0061     }
0062 
0063     return result;
0064 }
0065 
0066 u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version)
0067 {
0068     u32 i, j, data_length = 0L;
0069     u32 offset, length;
0070     u32 match_data_length = MATCH_DATA_LENGTH;
0071     u32 bits_avail = CHAR_BITS;
0072     u32 in_index = 0L;
0073 
0074     if (version > 0)
0075         --match_data_length;
0076 
0077     for (i = 0; i < out_length; ++i)
0078         out[i] = 0;
0079 
0080     /* Read number of bytes in data. */
0081     for (i = 0; i < sizeof(in_length); ++i) {
0082         data_length = data_length | (
0083             altera_read_packed(in,
0084                     CHAR_BITS,
0085                     &bits_avail,
0086                     &in_index) << (i * CHAR_BITS));
0087     }
0088 
0089     if (data_length > out_length) {
0090         data_length = 0L;
0091         return data_length;
0092     }
0093 
0094     i = 0;
0095     while (i < data_length) {
0096         /* A 0 bit indicates literal data. */
0097         if (altera_read_packed(in, 1, &bits_avail,
0098                         &in_index) == 0) {
0099             for (j = 0; j < DATA_BLOB_LENGTH; ++j) {
0100                 if (i < data_length) {
0101                     out[i] = (u8)altera_read_packed(in,
0102                             CHAR_BITS,
0103                             &bits_avail,
0104                             &in_index);
0105                     i++;
0106                 }
0107             }
0108         } else {
0109             /* A 1 bit indicates offset/length to follow. */
0110             offset = altera_read_packed(in, altera_bits_req((s16)
0111                     (i > match_data_length ?
0112                         match_data_length : i)),
0113                     &bits_avail,
0114                     &in_index);
0115             length = altera_read_packed(in, CHAR_BITS,
0116                     &bits_avail,
0117                     &in_index);
0118             for (j = 0; j < length; ++j) {
0119                 if (i < data_length) {
0120                     out[i] = out[i - offset];
0121                     i++;
0122                 }
0123             }
0124         }
0125     }
0126 
0127     return data_length;
0128 }