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