1 /****************************************************************
3 Siano Mobile Silicon, Inc.
4 MDTV receiver kernel modules.
5 Copyright (C) 2006-2008, Uri Shkolnik
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ****************************************************************/
21 #include "smsspicommon.h"
22 #include "smsdbg_prn.h"
23 #include "smscoreapi.h"
25 extern volatile bool g_libdownload;
28 static struct _rx_buffer_st *smsspi_handle_unused_bytes_buf(
30 struct _rx_buffer_st *buf, int offset, int len,
33 struct _rx_buffer_st *tmp_buf;
36 tmp_buf = dev->cb.allocate_rx_buf(dev->context,
41 sms_err("Failed to allocate RX buffer.\n");
44 if (unused_bytes > 0) {
45 /* Copy the remaining bytes to the end of
46 alignment block (256 bytes) so next read
49 (((unused_bytes + SPI_PACKET_SIZE -
50 1) >> SPI_PACKET_SIZE_BITS) <<
51 SPI_PACKET_SIZE_BITS);
52 memset(tmp_buf->ptr, 0,
53 align_block - unused_bytes);
54 memcpy((char *)tmp_buf->ptr +
55 (align_block - unused_bytes),
56 (char *)buf->ptr + offset + len -
57 unused_bytes, unused_bytes);
59 //sms_info("smsspi_handle_unused_bytes_buf unused_bytes=0x%x offset=0x%x len=0x%x \n",unused_bytes,offset,len);
63 static struct _rx_buffer_st *smsspi_common_find_msg(struct _spi_dev *dev,
64 struct _rx_buffer_st *buf, int offset, int len,
65 int *unused_bytes, int *missing_bytes)
68 int recieved_bytes, padded_msg_len;
71 unsigned char *ptr = (unsigned char *)buf->ptr + offset;
72 if (unused_bytes == NULL || missing_bytes == NULL)
78 //sms_info("entering with %d bytes.\n", len);
79 for (i = 0; i < len; i++, ptr++) {
80 switch (dev->rxState) {
83 ((*ptr & 0xff) == 0xa5) ? RxsWait_5a : RxsWait_a5;
84 dev->rxPacket.msg_offset =
85 (unsigned long)ptr - (unsigned long)buf->ptr + 4;
88 if ((*ptr & 0xff) == 0x5a) {
89 dev->rxState = RxsWait_e7;
92 dev->rxState = RxsWait_a5;
94 ptr--; // re-scan current byte
96 //sms_info("state %d.\n", dev->rxState);
99 if ((*ptr & 0xff) == 0xe7) {
100 dev->rxState = RxsWait_7e;
103 dev->rxState = RxsWait_a5;
105 ptr--; // re-scan current byte
107 //sms_info("state %d.\n", dev->rxState);
110 if ((*ptr & 0xff) == 0x7e) {
111 dev->rxState = RxsTypeH;
114 dev->rxState = RxsWait_a5;
116 ptr--; // re-scan current byte
118 //sms_info("state %d.\n", dev->rxState);
121 dev->rxPacket.msg_buf = buf;
122 dev->rxPacket.msg_offset =
123 (unsigned long)ptr - (unsigned long)buf->ptr;
124 dev->rxState = RxsTypeL;
125 //sms_info("state %d.\n", dev->rxState);
128 dev->rxState = RxsGetSrcId;
129 //sms_info("state %d.\n", dev->rxState);
132 dev->rxState = RxsGetDstId;
133 //sms_info("state %d.\n", dev->rxState);
136 dev->rxState = RxsGetLenL;
137 //sms_info("state %d.\n", dev->rxState);
140 dev->rxState = RxsGetLenH;
141 dev->rxPacket.msg_len = (*ptr & 0xff);
142 //sms_info("state %d.\n", dev->rxState);
145 dev->rxState = RxsFlagsL;
146 dev->rxPacket.msg_len += (*ptr & 0xff) << 8;
147 //sms_info("state %d.\n", dev->rxState);
150 dev->rxState = RxsFlagsH;
151 dev->rxPacket.msg_flags = (*ptr & 0xff);
152 //sms_info("state %d.\n", dev->rxState);
155 dev->rxState = RxsData;
156 dev->rxPacket.msg_flags += (*ptr & 0xff) << 8;
157 //sms_info("state %d.\n", dev->rxState);
161 len + offset - dev->rxPacket.msg_offset;
163 ((dev->rxPacket.msg_len + 4 + SPI_PACKET_SIZE -
164 1) >> SPI_PACKET_SIZE_BITS) <<
165 SPI_PACKET_SIZE_BITS;
166 if (recieved_bytes < padded_msg_len) {
168 *missing_bytes = padded_msg_len -
174 dev->rxState = RxsWait_a5;
175 if (dev->cb.msg_found_cb) {
178 msg_flags & MSG_HDR_FLAG_SPLIT_MSG_HDR) {
181 msg_flags >> 8) & 0x3;
182 /* The FW aligned the message data
183 therefore - alignment bytes should be
184 thrown away. Throw the alignment bytes
185 by moving the header ahead over the
190 (unsigned char *)dev->rxPacket.
192 dev->rxPacket.msg_offset;
194 /* Restore header to original
195 state before alignment changes
198 (ptr[5] << 8) | ptr[4];
200 ptr[5] = length >> 8;
201 ptr[4] = length & 0xff;
202 /* Zero alignment flags */
205 for (i = MSG_HDR_LEN - 1;
210 dev->rxPacket.msg_offset +=
215 sms_info("Msg found and sent to callback func.\n");
217 /* force all messages to start on
219 msg_offset = dev->rxPacket.msg_offset;
220 if (msg_offset & 0x3) {
221 msg_offset &= (~0x3);
222 memmove((unsigned char *)
223 (dev->rxPacket.msg_buf->ptr)
226 (dev->rxPacket.msg_buf->ptr)
227 + dev->rxPacket.msg_offset,
228 dev->rxPacket.msg_len -
233 len + offset - dev->rxPacket.msg_offset -
234 dev->rxPacket.msg_len;
236 /* In any case we got here - unused_bytes
237 * should not be 0 Because we want to force
238 * reading at least 256 after the end
239 of any found message */
240 if (*unused_bytes == 0)
243 buf = smsspi_handle_unused_bytes_buf(dev, buf,
244 offset, len, *unused_bytes);
248 dev->cb.msg_found_cb(dev->context,
249 dev->rxPacket.msg_buf,
251 dev->rxPacket.msg_len -
258 sms_info("Msg found but no callback. therefore - thrown away.\n");
260 sms_info("state %d.\n", dev->rxState);
265 if (dev->rxState == RxsWait_a5) {
271 /* Workaround to corner case: if the last byte of the buffer
272 is "a5" (first byte of the preamble), the host thinks it should
273 send another 256 bytes. In case the a5 is the firmware
274 underflow byte, this will cause an infinite loop, so we check
275 for this case explicity. */
276 if (dev->rxState == RxsWait_5a) {
277 if ((*(ptr - 2) == 0xa5) || (*((unsigned int*)(ptr-4)) == *((unsigned int*)(ptr-8)))) {
278 dev->rxState = RxsWait_a5;
286 if ((dev->rxState == RxsWait_5a) && (*(ptr - 2) == 0xa5)) {
287 dev->rxState = RxsWait_a5;
294 if (dev->rxPacket.msg_offset >= (SPI_PACKET_SIZE + 4))
295 /* adding 4 for the preamble. */
296 { /*The packet will be copied to a new buffer
297 and rescaned by the state machine */
298 struct _rx_buffer_st *tmp_buf = buf;
299 *unused_bytes = dev->rxState - RxsWait_a5;
300 tmp_buf = smsspi_handle_unused_bytes_buf(dev, buf,
301 offset, len, *unused_bytes);
302 dev->rxState = RxsWait_a5;
304 dev->cb.free_rx_buf(dev->context, buf);
310 /* report missing bytes and continue
311 with message scan. */
313 *missing_bytes = SPI_PACKET_SIZE;
319 void smsspi_common_transfer_msg(struct _spi_dev *dev, struct _spi_msg *txmsg,
322 int len, bytes_to_transfer;
323 unsigned long tx_phy_addr;
324 int missing_bytes, tx_bytes;
325 int offset, unused_bytes;
328 struct _rx_buffer_st *buf, *tmp_buf;
332 tx_bytes = txmsg->len;
335 (((tx_bytes + SPI_PACKET_SIZE -
336 1) >> SPI_PACKET_SIZE_BITS) <<
337 SPI_PACKET_SIZE_BITS);
339 bytes_to_transfer = (((tx_bytes + 3) >> 2) << 2);
341 tx_phy_addr = txmsg->buf_phy_addr;
342 len = min(bytes_to_transfer, RX_PACKET_SIZE);
343 dev->cb.transfer_data_cb(dev->phy_context,(unsigned char *)txbuf,tx_phy_addr,NULL,NULL,len);
349 // sms_info("g_libdownload == %d!!!!!!!!!!!!!!!!!\n",g_libdownload);
350 if(g_libdownload == false)
352 // sms_info("g_libdownload == false!!!!!!!!!!!!!!!!!\n");
354 if (!dev->cb.transfer_data_cb) {
355 sms_err("function called while module is not initialized.\n");
359 bytes_to_transfer = SPI_PACKET_SIZE;
364 tx_bytes = txmsg->len;
367 (((tx_bytes + SPI_PACKET_SIZE -
368 1) >> SPI_PACKET_SIZE_BITS) <<
369 SPI_PACKET_SIZE_BITS);
371 bytes_to_transfer = (((tx_bytes + 3) >> 2) << 2);
373 tx_phy_addr = txmsg->buf_phy_addr;
379 dev->cb.allocate_rx_buf(dev->context,
380 RX_PACKET_SIZE + SPI_PACKET_SIZE);
384 sms_err("Failed to allocate RX buffer.\n");
387 while (bytes_to_transfer || unused_bytes) {
388 if ((unused_bytes <= 0) && (bytes_to_transfer > 0)) {
389 len = min(bytes_to_transfer, RX_PACKET_SIZE);
390 //sms_info("transfering block of %d bytes\n", len);
391 dev->cb.transfer_data_cb(dev->phy_context,
392 (unsigned char *)txbuf,
394 (unsigned char *)buf->ptr + offset,
395 buf->phy_addr + offset, len);
399 smsspi_common_find_msg(dev, buf, offset, len,
400 &unused_bytes, &missing_bytes);
403 //sms_info("smsspi_common_transfer_msg unused_bytes=0x%x missing_bytes=0x%x\n", unused_bytes, missing_bytes);
405 if (bytes_to_transfer)
406 bytes_to_transfer -= len;
415 /* In this case tmp_buf is a new buffer allocated
416 * in smsspi_common_find_msg
417 * and it already contains the unused bytes */
418 if (unused_bytes > 0) {
420 (((unused_bytes + SPI_PACKET_SIZE -
421 1) >> SPI_PACKET_SIZE_BITS) <<
422 SPI_PACKET_SIZE_BITS);
433 if (bytes_to_transfer < missing_bytes) {
435 (((missing_bytes + SPI_PACKET_SIZE -
436 1) >> SPI_PACKET_SIZE_BITS) <<
437 SPI_PACKET_SIZE_BITS);
438 sms_info("a message was found, adding bytes to transfer, txmsg %d, total %d\n"
439 , tx_bytes, bytes_to_transfer);
444 dev->cb.free_rx_buf(dev->context, buf);
450 int smsspicommon_init(struct _spi_dev *dev, void *context, void *phy_context,
451 struct _spi_dev_cb_st *cb)
453 sms_info("entering.\n");
454 if (cb->transfer_data_cb == 0 ||
455 cb->msg_found_cb == 0 ||
456 cb->allocate_rx_buf == 0 || cb->free_rx_buf == 0) {
457 sms_err("Invalid input parameters of init routine.\n");
460 dev->context = context;
461 dev->phy_context = phy_context;
462 memcpy(&dev->cb, cb, sizeof(struct _spi_dev_cb_st));
463 dev->rxState = RxsWait_a5;
464 sms_info("exiting.\n");