eaf183bc3501a704b26389bc376e87245b6baeb3
[dahdi/tools.git] / xpp / echo_loader.c
1 /*
2  * Written by Oron Peled <oron@actcom.co.il>
3  * Copyright (C) 2008, Xorcom
4  *
5  * All rights reserved.
6  *
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.
11  *
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.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #include <stdio.h>
24 #include <assert.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <regex.h>
29 #include <sys/time.h>
30 #include "echo_loader.h"
31 #include "debug.h"
32 #include <oct6100api/oct6100_api.h>
33
34 #define DBG_MASK                0x03
35 #define TIMEOUT                 1000
36 #define ECHO_MAX_CHANS          128
37 #define ECHO_RIN_STREAM         0
38 #define ECHO_ROUT_STREAM        1
39 #define ECHO_SIN_STREAM         2
40 #define ECHO_SOUT_STREAM        3
41
42 #define ECHO_RIN_STREAM2        4
43 #define ECHO_SIN_STREAM2        6
44 #define ECHO_ROUT_STREAM2       5
45 #define ECHO_SOUT_STREAM2       7
46
47 #define EC_VER_TEST             0xABCD
48 #define EC_VER_INVALID          0xFFFF
49 static float oct_fw_load_timeout = 2.0;
50
51 struct echo_mod {
52         tPOCT6100_INSTANCE_API pApiInstance;
53         UINT32 ulEchoChanHndl[256];
54         struct astribank_device *astribank;
55         int maxchans;
56 };
57
58 enum xpp_packet_types {
59         SPI_SND_XOP     = 0x0F,
60         SPI_RCV_XOP     = 0x10,
61         TST_SND_XOP     = 0x35,
62         TST_RCV_XOP     = 0x36,
63 };
64
65 struct xpp_packet_header {
66         struct {
67                 uint16_t        len;
68                 uint8_t         op;
69                 uint8_t         unit;
70         } PACKED header;
71         union {
72                 struct {
73                         uint8_t         header;
74                         uint8_t         flags;
75                         uint8_t         addr_l;
76                         uint8_t         addr_h;
77                         uint8_t         data_l;
78                         uint8_t         data_h;
79                 } PACKED spi_pack;
80                 struct {
81                         uint8_t         tid;
82                         uint8_t         tsid;
83                 } PACKED tst_pack;
84         } alt;
85 } PACKED;
86
87 static struct usb_buffer {
88         char    data[PACKET_SIZE];
89         int     max_len;
90         int     curr;
91         /* statistics */
92         int     min_send;
93         int     max_send;
94         int     num_sends;
95         long    total_bytes;
96         struct timeval  start;
97         struct timeval  end;
98 } usb_buffer;
99
100
101 static void usb_buffer_init(struct astribank_device *astribank, struct usb_buffer *ub)
102 {
103         ub->max_len = xusb_packet_size(astribank->xusb);
104         ub->curr = 0;
105         ub->min_send = INT_MAX;
106         ub->max_send = 0;
107         ub->num_sends = 0;
108         ub->total_bytes = 0;
109         gettimeofday(&ub->start, NULL);
110 }
111
112 static long usb_buffer_usec(struct usb_buffer *ub)
113 {
114         struct timeval  now;
115
116         gettimeofday(&now, NULL);
117         return (now.tv_sec - ub->start.tv_sec) * 1000000 +
118                 (now.tv_usec - ub->start.tv_usec);
119 }
120
121 static void usb_buffer_showstatistics(struct astribank_device *astribank, struct usb_buffer *ub)
122 {
123         long    usec;
124
125         usec = usb_buffer_usec(ub);
126         INFO("%s [%s]: Octasic statistics: packet_size=[%d, %ld, %d] packets=%d, bytes=%ld msec=%ld usec/packet=%d\n",
127                 xusb_devpath(astribank->xusb),
128                 xusb_serial(astribank->xusb),
129                 ub->min_send,
130                 ub->total_bytes / ub->num_sends,
131                 ub->max_send,
132                 ub->num_sends, ub->total_bytes,
133                 usec / 1000, usec / ub->num_sends);
134 }
135
136 static int usb_buffer_flush(struct astribank_device *astribank, struct usb_buffer *ub)
137 {
138         int     ret;
139         long    t;
140         long    sec;
141         static int      last_sec;
142
143         if (ub->curr == 0)
144                 return 0;
145         ret = xusb_send(astribank->xusb, ub->data, ub->curr, TIMEOUT);
146         if(ret < 0) {
147                 ERR("xusb_send failed: %d\n", ret);
148                 return ret;
149         }
150         DBG("%s: Written %d bytes\n", __func__, ret);
151         if (ret > ub->max_send)
152                 ub->max_send = ret;
153         if (ret < ub->min_send)
154                 ub->min_send = ret;
155         ub->total_bytes += ret;
156         ub->num_sends++;
157         ub->curr = 0;
158
159         sec = usb_buffer_usec(ub) / (1000 * 1000);
160         if (sec > last_sec) {
161                 DBG("bytes/sec=%ld average len=%ld\n",
162                         ub->total_bytes / sec,
163                         ub->total_bytes / ub->num_sends);
164                 last_sec = sec;
165         }
166
167         /*
168          * Best result with high frequency firmware: 21 seconds
169          * Octasic statistics: packet_size=[10, 239, 510] packets=26806, bytes=6419640 usec=21127883 usec/packet=788
170          * t = 0.3 * ret - 150;
171          */
172         t = oct_fw_load_timeout * ret - 150;
173         if (t > 0)
174                 usleep(t);
175         return ret;
176 }
177
178 static int usb_buffer_append(struct astribank_device *astribank, struct usb_buffer *ub,
179         char *buf, int len)
180 {
181         if (ub->curr + len >= ub->max_len) {
182                 ERR("%s: buffer too small ub->curr=%d, len=%d, ub->max_len=%d\n",
183                         __func__, ub->curr, len, ub->max_len);
184                 return -ENOMEM;
185         }
186         memcpy(ub->data + ub->curr, buf, len);
187         ub->curr += len;
188         return len;
189 }
190
191 static int usb_buffer_send(struct astribank_device *astribank, struct usb_buffer *ub,
192         char *buf, int len, int timeout, int recv_answer)
193 {
194         int     ret = 0;
195
196         if (ub->curr + len >= ub->max_len) {
197                 ret = usb_buffer_flush(astribank, ub);
198                 if (ret < 0)
199                         return ret;
200         }
201
202         if ((ret = usb_buffer_append(astribank, ub, buf, len)) < 0) {
203                 return ret;
204         }
205         DBG("%s: %d bytes %s\n", __func__, len, (recv_answer) ? "recv" : "send");
206         if (recv_answer) {
207                 struct xpp_packet_header        *phead;
208
209                 ret = usb_buffer_flush(astribank, ub);
210                 if (ret < 0)
211                         return ret;
212                 ret = xusb_recv(astribank->xusb, buf, PACKET_SIZE, TIMEOUT);
213                 if(ret <= 0) {
214                         ERR("No USB packs to read: %s\n", strerror(-ret));
215                         return -EINVAL;
216                 }
217                 DBG("%s: %d bytes recv\n", __func__, ret);
218                 phead = (struct xpp_packet_header *)buf;
219                 if(phead->header.op != SPI_RCV_XOP && phead->header.op != TST_RCV_XOP) {
220                         ERR("Got unexpected reply OP=0x%02X\n", phead->header.op);
221                         dump_packet(LOG_ERR, DBG_MASK, "hexline[ERR]", buf, ret);
222                         return -EINVAL;
223                 }
224                 dump_packet(LOG_DEBUG, DBG_MASK, "dump:echoline[R]", (char *)phead, phead->header.len);
225                 switch(phead->header.op) {
226                 case SPI_RCV_XOP:
227                         ret = (phead->alt.spi_pack.data_h << 8) | phead->alt.spi_pack.data_l;
228                         break;
229                 case TST_RCV_XOP:
230                         ret = (phead->alt.tst_pack.tid << 8) | phead->alt.tst_pack.tsid;
231                         break;
232                 default:
233                         ret = -EINVAL;
234                 }
235         }
236         return ret;
237 }
238
239 int spi_send(struct astribank_device *astribank, uint16_t addr, uint16_t data, int recv_answer, int ver)
240 {
241         int                             ret;
242         char                            buf[PACKET_SIZE];
243         struct xpp_packet_header        *phead = (struct xpp_packet_header *)buf;
244         int                             pack_len;
245
246         assert(astribank != NULL);
247         pack_len = sizeof(phead->header) + sizeof(phead->alt.spi_pack);
248         phead->header.len               = pack_len;
249         phead->header.op                = SPI_SND_XOP;
250         phead->header.unit              = 0x40; /* EC has always this unit num */
251         phead->alt.spi_pack.header      = 0x05; 
252         phead->alt.spi_pack.flags       = 0x30 | (recv_answer ? 0x40: 0x00) | (ver ? 0x01: 0x00); 
253         phead->alt.spi_pack.addr_l      = (addr >> 0) & 0xFF;
254         phead->alt.spi_pack.addr_h      = (addr >> 8) & 0xFF;
255         phead->alt.spi_pack.data_l      = (data >> 0) & 0xFF;
256         phead->alt.spi_pack.data_h      = (data >> 8) & 0xFF;
257
258         dump_packet(LOG_DEBUG, DBG_MASK, "dump:echoline[W]", (char *)phead, pack_len);
259
260
261         ret = usb_buffer_send(astribank, &usb_buffer, buf, pack_len, TIMEOUT, recv_answer);
262         if(ret < 0) {
263                 ERR("usb_buffer_send failed: %d\n", ret);
264                 return ret;
265         }
266         DBG("%s: Written %d bytes\n", __func__, ret);
267         return ret;
268 }
269
270 int test_send(struct astribank_device *astribank)
271 {
272         int                             ret;
273         char                            buf[PACKET_SIZE];
274         struct xpp_packet_header       *phead = (struct xpp_packet_header *)buf;
275         int                             pack_len;
276
277         assert(astribank != NULL);
278         pack_len = sizeof(phead->header) + sizeof(phead->alt.tst_pack);
279         phead->header.len               = 6;
280         phead->header.op                = 0x35;
281         phead->header.unit              = 0x00;
282         phead->alt.tst_pack.tid         = 0x28; // EC TestId
283         phead->alt.tst_pack.tsid        = 0x00; // EC SubId
284
285         dump_packet(LOG_DEBUG, DBG_MASK, "dump:echoline[W]", (char *)phead, pack_len);
286
287
288         ret = usb_buffer_send(astribank, &usb_buffer, buf, pack_len, TIMEOUT, 1);
289         if(ret < 0) {
290                 ERR("usb_buffer_send failed: %d\n", ret);
291                 return ret;
292         }
293         DBG("%s: Written %d bytes\n", __func__, ret);
294         return ret;
295 }
296
297 void echo_send_data(struct astribank_device *astribank, const unsigned int addr, const unsigned int data)
298 {
299 /*      DBG("SEND: %04X -> [%04X]\n", data, addr);
300         DBG("\t\t[%04X] <- %04X\n", 0x0008, (addr >> 20));
301         DBG("\t\t[%04X] <- %04X\n", 0x000A, (addr >> 4) & ((1 << 16) - 1));
302         DBG("\t\t[%04X] <- %04X\n", 0x0004, data);
303         DBG("\t\t[%04X] <- %04X\n", 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1);
304  */
305
306         DBG("SND:\n");
307         spi_send(astribank, 0x0008, (addr >> 20)                        , 0, 0);
308         spi_send(astribank, 0x000A, (addr >> 4) & ((1 << 16) - 1)       , 0, 0);
309         spi_send(astribank, 0x0004, data                                , 0, 0);
310         spi_send(astribank, 0x0000, (((addr >> 1) & 0x7) << 9) | 
311                                 (1 << 8) | (3 << 12) | 1                , 0, 0);
312 }
313
314 unsigned int echo_recv_data(struct astribank_device *astribank, const unsigned int addr)
315 {
316         unsigned int data = 0x00;
317         unsigned int ret;
318
319         DBG("RCV:\n");
320         spi_send(astribank, 0x0008, (addr >> 20)                        , 0, 0);
321         spi_send(astribank, 0x000A, (addr >> 4) & ((1 << 16) - 1)       , 0, 0);
322         spi_send(astribank, 0x0000, (((addr >> 1) & 0x7) << 9) | 
323                                 (1 << 8) | 1                            , 0, 0);
324         ret = spi_send(astribank, 0x0004, data                          , 1, 0);
325         return ret; 
326 }
327
328 int load_file(char *filename, unsigned char **ppBuf, UINT32 *pLen)
329 {
330         unsigned char * pbyFileData = NULL;
331         FILE* pFile; 
332
333         DBG("Loading %s file...\n", filename);
334         pFile = fopen( filename, "rb" ); 
335         if (pFile == NULL) { 
336                 ERR("fopen\n");  
337                 return -ENODEV;
338         } 
339
340         fseek( pFile, 0L, SEEK_END ); 
341         *pLen = ftell( pFile ); 
342         fseek( pFile, 0L, SEEK_SET ); 
343
344         pbyFileData = (unsigned char *)malloc(*pLen); 
345         if (pbyFileData == NULL) { 
346                 fclose( pFile ); 
347                 ERR("malloc\n" );  
348                 return -ENODEV;
349         } else {
350                 DBG("allocated mem for pbyFileData\n");
351         }
352         fread(pbyFileData, 1, *pLen, pFile); 
353         fclose(pFile); 
354         DBG("Successful loading %s file into memory (size = %d, DUMP: first = %02X %02X, last = %02X %02X)\n", 
355                         filename, *pLen, 
356                         pbyFileData[0], pbyFileData[1],
357                         pbyFileData[(*pLen)-2], pbyFileData[(*pLen)-1]);
358         *ppBuf = pbyFileData;
359         return 0;
360 }
361
362 UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
363 {
364         ///* Why couldn't they just take a timeval like everyone else? */
365         struct timeval tv;
366         unsigned long long total_usecs;
367         unsigned int mask = ~0;
368         
369         gettimeofday(&tv, 0);
370         total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) + 
371                                   (((unsigned long long)(tv.tv_usec)));
372         f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
373         f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
374         //printf("Inside of Oct6100UserGetTime\n");
375         return cOCT6100_ERR_OK;
376 }
377
378 UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength)
379 {
380         memset(f_pAddress, f_ulPattern, f_ulLength);
381         return cOCT6100_ERR_OK;
382 }
383
384 UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength)
385 {
386         memcpy(f_pDestination, f_pSource, f_ulLength);
387         return cOCT6100_ERR_OK;
388 }
389
390 UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
391 {
392         return cOCT6100_ERR_OK;
393 }
394
395 UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
396 {
397 #ifdef OCTASIC_DEBUG
398         ERR("I should never be called! (destroy serialize object)\n");
399 #endif
400         return cOCT6100_ERR_OK;
401 }
402
403 UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
404 {
405         /* Not needed */
406         return cOCT6100_ERR_OK;
407 }
408
409 UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
410 {
411         /* Not needed */
412         return cOCT6100_ERR_OK;
413 }
414
415 UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
416 {
417         const unsigned int              addr            = f_pWriteParams->ulWriteAddress;
418         const unsigned int              data            = f_pWriteParams->usWriteData;
419         const struct echo_mod           *echo_mod       = (struct echo_mod *)(f_pWriteParams->pProcessContext);
420         struct astribank_device         *astribank      = echo_mod->astribank;
421
422         echo_send_data(astribank, addr, data);
423
424         return cOCT6100_ERR_OK;
425 }
426
427 UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
428 {
429         unsigned int                    addr;
430         unsigned int                    data;
431         unsigned int                    len             = f_pSmearParams->ulWriteLength;
432         const struct echo_mod           *echo_mod       = (struct echo_mod *)f_pSmearParams->pProcessContext;
433         struct astribank_device         *astribank      = echo_mod->astribank;
434         unsigned int                    i;
435
436         for (i = 0; i < len; i++) {
437                 addr = f_pSmearParams->ulWriteAddress + (i << 1);
438                 data = f_pSmearParams->usWriteData;
439                 echo_send_data(astribank, addr, data);
440         }
441         return cOCT6100_ERR_OK;
442 }
443
444 UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
445 {
446         unsigned int                    addr;
447         unsigned int                    data;
448         unsigned int                    len             = f_pBurstParams->ulWriteLength;
449         const struct echo_mod           *echo_mod       = (struct echo_mod *)f_pBurstParams->pProcessContext;
450         struct astribank_device         *astribank      = echo_mod->astribank;
451         unsigned int                    i;
452
453         for (i = 0; i < len; i++) {
454                 addr = f_pBurstParams->ulWriteAddress + (i << 1);
455                 data = f_pBurstParams->pusWriteData[i];
456                 echo_send_data(astribank, addr, data);
457         }
458         return cOCT6100_ERR_OK;
459 }
460
461 UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
462 {
463         const unsigned int              addr            =  f_pReadParams->ulReadAddress;
464         const struct echo_mod           *echo_mod       = (struct echo_mod *)f_pReadParams->pProcessContext;
465         struct astribank_device         *astribank      = echo_mod->astribank;
466
467         *f_pReadParams->pusReadData = echo_recv_data(astribank, addr);
468         return cOCT6100_ERR_OK;
469 }
470
471 UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
472 {
473         unsigned int                    addr;
474         unsigned int                    len             = f_pBurstParams->ulReadLength;
475         const struct echo_mod           *echo_mod       = (struct echo_mod *)f_pBurstParams->pProcessContext;
476         struct astribank_device         *astribank      = echo_mod->astribank;
477         unsigned int                    i;
478
479         for (i = 0;i < len; i++) {
480                 addr = f_pBurstParams->ulReadAddress + (i << 1);
481                 f_pBurstParams->pusReadData[i] = echo_recv_data(astribank, addr);
482         }
483         return cOCT6100_ERR_OK;
484 }
485
486 inline int get_ver(struct astribank_device *astribank)
487 {
488  
489         return  spi_send(astribank, 0, 0, 1, 1);
490 }
491
492 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
493 UINT32 init_octasic(char *filename, struct astribank_device *astribank, int is_alaw)
494 {
495         int                                                     cpld_ver;
496         struct echo_mod                                         *echo_mod;
497         UINT32                                                  nChan;
498         UINT32                                                  nSlot;
499         UINT32                                                  pcmLaw;
500         UINT32                                                  ulResult;
501
502         tOCT6100_GET_INSTANCE_SIZE                              InstanceSize;
503         tPOCT6100_INSTANCE_API                                  pApiInstance;
504         tOCT6100_CHIP_OPEN                                      OpenChip;
505
506         UINT32                                                  ulImageByteSize;
507         PUINT8                                                  pbyImageData = NULL;
508
509         /*=========================================================================*/
510         /* Channel resources.*/
511         tOCT6100_CHANNEL_OPEN                                   ChannelOpen;
512         UINT32                                                  ulChanHndl;
513
514         test_send(astribank);
515         cpld_ver = get_ver(astribank);
516         INFO("%s [%s]: Check EC_CPLD version: %d\n",
517                 xusb_devpath(astribank->xusb),
518                 xusb_serial(astribank->xusb),
519                 cpld_ver);
520         if (cpld_ver < 0)
521                 return cpld_ver;
522         else if (cpld_ver == EC_VER_TEST) {
523                 INFO("+---------------------------------------------------------+\n");
524                 INFO("| WARNING: TEST HARDWARE IS ON THE BOARD INSTEAD OF EC!!! |\n");
525                 INFO("+---------------------------------------------------------+\n");
526                 return cOCT6100_ERR_OK;
527         }
528
529
530         /**************************************************************************/
531         /**************************************************************************/
532         /*      1) Configure and Open the OCT6100.                                */
533         /**************************************************************************/
534         /**************************************************************************/
535         
536         memset(&InstanceSize, 0, sizeof(tOCT6100_GET_INSTANCE_SIZE));
537         memset(&OpenChip, 0, sizeof(tOCT6100_CHIP_OPEN));
538
539         if (!(echo_mod = malloc(sizeof(struct echo_mod)))) {
540                 ERR("cannot allocate memory for echo_mod\n");
541                 return 1;
542         }
543                 DBG("allocated mem for echo_mod\n");
544
545         memset(echo_mod, 0, sizeof(struct echo_mod));
546
547         /* Fill the OCT6100 Chip Open configuration structure with default values */
548
549         ulResult = Oct6100ChipOpenDef( &OpenChip );
550         if (ulResult != cOCT6100_ERR_OK) {
551                 ERR("Oct6100ChipOpenDef failed: result=%X\n", ulResult);
552                 return ulResult;
553         }
554
555         OpenChip.pProcessContext                        = echo_mod;
556         /* Configure clocks */
557         
558         /* upclk oscillator is at 33.33 Mhz */
559         OpenChip.ulUpclkFreq                            = cOCT6100_UPCLK_FREQ_33_33_MHZ;
560
561         /* mclk will be generated by internal PLL at 133 Mhz */
562         OpenChip.fEnableMemClkOut                       = TRUE;
563         OpenChip.ulMemClkFreq                           = cOCT6100_MCLK_FREQ_133_MHZ;
564
565         /* General parameters */
566         OpenChip.fEnableChannelRecording                = TRUE;
567
568         /* Chip ID.*/   
569         OpenChip.ulUserChipId                           = 1;
570
571         /* Set the max number of accesses to 1024 to speed things up */
572         /* OpenChip.ulMaxRwAccesses                     = 1024;      */
573
574         /* Set the maximums that the chip needs to support for this test */
575         OpenChip.ulMaxChannels                          = 256;
576         OpenChip.ulMaxPlayoutBuffers                    = 2;
577
578         OpenChip.ulMaxBiDirChannels                     = 0;
579         OpenChip.ulMaxConfBridges                       = 0;
580         OpenChip.ulMaxPhasingTssts                      = 0;
581         OpenChip.ulMaxTdmStreams                        = 8;
582         OpenChip.ulMaxTsiCncts                          = 0;
583
584         /* External Memory Settings: Use DDR memory*/
585         OpenChip.ulMemoryType                           = cOCT6100_MEM_TYPE_DDR;
586         
587         OpenChip.ulNumMemoryChips                       = 1;
588         OpenChip.ulMemoryChipSize                       = cOCT6100_MEMORY_CHIP_SIZE_32MB;
589
590
591         /* Load the image file */
592         ulResult = load_file(   filename,
593                                 &pbyImageData,
594                                 &ulImageByteSize );
595
596         if (pbyImageData == NULL || ulImageByteSize == 0){
597                 ERR("Bad pbyImageData or ulImageByteSize\n");
598                 return 1;
599         }
600         if ( ulResult != 0 ) {
601                 ERR("Failed load_file %s (%08X)\n", filename, ulResult);
602                 return ulResult;
603         }
604
605         /* Assign the image file.*/
606         OpenChip.pbyImageFile                           = pbyImageData;
607         OpenChip.ulImageSize                            = ulImageByteSize;
608
609         /* Inserting default values into tOCT6100_GET_INSTANCE_SIZE structure parameters. */
610         Oct6100GetInstanceSizeDef ( &InstanceSize );
611
612         /* Get the size of the OCT6100 instance structure. */
613         ulResult = Oct6100GetInstanceSize(&OpenChip, &InstanceSize );
614         if (ulResult != cOCT6100_ERR_OK)
615         {
616                 ERR("Oct6100GetInstanceSize failed (%08X)\n", ulResult);
617                 return ulResult;
618         }
619
620         pApiInstance = malloc(InstanceSize.ulApiInstanceSize);
621         echo_mod->pApiInstance                          = pApiInstance;
622         echo_mod->astribank                             = astribank;
623
624         if (!pApiInstance) {
625                 ERR("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize);
626                 return 1;
627         }
628
629         /* Perform actual open of chip */
630         ulResult = Oct6100ChipOpen(pApiInstance, &OpenChip);
631         if (ulResult != cOCT6100_ERR_OK) {
632                 ERR("Oct6100ChipOpen failed: result=%X\n", ulResult);
633                 return ulResult;
634         }
635         DBG("%s: OCT6100 is open\n", __func__);
636
637         /* Free the image file data  */
638         free( pbyImageData );
639         
640         /**************************************************************************/
641         /**************************************************************************/
642         /*      2) Open channels in echo cancellation mode.                       */
643         /**************************************************************************/
644         /**************************************************************************/
645
646         for( nChan = 0; nChan < ECHO_MAX_CHANS; nChan++ ) {
647                 nSlot                                           = nChan;
648                 /* open a channel.*/
649                 Oct6100ChannelOpenDef( &ChannelOpen );
650
651                 /* Assign the handle memory.*/
652                 ChannelOpen.pulChannelHndl = &ulChanHndl;
653
654                 /* Set the channel to work at the echo cancellation mode.*/
655                 ChannelOpen.ulEchoOperationMode         = cOCT6100_ECHO_OP_MODE_NORMAL;
656
657                 pcmLaw                                          = (is_alaw ? cOCT6100_PCM_A_LAW: cOCT6100_PCM_U_LAW);
658
659                 /* Configure the TDM interface.*/
660                 ChannelOpen.TdmConfig.ulRinPcmLaw               = pcmLaw;
661                 ChannelOpen.TdmConfig.ulRinStream               = ECHO_RIN_STREAM;
662                 ChannelOpen.TdmConfig.ulRinTimeslot             = nSlot;
663
664                 ChannelOpen.TdmConfig.ulSinPcmLaw               = pcmLaw;
665                 ChannelOpen.TdmConfig.ulSinStream               = ECHO_SIN_STREAM;
666                 ChannelOpen.TdmConfig.ulSinTimeslot             = nSlot;
667
668                 ChannelOpen.TdmConfig.ulRoutPcmLaw              = pcmLaw;
669                 ChannelOpen.TdmConfig.ulRoutStream              = ECHO_ROUT_STREAM;
670                 ChannelOpen.TdmConfig.ulRoutTimeslot            = nSlot;
671                 
672                 ChannelOpen.TdmConfig.ulSoutPcmLaw              = pcmLaw;
673                 ChannelOpen.TdmConfig.ulSoutStream              = ECHO_SOUT_STREAM;
674                 ChannelOpen.TdmConfig.ulSoutTimeslot            = nSlot;
675
676                 /* Set the desired VQE features.*/
677                 ChannelOpen.VqeConfig.fEnableNlp                = TRUE;
678                 ChannelOpen.VqeConfig.fRinDcOffsetRemoval       = TRUE;
679                 ChannelOpen.VqeConfig.fSinDcOffsetRemoval       = TRUE;
680
681                 ChannelOpen.VqeConfig.ulComfortNoiseMode        = cOCT6100_COMFORT_NOISE_NORMAL;        
682                                                         /*        cOCT6100_COMFORT_NOISE_NORMAL
683                                                                   cOCT6100_COMFORT_NOISE_EXTENDED,
684                                                                   cOCT6100_COMFORT_NOISE_OFF,
685                                                                   cOCT6100_COMFORT_NOISE_FAST_LATCH 
686                                                          */
687                 ulResult = Oct6100ChannelOpen(  pApiInstance,
688                                                 &ChannelOpen );
689                 if (ulResult != cOCT6100_ERR_OK) {
690                         ERR("Found error on chan %d\n", nChan);
691                         return ulResult;
692                 }
693         }
694
695         /**************************************************************************/
696         /**************************************************************************/
697         /*      *) Open channels in echo cancellation mode for second bus.        */
698         /**************************************************************************/
699         /**************************************************************************/
700
701         for( nChan = 8; nChan < 32; nChan++ ) {
702                 nSlot                                           = (nChan >> 3) * 32 + (nChan & 0x07);
703                 /* open a channel.*/
704                 Oct6100ChannelOpenDef( &ChannelOpen );
705
706                 /* Assign the handle memory.*/
707                 ChannelOpen.pulChannelHndl = &ulChanHndl;
708
709                 /* Set the channel to work at the echo cancellation mode.*/
710                 ChannelOpen.ulEchoOperationMode         = cOCT6100_ECHO_OP_MODE_NORMAL;
711
712                 /* Configure the TDM interface.*/
713                 ChannelOpen.TdmConfig.ulRinStream               = ECHO_RIN_STREAM2;;
714                 ChannelOpen.TdmConfig.ulRinTimeslot             = nSlot;
715
716                 ChannelOpen.TdmConfig.ulSinStream               = ECHO_SIN_STREAM2;
717                 ChannelOpen.TdmConfig.ulSinTimeslot             = nSlot;
718
719                 ChannelOpen.TdmConfig.ulRoutStream              = ECHO_ROUT_STREAM2;
720                 ChannelOpen.TdmConfig.ulRoutTimeslot            = nSlot;
721                 
722                 ChannelOpen.TdmConfig.ulSoutStream              = ECHO_SOUT_STREAM2;
723                 ChannelOpen.TdmConfig.ulSoutTimeslot            = nSlot;
724
725                 /* Set the desired VQE features.*/
726                 ChannelOpen.VqeConfig.fEnableNlp                = TRUE;
727                 ChannelOpen.VqeConfig.fRinDcOffsetRemoval       = TRUE;
728                 ChannelOpen.VqeConfig.fSinDcOffsetRemoval       = TRUE;
729
730                 ChannelOpen.VqeConfig.ulComfortNoiseMode        = cOCT6100_COMFORT_NOISE_NORMAL;        
731                                                         /*        cOCT6100_COMFORT_NOISE_NORMAL
732                                                                   cOCT6100_COMFORT_NOISE_EXTENDED,
733                                                                   cOCT6100_COMFORT_NOISE_OFF,
734                                                                   cOCT6100_COMFORT_NOISE_FAST_LATCH 
735                                                          */
736                 ulResult = Oct6100ChannelOpen(  pApiInstance,
737                                                 &ChannelOpen );
738                 if (ulResult != cOCT6100_ERR_OK) {
739                         ERR("Found error on chan %d\n", nChan);
740                         return ulResult;
741                 }
742         }
743
744
745         DBG("%s: Finishing\n", __func__);
746         free(pApiInstance);
747         free(echo_mod);
748         return cOCT6100_ERR_OK;
749
750 }
751 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
752
753 int load_echo(struct astribank_device *astribank, char *filename, int is_alaw)
754 {
755         int             iLen;
756         int             ret;
757         unsigned char   *pbyFileData = NULL; 
758         const char      *devstr;
759
760         devstr = xusb_devpath(astribank->xusb);
761         INFO("%s [%s]: Loading ECHOCAN Firmware: %s (%s)\n",
762                 devstr, xusb_serial(astribank->xusb), filename,
763                 (is_alaw) ? "alaw" : "ulaw");
764         usb_buffer_init(astribank, &usb_buffer);
765         ret = init_octasic(filename, astribank, is_alaw);
766         if (ret) {
767                 ERR("ECHO %s burning failed (%08X)\n", filename, ret);
768                 return -ENODEV;
769         }
770         ret = usb_buffer_flush(astribank, &usb_buffer);
771         if (ret < 0) {
772                 ERR("ECHO %s buffer flush failed (%d)\n", filename, ret);
773                 return -ENODEV;
774         }
775         usb_buffer_showstatistics(astribank, &usb_buffer);
776         return 0;
777 }
778
779 int echo_ver(struct astribank_device *astribank)
780 {
781         usb_buffer_init(astribank, &usb_buffer);
782         return get_ver(astribank);
783 }
784