configure.ac: add libusb/libusbx support (for xpp)
[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 <limits.h>
29 #include <regex.h>
30 #include <sys/time.h>
31 #include "echo_loader.h"
32 #include "debug.h"
33 #include <oct6100api/oct6100_api.h>
34 #include "parse_span_specs.h"
35
36 #define DBG_MASK                0x03
37 #define TIMEOUT                 1000
38 #define ECHO_MAX_CHANS          128
39 #define ECHO_RIN_STREAM         0
40 #define ECHO_ROUT_STREAM        1
41 #define ECHO_SIN_STREAM         2
42 #define ECHO_SOUT_STREAM        3
43
44 #define ECHO_RIN_STREAM2        4
45 #define ECHO_SIN_STREAM2        6
46 #define ECHO_ROUT_STREAM2       5
47 #define ECHO_SOUT_STREAM2       7
48
49 #define EC_VER_TEST             0xABCD
50 #define EC_VER_INVALID          0xFFFF
51 static float oct_fw_load_timeout = 2.0;
52
53 struct echo_mod {
54         tPOCT6100_INSTANCE_API pApiInstance;
55         UINT32 ulEchoChanHndl[256];
56         struct astribank_device *astribank;
57         int maxchans;
58 };
59
60 enum xpp_packet_types {
61         SPI_SND_XOP     = 0x0F,
62         SPI_RCV_XOP     = 0x10,
63         TST_SND_XOP     = 0x35,
64         TST_RCV_XOP     = 0x36,
65 };
66
67 struct xpp_packet_header {
68         struct {
69                 uint16_t        len;
70                 uint8_t         op;
71                 uint8_t         unit;
72         } PACKED header;
73         union {
74                 struct {
75                         uint8_t         header;
76                         uint8_t         flags;
77                         uint8_t         addr_l;
78                         uint8_t         addr_h;
79                         uint8_t         data_l;
80                         uint8_t         data_h;
81                 } PACKED spi_pack;
82                 struct {
83                         uint8_t         tid;
84                         uint8_t         tsid;
85                 } PACKED tst_pack;
86         } alt;
87 } PACKED;
88
89 static struct usb_buffer {
90         char    data[PACKET_SIZE];
91         int     max_len;
92         int     curr;
93         /* statistics */
94         int     min_send;
95         int     max_send;
96         int     num_sends;
97         long    total_bytes;
98         struct timeval  start;
99         struct timeval  end;
100 } usb_buffer;
101
102
103 static void usb_buffer_init(struct astribank_device *astribank, struct usb_buffer *ub)
104 {
105         ub->max_len = xusb_packet_size(astribank->xusb);
106         ub->curr = 0;
107         ub->min_send = INT_MAX;
108         ub->max_send = 0;
109         ub->num_sends = 0;
110         ub->total_bytes = 0;
111         gettimeofday(&ub->start, NULL);
112 }
113
114 static long usb_buffer_usec(struct usb_buffer *ub)
115 {
116         struct timeval  now;
117
118         gettimeofday(&now, NULL);
119         return (now.tv_sec - ub->start.tv_sec) * 1000000 +
120                 (now.tv_usec - ub->start.tv_usec);
121 }
122
123 static void usb_buffer_showstatistics(struct astribank_device *astribank, struct usb_buffer *ub)
124 {
125         long    usec;
126
127         usec = usb_buffer_usec(ub);
128         AB_INFO(astribank, "Octasic statistics: packet_size=[%d, %ld, %d] packets=%d, bytes=%ld msec=%ld usec/packet=%ld\n",
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                 AB_ERR(astribank, "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                 AB_ERR(astribank, "%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                         AB_ERR(astribank, "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 &&
220                         phead->header.op != TST_RCV_XOP) {
221                         AB_ERR(astribank, "Got unexpected reply OP=0x%02X\n",
222                                 phead->header.op);
223                         dump_packet(LOG_ERR, DBG_MASK, "hexline[ERR]",
224                                 buf, ret);
225                         return -EINVAL;
226                 }
227                 dump_packet(LOG_DEBUG, DBG_MASK, "dump:echoline[R]", (char *)phead, phead->header.len);
228                 switch(phead->header.op) {
229                 case SPI_RCV_XOP:
230                         ret = (phead->alt.spi_pack.data_h << 8) | phead->alt.spi_pack.data_l;
231                         break;
232                 case TST_RCV_XOP:
233                         ret = (phead->alt.tst_pack.tid << 8) | phead->alt.tst_pack.tsid;
234                         break;
235                 default:
236                         ret = -EINVAL;
237                 }
238         }
239         return ret;
240 }
241
242 int spi_send(struct astribank_device *astribank, uint16_t addr, uint16_t data, int recv_answer, int ver)
243 {
244         int                             ret;
245         char                            buf[PACKET_SIZE];
246         struct xpp_packet_header        *phead = (struct xpp_packet_header *)buf;
247         int                             pack_len;
248         int                             spi_flags;
249
250         assert(astribank != NULL);
251         spi_flags = 0x30 | (recv_answer ? 0x40 : 0x00) | (ver ? 0x01 : 0x00);
252         pack_len = sizeof(phead->header) + sizeof(phead->alt.spi_pack);
253         phead->header.len               = pack_len;
254         phead->header.op                = SPI_SND_XOP;
255         phead->header.unit              = 0x40; /* EC has always this unit num */
256         phead->alt.spi_pack.header      = 0x05;
257         phead->alt.spi_pack.flags       = spi_flags;
258         phead->alt.spi_pack.addr_l      = (addr >> 0) & 0xFF;
259         phead->alt.spi_pack.addr_h      = (addr >> 8) & 0xFF;
260         phead->alt.spi_pack.data_l      = (data >> 0) & 0xFF;
261         phead->alt.spi_pack.data_h      = (data >> 8) & 0xFF;
262
263         dump_packet(LOG_DEBUG, DBG_MASK, "dump:echoline[W]", (char *)phead, pack_len);
264
265
266         ret = usb_buffer_send(astribank, &usb_buffer, buf, pack_len, TIMEOUT, recv_answer);
267         if (ret < 0) {
268                 AB_ERR(astribank, "usb_buffer_send failed: %d\n", ret);
269                 return ret;
270         }
271         DBG("%s: Written %d bytes\n", __func__, ret);
272         return ret;
273 }
274
275 int test_send(struct astribank_device *astribank)
276 {
277         int                             ret;
278         char                            buf[PACKET_SIZE];
279         struct xpp_packet_header       *phead = (struct xpp_packet_header *)buf;
280         int                             pack_len;
281
282         assert(astribank != NULL);
283         pack_len = sizeof(phead->header) + sizeof(phead->alt.tst_pack);
284         phead->header.len               = 6;
285         phead->header.op                = 0x35;
286         phead->header.unit              = 0x00;
287         phead->alt.tst_pack.tid         = 0x28; /* EC TestId    */
288         phead->alt.tst_pack.tsid        = 0x00; /* EC SubId     */
289
290         dump_packet(LOG_DEBUG, DBG_MASK, "dump:echoline[W]",
291                 (char *)phead, pack_len);
292
293         ret = usb_buffer_send(astribank,
294                 &usb_buffer, buf, pack_len, TIMEOUT, 1);
295         if (ret < 0) {
296                 AB_ERR(astribank, "usb_buffer_send failed: %d\n", ret);
297                 return ret;
298         }
299         DBG("%s: Written %d bytes\n", __func__, ret);
300         return ret;
301 }
302
303 int echo_send_data(struct astribank_device *astribank, const unsigned int addr, const unsigned int data)
304 {
305         int ret;
306 /*      DBG("SEND: %04X -> [%04X]\n", data, addr);
307         DBG("\t\t[%04X] <- %04X\n", 0x0008, (addr >> 20));
308         DBG("\t\t[%04X] <- %04X\n", 0x000A, (addr >> 4) & ((1 << 16) - 1));
309         DBG("\t\t[%04X] <- %04X\n", 0x0004, data);
310         DBG("\t\t[%04X] <- %04X\n", 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1);
311  */
312
313         DBG("SND:\n");
314         ret = spi_send(astribank, 0x0008, (addr >> 20)                  , 0, 0);
315         if (ret < 0)
316                 goto failed;
317         ret = spi_send(astribank, 0x000A, (addr >> 4) & ((1 << 16) - 1) , 0, 0);
318         if (ret < 0)
319                 goto failed;
320         ret = spi_send(astribank, 0x0004, data                          , 0, 0);
321         if (ret < 0)
322                 goto failed;
323         ret = spi_send(astribank, 0x0000, (((addr >> 1) & 0x7) << 9) |
324                                 (1 << 8) | (3 << 12) | 1                , 0, 0);
325         if (ret < 0)
326                 goto failed;
327         return cOCT6100_ERR_OK;
328 failed:
329         AB_ERR(astribank, "echo_send_data: spi_send failed (ret = %d)\n", ret);
330         return ret;
331 }
332
333 int echo_recv_data(struct astribank_device *astribank, const unsigned int addr)
334 {
335         unsigned int data = 0x00;
336         int ret;
337
338         DBG("RCV:\n");
339         ret = spi_send(astribank, 0x0008, (addr >> 20)                  , 0, 0);
340         if (ret < 0)
341                 goto failed;
342         ret = spi_send(astribank, 0x000A, (addr >> 4) & ((1 << 16) - 1) , 0, 0);
343         if (ret < 0)
344                 goto failed;
345         ret = spi_send(astribank, 0x0000, (((addr >> 1) & 0x7) << 9) |
346                                 (1 << 8) | 1                            , 0, 0);
347         if (ret < 0)
348                 goto failed;
349         ret = spi_send(astribank, 0x0004, data                          , 1, 0);
350         if (ret < 0)
351                 goto failed;
352         return ret;
353 failed:
354         AB_ERR(astribank, "echo_recv_data: spi_send failed (ret = %d)\n", ret);
355         return ret;
356 }
357
358 int load_file(char *filename, unsigned char **ppBuf, UINT32 *pLen)
359 {
360         unsigned char *pbyFileData = NULL;
361         FILE *pFile;
362
363         DBG("Loading %s file...\n", filename);
364         pFile = fopen(filename, "rb");
365         if (pFile == NULL) {
366                 ERR("fopen: %s\n", strerror(errno));
367                 return -ENODEV;
368         }
369
370         fseek(pFile, 0L, SEEK_END);
371         *pLen = ftell(pFile);
372         fseek(pFile, 0L, SEEK_SET);
373
374         pbyFileData = (unsigned char *)malloc(*pLen);
375         if (pbyFileData == NULL) {
376                 fclose(pFile);
377                 ERR("malloc\n");
378                 return -ENODEV;
379         } else {
380                 DBG("allocated mem for pbyFileData\n");
381         }
382         if (fread(pbyFileData, 1, *pLen, pFile) != *pLen) {
383                 fclose(pFile);
384                 ERR("fread: %s\n", strerror(errno));
385                 return -ENODEV;
386         }
387         fclose(pFile);
388         DBG("Successful loading %s file into memory "
389                 "(size = %d, DUMP: first = %02X %02X, last = %02X %02X)\n",
390                         filename, *pLen,
391                         pbyFileData[0], pbyFileData[1],
392                         pbyFileData[(*pLen)-2], pbyFileData[(*pLen)-1]);
393         *ppBuf = pbyFileData;
394         return 0;
395 }
396
397 UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
398 {
399         ///* Why couldn't they just take a timeval like everyone else? */
400         struct timeval tv;
401         unsigned long long total_usecs;
402         unsigned int mask = ~0;
403         
404         gettimeofday(&tv, 0);
405         total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
406                                   (((unsigned long long)(tv.tv_usec)));
407         f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
408         f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
409         //printf("Inside of Oct6100UserGetTime\n");
410         return cOCT6100_ERR_OK;
411 }
412
413 UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength)
414 {
415         memset(f_pAddress, f_ulPattern, f_ulLength);
416         return cOCT6100_ERR_OK;
417 }
418
419 UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength)
420 {
421         memcpy(f_pDestination, f_pSource, f_ulLength);
422         return cOCT6100_ERR_OK;
423 }
424
425 UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
426 {
427         return cOCT6100_ERR_OK;
428 }
429
430 UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
431 {
432 #ifdef OCTASIC_DEBUG
433         ERR("I should never be called! (destroy serialize object)\n");
434 #endif
435         return cOCT6100_ERR_OK;
436 }
437
438 UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
439 {
440         /* Not needed */
441         return cOCT6100_ERR_OK;
442 }
443
444 UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
445 {
446         /* Not needed */
447         return cOCT6100_ERR_OK;
448 }
449
450 UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
451 {
452         const unsigned int              addr            = f_pWriteParams->ulWriteAddress;
453         const unsigned int              data            = f_pWriteParams->usWriteData;
454         const struct echo_mod           *echo_mod       = (struct echo_mod *)(f_pWriteParams->pProcessContext);
455         struct astribank_device         *astribank      = echo_mod->astribank;
456         int ret;
457
458         ret = echo_send_data(astribank, addr, data);
459         if (ret < 0) {
460                 ERR("echo_send_data failed (ret = %d)\n", ret);
461                 return cOCT6100_ERR_FATAL_DRIVER_WRITE_API;
462         }
463         return cOCT6100_ERR_OK;
464 }
465
466 UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
467 {
468         unsigned int                    addr;
469         unsigned int                    data;
470         unsigned int                    len;
471         const struct echo_mod           *echo_mod;
472         struct astribank_device         *astribank;
473         unsigned int                    i;
474
475         len = f_pSmearParams->ulWriteLength;
476         echo_mod = (struct echo_mod *)f_pSmearParams->pProcessContext;
477         astribank = echo_mod->astribank;
478         for (i = 0; i < len; i++) {
479                 int ret;
480
481                 addr = f_pSmearParams->ulWriteAddress + (i << 1);
482                 data = f_pSmearParams->usWriteData;
483                 ret = echo_send_data(astribank, addr, data);
484                 if (ret < 0) {
485                         ERR("echo_send_data failed (ret = %d)\n", ret);
486                         return cOCT6100_ERR_FATAL_DRIVER_WRITE_API;
487                 }
488         }
489         return cOCT6100_ERR_OK;
490 }
491
492 UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
493 {
494         unsigned int                    addr;
495         unsigned int                    data;
496         unsigned int                    len             = f_pBurstParams->ulWriteLength;
497         const struct echo_mod           *echo_mod       = (struct echo_mod *)f_pBurstParams->pProcessContext;
498         struct astribank_device         *astribank      = echo_mod->astribank;
499         unsigned int                    i;
500
501         for (i = 0; i < len; i++) {
502                 int ret;
503
504                 addr = f_pBurstParams->ulWriteAddress + (i << 1);
505                 data = f_pBurstParams->pusWriteData[i];
506                 ret = echo_send_data(astribank, addr, data);
507                 if (ret < 0) {
508                         ERR("echo_send_data failed (ret = %d)\n", ret);
509                         return cOCT6100_ERR_FATAL_DRIVER_WRITE_API;
510                 }
511         }
512         return cOCT6100_ERR_OK;
513 }
514
515 UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
516 {
517         const unsigned int              addr =  f_pReadParams->ulReadAddress;
518         const struct echo_mod           *echo_mod;
519         struct astribank_device         *astribank;
520         int ret;
521
522         echo_mod = (struct echo_mod *)f_pReadParams->pProcessContext;
523         astribank = echo_mod->astribank;
524         ret = echo_recv_data(astribank, addr);
525         if (ret < 0) {
526                 ERR("echo_recv_data failed (%d)\n", ret);
527                 return cOCT6100_ERR_FATAL_DRIVER_READ_API;
528         }
529         *f_pReadParams->pusReadData = ret;
530         return cOCT6100_ERR_OK;
531 }
532
533 UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
534 {
535         unsigned int                    addr;
536         unsigned int                    len;
537         const struct echo_mod           *echo_mod;
538         struct astribank_device         *astribank;
539         unsigned int                    i;
540
541         len = f_pBurstParams->ulReadLength;
542         echo_mod = (struct echo_mod *)f_pBurstParams->pProcessContext;
543         astribank = echo_mod->astribank;
544         for (i = 0;i < len; i++) {
545                 unsigned int ret;
546
547                 addr = f_pBurstParams->ulReadAddress + (i << 1);
548                 ret = echo_recv_data(astribank, addr);
549                 if (ret < 0) {
550                         ERR("echo_recv_data failed (%d)\n", ret);
551                         return cOCT6100_ERR_FATAL_DRIVER_READ_API;
552                 }
553                 f_pBurstParams->pusReadData[i] = ret;
554         }
555         return cOCT6100_ERR_OK;
556 }
557
558 inline int get_ver(struct astribank_device *astribank)
559 {
560         return spi_send(astribank, 0, 0, 1, 1);
561 }
562
563 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
564 UINT32 init_octasic(char *filename, struct astribank_device *astribank, struct span_specs *span_specs)
565 {
566         int                                                     cpld_ver;
567         struct echo_mod                                         *echo_mod;
568         UINT32                                                  nChan;
569         UINT32                                                  nSlot;
570         UINT32                                                  pcmLaw;
571         UINT32                                                  ulResult;
572
573         tOCT6100_GET_INSTANCE_SIZE                              InstanceSize;
574         tPOCT6100_INSTANCE_API                                  pApiInstance;
575         tOCT6100_CHIP_OPEN                                      OpenChip;
576
577         UINT32                                                  ulImageByteSize;
578         PUINT8                                                  pbyImageData = NULL;
579
580         /*=========================================================================*/
581         /* Channel resources.*/
582         tOCT6100_CHANNEL_OPEN                                   ChannelOpen;
583         UINT32                                                  ulChanHndl;
584         enum tdm_codec tdm_codec;
585         int spanno;
586
587         if (test_send(astribank) < 0)
588                 return cOCT6100_ERR_FATAL;
589         cpld_ver = get_ver(astribank);
590         AB_INFO(astribank, "Check EC_CPLD version: %d\n", cpld_ver);
591         if (cpld_ver < 0)
592                 return cOCT6100_ERR_FATAL;
593         else if (cpld_ver == EC_VER_TEST) {
594                 AB_INFO(astribank, "+---------------------------------------------------------+\n");
595                 AB_INFO(astribank, "| WARNING: TEST HARDWARE IS ON THE BOARD INSTEAD OF EC!!! |\n");
596                 AB_INFO(astribank, "+---------------------------------------------------------+\n");
597                 return cOCT6100_ERR_OK;
598         }
599
600
601         /**************************************************************************/
602         /**************************************************************************/
603         /*      1) Configure and Open the OCT6100.                                */
604         /**************************************************************************/
605         /**************************************************************************/
606
607         memset(&InstanceSize, 0, sizeof(tOCT6100_GET_INSTANCE_SIZE));
608         memset(&OpenChip, 0, sizeof(tOCT6100_CHIP_OPEN));
609
610         echo_mod = malloc(sizeof(struct echo_mod));
611         if (!echo_mod) {
612                 AB_ERR(astribank, "cannot allocate memory for echo_mod\n");
613                 return cOCT6100_ERR_FATAL;
614         }
615         DBG("allocated mem for echo_mod\n");
616
617         memset(echo_mod, 0, sizeof(struct echo_mod));
618
619         /* Fill the OCT6100 Chip Open configuration structure with default values */
620
621         ulResult = Oct6100ChipOpenDef(&OpenChip);
622         if (ulResult != cOCT6100_ERR_OK) {
623                 AB_ERR(astribank, "Oct6100ChipOpenDef failed: result=%X\n",
624                         ulResult);
625                 return ulResult;
626         }
627
628         OpenChip.pProcessContext                        = echo_mod;
629         /* Configure clocks */
630
631         /* upclk oscillator is at 33.33 Mhz */
632         OpenChip.ulUpclkFreq                            = cOCT6100_UPCLK_FREQ_33_33_MHZ;
633
634         /* mclk will be generated by internal PLL at 133 Mhz */
635         OpenChip.fEnableMemClkOut                       = TRUE;
636         OpenChip.ulMemClkFreq                           = cOCT6100_MCLK_FREQ_133_MHZ;
637
638         /* General parameters */
639         OpenChip.fEnableChannelRecording                = TRUE;
640
641         /* Chip ID.*/   
642         OpenChip.ulUserChipId                           = 1;
643
644         /* Set the max number of accesses to 1024 to speed things up */
645         /* OpenChip.ulMaxRwAccesses                     = 1024;      */
646
647         /* Set the maximums that the chip needs to support for this test */
648         OpenChip.ulMaxChannels                          = 256;
649         OpenChip.ulMaxPlayoutBuffers                    = 2;
650
651         OpenChip.ulMaxBiDirChannels                     = 0;
652         OpenChip.ulMaxConfBridges                       = 0;
653         OpenChip.ulMaxPhasingTssts                      = 0;
654         OpenChip.ulMaxTdmStreams                        = 8;
655         OpenChip.ulMaxTsiCncts                          = 0;
656
657         /* External Memory Settings: Use DDR memory*/
658         OpenChip.ulMemoryType                           = cOCT6100_MEM_TYPE_DDR;
659
660         OpenChip.ulNumMemoryChips                       = 1;
661         OpenChip.ulMemoryChipSize                       = cOCT6100_MEMORY_CHIP_SIZE_32MB;
662
663
664         /* Load the image file */
665         ulResult = load_file(   filename,
666                         &pbyImageData,
667                         &ulImageByteSize);
668
669         if (ulResult != 0) {
670                 AB_ERR(astribank, "Failed load_file %s (%08X)\n", filename, ulResult);
671                 return ulResult;
672         }
673         if (pbyImageData == NULL || ulImageByteSize == 0){
674                 AB_ERR(astribank, "Bad pbyImageData or ulImageByteSize\n");
675                 return cOCT6100_ERR_FATAL;
676         }
677
678         /* Assign the image file.*/
679         OpenChip.pbyImageFile                           = pbyImageData;
680         OpenChip.ulImageSize                            = ulImageByteSize;
681
682         /*
683          * Inserting default values into tOCT6100_GET_INSTANCE_SIZE
684          * structure parameters.
685          */
686         Oct6100GetInstanceSizeDef(&InstanceSize);
687
688         /* Get the size of the OCT6100 instance structure. */
689         ulResult = Oct6100GetInstanceSize(&OpenChip, &InstanceSize);
690         if (ulResult != cOCT6100_ERR_OK) {
691                 AB_ERR(astribank, "Oct6100GetInstanceSize failed (%08X)\n",
692                         ulResult);
693                 return ulResult;
694         }
695
696         pApiInstance = malloc(InstanceSize.ulApiInstanceSize);
697         echo_mod->pApiInstance                          = pApiInstance;
698         echo_mod->astribank                             = astribank;
699
700         if (!pApiInstance) {
701                 AB_ERR(astribank, "Out of memory (can't allocate %d bytes)!\n",
702                         InstanceSize.ulApiInstanceSize);
703                 return cOCT6100_ERR_FATAL;
704         }
705
706         /* Perform actual open of chip */
707         ulResult = Oct6100ChipOpen(pApiInstance, &OpenChip);
708         if (ulResult != cOCT6100_ERR_OK) {
709                 AB_ERR(astribank, "Oct6100ChipOpen failed: result=%X\n",
710                         ulResult);
711                 return ulResult;
712         }
713         DBG("%s: OCT6100 is open\n", __func__);
714
715         /* Free the image file data  */
716         free(pbyImageData);
717
718         /**************************************************************************/
719         /**************************************************************************/
720         /*      2) Open channels in echo cancellation mode.                       */
721         /**************************************************************************/
722         /**************************************************************************/
723
724         for (nChan = 0; nChan < ECHO_MAX_CHANS; nChan++) {
725                 nSlot                                           = nChan;
726                 /* open a channel.*/
727                 Oct6100ChannelOpenDef(&ChannelOpen);
728
729                 /* Assign the handle memory.*/
730                 ChannelOpen.pulChannelHndl = &ulChanHndl;
731
732                 /* Set the channel to work at the echo cancellation mode.*/
733                 ChannelOpen.ulEchoOperationMode         = cOCT6100_ECHO_OP_MODE_NORMAL;
734
735                 spanno = nChan % 4;
736                 assert(spanno >= 0 && spanno < MAX_SPANNO);
737                 tdm_codec = span_specs->span_is_alaw[spanno];
738                 if (tdm_codec == TDM_CODEC_UNKNOWN) {
739                         AB_ERR(astribank, "Calculated bad alaw/ulaw on channel %d\n", nChan);
740                         return cOCT6100_ERR_FATAL;
741                 }
742                 if (nChan < 4)
743                         AB_INFO(astribank, "ECHO PRI port %d = %s\n", spanno+1, (tdm_codec == TDM_CODEC_ALAW) ? "alaw" : "ulaw");
744
745                 pcmLaw                                          = ((tdm_codec == TDM_CODEC_ALAW) ? cOCT6100_PCM_A_LAW: cOCT6100_PCM_U_LAW);
746
747                 /* Configure the TDM interface.*/
748                 ChannelOpen.TdmConfig.ulRinPcmLaw               = pcmLaw;
749                 ChannelOpen.TdmConfig.ulRinStream               = ECHO_RIN_STREAM;
750                 ChannelOpen.TdmConfig.ulRinTimeslot             = nSlot;
751
752                 ChannelOpen.TdmConfig.ulSinPcmLaw               = pcmLaw;
753                 ChannelOpen.TdmConfig.ulSinStream               = ECHO_SIN_STREAM;
754                 ChannelOpen.TdmConfig.ulSinTimeslot             = nSlot;
755
756                 ChannelOpen.TdmConfig.ulRoutPcmLaw              = pcmLaw;
757                 ChannelOpen.TdmConfig.ulRoutStream              = ECHO_ROUT_STREAM;
758                 ChannelOpen.TdmConfig.ulRoutTimeslot            = nSlot;
759
760                 ChannelOpen.TdmConfig.ulSoutPcmLaw              = pcmLaw;
761                 ChannelOpen.TdmConfig.ulSoutStream              = ECHO_SOUT_STREAM;
762                 ChannelOpen.TdmConfig.ulSoutTimeslot            = nSlot;
763
764                 /* Set the desired VQE features.*/
765                 ChannelOpen.VqeConfig.fEnableNlp                = TRUE;
766                 ChannelOpen.VqeConfig.fRinDcOffsetRemoval       = TRUE;
767                 ChannelOpen.VqeConfig.fSinDcOffsetRemoval       = TRUE;
768
769                 ChannelOpen.VqeConfig.ulComfortNoiseMode        = cOCT6100_COMFORT_NOISE_NORMAL;        
770                 /*        cOCT6100_COMFORT_NOISE_NORMAL
771                           cOCT6100_COMFORT_NOISE_EXTENDED,
772                           cOCT6100_COMFORT_NOISE_OFF,
773                           cOCT6100_COMFORT_NOISE_FAST_LATCH
774                  */
775                 ulResult = Oct6100ChannelOpen(  pApiInstance,
776                                 &ChannelOpen);
777                 if (ulResult != cOCT6100_ERR_OK) {
778                         AB_ERR(astribank, "Found error on chan %d\n", nChan);
779                         return ulResult;
780                 }
781         }
782
783         /**************************************************************************/
784         /**************************************************************************/
785         /*      *) Open channels in echo cancellation mode for second bus.        */
786         /**************************************************************************/
787         /**************************************************************************/
788
789         for (nChan = 8; nChan < 32; nChan++) {
790                 nSlot                                           = (nChan >> 3) * 32 + (nChan & 0x07);
791                 /* open a channel.*/
792                 Oct6100ChannelOpenDef(&ChannelOpen);
793
794                 /* Assign the handle memory.*/
795                 ChannelOpen.pulChannelHndl = &ulChanHndl;
796
797                 /* Set the channel to work at the echo cancellation mode.*/
798                 ChannelOpen.ulEchoOperationMode         = cOCT6100_ECHO_OP_MODE_NORMAL;
799
800                 /* Configure the TDM interface.*/
801                 ChannelOpen.TdmConfig.ulRinStream               = ECHO_RIN_STREAM2;;
802                 ChannelOpen.TdmConfig.ulRinTimeslot             = nSlot;
803
804                 ChannelOpen.TdmConfig.ulSinStream               = ECHO_SIN_STREAM2;
805                 ChannelOpen.TdmConfig.ulSinTimeslot             = nSlot;
806
807                 ChannelOpen.TdmConfig.ulRoutStream              = ECHO_ROUT_STREAM2;
808                 ChannelOpen.TdmConfig.ulRoutTimeslot            = nSlot;
809
810                 ChannelOpen.TdmConfig.ulSoutStream              = ECHO_SOUT_STREAM2;
811                 ChannelOpen.TdmConfig.ulSoutTimeslot            = nSlot;
812
813                 /* Set the desired VQE features.*/
814                 ChannelOpen.VqeConfig.fEnableNlp                = TRUE;
815                 ChannelOpen.VqeConfig.fRinDcOffsetRemoval       = TRUE;
816                 ChannelOpen.VqeConfig.fSinDcOffsetRemoval       = TRUE;
817
818                 ChannelOpen.VqeConfig.ulComfortNoiseMode        = cOCT6100_COMFORT_NOISE_NORMAL;        
819                 /*        cOCT6100_COMFORT_NOISE_NORMAL
820                           cOCT6100_COMFORT_NOISE_EXTENDED,
821                           cOCT6100_COMFORT_NOISE_OFF,
822                           cOCT6100_COMFORT_NOISE_FAST_LATCH
823                  */
824                 ulResult = Oct6100ChannelOpen(  pApiInstance,
825                                 &ChannelOpen);
826                 if (ulResult != cOCT6100_ERR_OK) {
827                         AB_ERR(astribank, "Found error on chan %d\n", nChan);
828                         return ulResult;
829                 }
830         }
831
832
833         DBG("%s: Finishing\n", __func__);
834         free(pApiInstance);
835         free(echo_mod);
836         return cOCT6100_ERR_OK;
837
838 }
839 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
840
841 int load_echo(struct astribank_device *astribank, char *filename, int default_is_alaw, const char *span_spec)
842 {
843         int             ret;
844         UINT32          octasic_status;
845         struct span_specs *span_specs;
846
847         span_specs = parse_span_specifications(span_spec, default_is_alaw);
848         if (!span_specs) {
849                 AB_ERR(astribank, "ECHO parsing span specs failed\n");
850                 return -EFAULT;
851         }
852         AB_INFO(astribank, "Loading ECHOCAN Firmware: %s (default %s)\n",
853                 filename, (default_is_alaw) ? "alaw" : "ulaw");
854         usb_buffer_init(astribank, &usb_buffer);
855         octasic_status = init_octasic(filename, astribank, span_specs);
856         free_span_specifications(span_specs);
857         if (octasic_status != cOCT6100_ERR_OK) {
858                 AB_ERR(astribank, "ECHO %s burning failed (%08X)\n",
859                         filename, octasic_status);
860                 return -ENODEV;
861         }
862         ret = usb_buffer_flush(astribank, &usb_buffer);
863         if (ret < 0) {
864                 AB_ERR(astribank, "ECHO %s buffer flush failed (%d)\n", filename, ret);
865                 return -ENODEV;
866         }
867         usb_buffer_showstatistics(astribank, &usb_buffer);
868         return 0;
869 }
870
871 int echo_ver(struct astribank_device *astribank)
872 {
873         usb_buffer_init(astribank, &usb_buffer);
874         return get_ver(astribank);
875 }
876