Add debug counters
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / mib / mib.c
2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without 
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 //
37 //
38 // Stacking Input Buffer Driver implementations
39 //
40 //
41 // Derived from /c/ti/c6000/src/drivers/dgs.c
43 #include <xdc/std.h>
44 #include <xdc/cfg/global.h>
45 #include <xdc/runtime/Memory.h>
46 #include <xdc/runtime/System.h>
47 #include <xdc/runtime/Error.h>
48 #include <xdc/runtime/IHeap.h>
49 #include <ti/sysbios/knl/Queue.h>
50 #include <ti/sysbios/knl/Semaphore.h>
51 #include <ti/sysbios/heaps/HeapMem.h>
53 #include <dev2.h>
54 #include "mib.h"
55 #include "miberr.h"
56 #include <inpbuf.h>
57 #include <pafdec.h>
58 #include <pafsio.h>
59 #include <pafsio_ialg.h>
61 #include <limits.h> //INT_MAX
62 #include <string.h>
64 typedef xdc_Short MdInt;
65 typedef xdc_UShort MdUns;
66 typedef xdc_Char SmInt;
67 typedef xdc_UChar SmUns;
70 extern const ti_sysbios_heaps_HeapMem_Handle heapMemDdr3;
71 #define HEAPMALLOC (IHeap_Handle)heapMemDdr3
72 extern HeapMem_Handle DEV2_memSpaceToHeap (IALG_MemSpace space);
74 #if 0
75 #if ((PAF_DEVICE&0xFF000000) == 0xD8000000)
76 #ifndef dMAX_CFG
77 #include <dap_dmax.h>
78 #else
79 #include <dmax_struct.h>
80 #include <dmax_params.h>
81 #endif /* dMAX_CFG */
82 #include "psdkaf_hjt.h"
83 extern Uint32 DAT_cacheop_and_copy (void *src, void *dst, Uint16 byteCnt);
84 #undef DAT_copy
85 #define DAT_copy DAT_cacheop_and_copy
86 #else
87 #include "pafhjt.h"
88 #include "dmax_dat.h" // this has to come after pafhjt
89 #endif
91 #else
92 #include "pafhjt.h"
93 #endif
95 #include <ti/sysbios/knl/Clock.h>
96 #include <xdc/runtime/Log.h>
98 //grab from samrat.c
99 #include <paftyp.h>
100 #include <stdasp.h>
102 #include <logp.h>
103 #include <stdio.h>  // printf in case of programming error
105 // allows you to set a different trace module in pa.cfg
106 #define TR_MOD  trace
108 //#define TRACE_ENABLE
109 #ifdef TRACE_ENABLE
110   #include "dp.h"
111   #define TRACE(a)  dp a    // LOG_printf a
112 #else
113   #define TRACE(a)
114 #endif
116 extern const PAF_SampleRateHz
117 PAF_ASP_sampleRateHzTable[PAF_SAMPLERATE_N][PAF_SAMPLERATEHZ_N];
119 #define SCANATSAMPLERATELIMIT ((float) 48000.)
121 // Likely needs to be 7 when/if AC3 handling is changed to
122 // throw away fill.
123 #define NUM_CHILD_BUFFERS 6
125 Int   DIB_ctrl (DEV2_Handle device, Uns code, Arg Arg);
126 Int   DIB_idle (DEV2_Handle device, Bool Flush);
127 Int   DIB_issue (DEV2_Handle device);
128 Int   DIB_open (DEV2_Handle device, String Name);
129 Int   DIB_reclaim (DEV2_Handle device);
130 Int   DIB_getSync (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
131 Int   DIB_initFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
132 Int   DIB_requestFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
133 Int   DIB_issueChild (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, Int size, Int forTotal);
134 Int   DIB_reclaimChild (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
135 Int   DIB_reset (DEV2_Handle device, PAF_InpBufConfig *pBufConfig);
136 Int   DIB_syncScan (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout);
137 Int   DIB_waitForData (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 count);
138 Int   DIB_syncScanDTS (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout, XDAS_UInt16 *pHeaderEnd);
140 // Driver function table.
141 DIB_Fxns DIB_FXNS  = {
142     NULL,                // close not used in PA/F systems
143     DIB_ctrl,
144     DIB_idle,
145     DIB_issue,
146     DIB_open,
147     NULL,                // ready not used in PA/F systems
148     DIB_reclaim,
149     DIB_getSync,
150     DIB_initFrame,
151     DIB_requestFrame,
152     DIB_issueChild,
153     DIB_reclaimChild,
154     DIB_reset,
155     DIB_syncScan,
156     DIB_waitForData,
157     DIB_syncScanDTS
158 };
160 // macros assume pDevExt is available and pDevExt->pFxns is valid
161 #define DIB_FTABLE_getSync(_a,_b)             (*pDevExt->pFxns->getSync)(_a,_b)
162 #define DIB_FTABLE_initFrame(_a,_b)           (*pDevExt->pFxns->initFrame)(_a,_b)
163 #define DIB_FTABLE_requestFrame(_a,_b)        (*pDevExt->pFxns->requestFrame)(_a,_b)
164 #define DIB_FTABLE_issueChild(_a,_b,_c,_d)    (*pDevExt->pFxns->issueChild)(_a,_b,_c,_d)
165 #define DIB_FTABLE_reclaimChild(_a,_b)        (*pDevExt->pFxns->reclaimChild)(_a,_b)
166 #define DIB_FTABLE_reset(_a,_b)               (*pDevExt->pFxns->reset)(_a,_b)
167 #define DIB_FTABLE_syncScan(_a,_b,_c)         (*pDevExt->pFxns->syncScan)(_a,_b,_c)
168 #define DIB_FTABLE_waitForData(_a,_b,_c)      (*pDevExt->pFxns->waitForData)(_a,_b,_c)
169 #define DIB_FTABLE_syncScanDTS(_a,_b,_c,_d)   (*pDevExt->pFxns->syncScanDTS)(_a,_b,_c,_d)
171 // .............................................................................
173 //IBMODE
174 enum
176     MODE_DEFAULT = 0,
177     MODE_NO_ZERORUNRESTART = 1,
178     MODE_NO_ZERORUN = 2
179 };
181 // syncState
182 enum
184     SYNC_NONE,
185     SYNC_ONE,
186     SYNC_ONGOING,
187     SYNC_PCM,
188     SYNC_PCM_FORCED,
189     SYNC_AUTO
190 };
192 // scanState
193 enum
195     SCANNED_NONE,
196     SCANNED_IEC_PA,
197     SCANNED_IEC_PB,
198     SCANNED_IEC_PC,
199     SCANNED_DTS14_SYNC_A,
200     SCANNED_DTS14_SYNC_B,
201     SCANNED_DTS14_SYNC_C,
202     SCANNED_DTS14_SYNC_D,
203     SCANNED_DTS16_SYNC_A,
204     SCANNED_DTS16_SYNC_B,
205     SCANNED_DTS16_SYNC_C
206 };
208 // all sizes in number of 16bit words words
209 #define IEC_HEADER_SIZE   4 //PA PB PC PD
210 #define DTS14_HEADER_SIZE 6
211 #define DTS16_HEADER_SIZE 4
213 //table needed until PAF_SOURCE is reordered to match IEC numbering
214 const SmUns iecPafSource[23] =
216     PAF_SOURCE_UNKNOWN,  // 0: IEC NULL Type
217     PAF_SOURCE_AC3,      // 1: Comments on 1-15 match IEC 61937 part 2.
218     PAF_SOURCE_UNKNOWN,  // 2: IEC reserved
219     PAF_SOURCE_UNKNOWN,  // 3: IEC pause
220     PAF_SOURCE_UNKNOWN,  // 4: MPEG 1 layer 1
221     PAF_SOURCE_MP3,      // 5: MPEG layer 2 or 3
222     PAF_SOURCE_UNKNOWN,  // 6: MPEG 2 data with extension
223     PAF_SOURCE_AAC,      // 7: MPEG-2 AAC ADTS
224     PAF_SOURCE_UNKNOWN,  // 8: MPEG 2 layer 1 low sampling frequency
225     PAF_SOURCE_UNKNOWN,  // 9: MPEG 2 layer 2 or 3 low sampling frequency
226     PAF_SOURCE_UNKNOWN,  // 10: reserved
227     PAF_SOURCE_DTS,      // 11: DTS type 1 (11 bit: 512 sample repeat period)
228     PAF_SOURCE_DTS12,    // 12: DTS type 2 (12 bit: 1024 sample repeat period)
229     PAF_SOURCE_DTS13,    // 13: DTS type 3 (13 bit: 2048 sample repeat period)
230     PAF_SOURCE_DTS14,    // 14: ATRAC
231     PAF_SOURCE_UNKNOWN,  // 15: ATRAC 2/3
232     PAF_SOURCE_THD,      // 16
233     PAF_SOURCE_DTSHD,    // 17
234     PAF_SOURCE_WMA9PRO,  // 18
235     PAF_SOURCE_UNKNOWN,  // 19
236     PAF_SOURCE_UNKNOWN,  // 20
237     PAF_SOURCE_DDP,      // 21
238     PAF_SOURCE_THD,      // 22
239 };
241 // IEC framelengths (in 16bit words)
242 static const MdUns iecFrameLength[23] =
244     0,
245     1536*2,
246     0, 0, 0,
247     1152*2,
248     0,
249     1024*2,
250     0, 0, 0,
251     512*2,
252     1024*2,
253     2048*2,
254     0, 0,
255     15*1024*2, //THD
256     1*1024, // DTSHD, actual framelength is adjusted by DTSsubType
257     4096*2,
258     0,0,
259     1536*2*4,
260     15*1024*2 //THD
261 };
263 #define IEC_PA       ((short) 0xF872)
264 #define IEC_PB       ((short) 0x4E1F)
265 #define DTS16_SYNC_A ((short) 0x7FFE)
266 #define DTS16_SYNC_B ((short) 0x8001)
267 #define DTS16_SYNC_C ((short) 0xFC00)
268 #define DTS14_SYNC_A ((short) 0x1FFF)
269 #define DTS14_SYNC_B ((short) 0xE800)
270 #define DTS14_SYNC_C ((short) 0x07F0)
272 #define  DTS_BURST_TYPE_I  0x008B
273 #define  DTS_BURST_TYPE_II 0x018C
274 #define  DTS_BURST_TYPE_III 0x028D
275 #define  DTS_BURST_TYPE_IV  0x0491
277 #define  DTS_BURST_TYPE_IV_CBR  0x02
278 #define  DTS_BURST_TYPE_IV_LBR  0x03
279 #define  DTS_BURST_TYPE_IV_HBR  0x04
281 #define DEFAULT_AUTOREQUESTSIZE  128
282 //#define DEFAULT_AUTOREQUESTSIZE  256
284 // This is used at a couple of locations to ensure the transfer
285 // size is sufficiently long to be useful.
286 //#define NOMINAL_XFERSIZE         128
287 #define NOMINAL_XFERSIZE         128 //GJ Debug
288 //#define NOMINAL_XFERSIZE         512 //GJ Debug
290 #define min(a, b)  (((a) < (b)) ? (a) : (b))
291 #define max(a, b)  (((a) > (b)) ? (a) : (b))
293 // -----------------------------------------------------------------------------
295 inline void IncrementPtr (PAF_InpBufConfig *pBufConfig, Ptr *pPtr, int numWords)
297     int addr;
300     addr = (int) *pPtr + numWords*pBufConfig->sizeofElement;
301     if (addr > ((int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer - 1))
302         addr -= pBufConfig->sizeofBuffer;
304     *pPtr = (Ptr) addr;
305     return;
306 } // IncrementPtr
308 // -----------------------------------------------------------------------------
310 inline int GetNumAvail (PAF_InpBufConfig *pBufConfig)
312     int numBytes;
315     if ( (Uns) pBufConfig->head.pVoid >= (Uns) pBufConfig->pntr.pVoid)
316         numBytes = ((int)pBufConfig->head.pVoid - (int)pBufConfig->pntr.pVoid);
317     else
318         numBytes = ((int)pBufConfig->head.pVoid - (int)pBufConfig->pntr.pVoid + pBufConfig->sizeofBuffer);
320     // return in words
321     return (numBytes / pBufConfig->sizeofElement);
322 } // GetNumAvail
324 // -----------------------------------------------------------------------------
325 // compute how much data we have including outstanding requests
327 inline int GetFutureAvail (PAF_InpBufConfig *pBufConfig)
329     int numBytes;
332     if ( (Uns) pBufConfig->futureHead.pVoid >= (Uns) pBufConfig->pntr.pVoid)
333         numBytes = ((int)pBufConfig->futureHead.pVoid - (int)pBufConfig->pntr.pVoid);
334     else
335         numBytes = ((int)pBufConfig->futureHead.pVoid - (int)pBufConfig->pntr.pVoid + pBufConfig->sizeofBuffer);
337     // return in words
338     return (numBytes / pBufConfig->sizeofElement);
339 } // GetFutureAvail
341 // -----------------------------------------------------------------------------
343 Int DIB_issue (DEV2_Handle device)
345     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
346     DEV2_Frame             *srcFrame;
347     Int                    status;
348     PAF_InpBufConfig      *pBufConfig;
351     srcFrame = Queue_get (device->todevice);
352     pBufConfig = (PAF_InpBufConfig *) srcFrame->addr;
353     if (!pBufConfig || !pBufConfig->pBufStatus)
354         return SIO2_EINVAL;
356     Queue_put (device->fromdevice, srcFrame);
358     if (srcFrame->arg == PAF_SIO_REQUEST_AUTO) {
360         // if not yet running, prime input buffer
361         if (pDevExt->syncState == SYNC_NONE) {
363             status = DIB_FTABLE_reset (device, pBufConfig);
364             if (status)
365                 return status;
367             pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
369             status = DIB_FTABLE_issueChild (device, &pDevExt->bufConfig, pDevExt->autoRequestSize, 0);
370             if (status)
371                 return status;
373             // * also reset pDevExt->zeroCount, as in DIB_getSync()?
374             // just for PAF_SOURCE_PCMAUTO? *
375             pDevExt->pcmTimeout =
376                 pDevExt->sourceSelect == PAF_SOURCE_PCMAUTO ? 0 :
377                 2 * pBufConfig->pBufStatus->unknownTimeout;
378             pDevExt->syncState = SYNC_AUTO;
380             // allows PCM decoder to be used to generate zero-valued audio frames while scanning
381             pBufConfig->deliverZeros = 1;
382         }
383         // no action if already sync'ed
384         else if (pDevExt->syncState != SYNC_AUTO)
385             return 0;
387         status = DIB_FTABLE_issueChild (device, &pDevExt->bufConfig, pDevExt->autoRequestSize, 0);
388         if (status)
389             return status;
390     }
391     else if (srcFrame->arg == PAF_SIO_REQUEST_NEWFRAME) {
393         // do nothing if not synced since syncing done in reclaim
394         // This is executed in force modes from the first call to PAF_AST_decodeInit
395         // which calls SIO2_issue for NEWFRAME before all other calls.
396         if (pDevExt->syncState == SYNC_NONE)
397             return 0;
399         status = DIB_FTABLE_requestFrame (device, &pDevExt->bufConfig);
400         if (status)
401             return status;
402     }
404     return 0;
405 } // DIB_issue
407 // -----------------------------------------------------------------------------
408 // Although interface allows for arbitrary BufConfigs we only support 1 -- so
409 // we can assume the one on the fromdevice is the one we want
411 extern int gIsrInputCnt; // GJ Debug
412 extern int gIsrOutputCnt; // GJ Debug
414 Int DIB_reclaim (DEV2_Handle device)
416     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *) device->object;
417     DEV2_Frame             *dstFrame;
418     Int                    status = 0;
419     PAF_InpBufConfig      *pBufConfig;
421     dstFrame = (DEV2_Frame *) Queue_head (device->fromdevice);
423     if (dstFrame == (DEV2_Frame *) device->fromdevice)
424         return DIBERR_UNSPECIFIED;
425     if (!dstFrame->addr)
426         return DIBERR_UNSPECIFIED;
428     // if deferred error from last request frame then return now
429     status = pDevExt->deferredError;
430     if (status) {
431         pDevExt->deferredError = 0;
432         pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
433         return status;
434     }
436     pBufConfig = (Ptr) dstFrame->addr;
437     dstFrame->size = sizeof (PAF_InpBufConfig);
439     // .........................................................................
441     if (dstFrame->arg == PAF_SIO_REQUEST_AUTO) {
443         Log_info0("DIB: At case = PAF_SIO_REQUEST_AUTO"); // GJ Debug
445         // verify set up by prior DIB_issue()
446         // no action if already sync'ed
447         if (pDevExt->syncState == SYNC_NONE)
448             return DIBERR_AUTO;
449         else if (pDevExt->syncState != SYNC_AUTO)
450             return 0;
452         // get next block of data to scan
453         status = DIB_FTABLE_waitForData (device, &pDevExt->bufConfig, pDevExt->autoRequestSize);
454         if (status)
455             return status;
457         if (pDevExt->sourceSelect == PAF_SOURCE_NONE) {
458             IncrementPtr (pBufConfig, &pDevExt->bufConfig.pntr.pVoid, pDevExt->autoRequestSize);
459             return 0;
460         }
462         // this function updates the tail pointer; it WON'T reset to SYNC_NONE
463         status = DIB_FTABLE_syncScan (device, &pDevExt->bufConfig, &pDevExt->pcmTimeout);
464         if (status)
465             return status;
467         // if not yet sync'ed ...
468         if (pDevExt->syncState == SYNC_AUTO) {
469             // if timeout, harness tail of DIB_getSync()
470             if (!pDevExt->pcmTimeout) {
472                 // checks pDevExt->zeroCount, runs DIB_reset(),
473                 // updates pBufConfig->deliverZeros/sizeofElement/sizeofBuffer,
474                 // sets pDevExt->sourceProgram = PAF_SOURCE_PCM/DSD?
475                 //  and pDevExt->syncState = SYNC_PCM[_FORCED]
476                 status = DIB_FTABLE_getSync (device, &pDevExt->bufConfig);
477                 if (status)
478                     return status;
479             }
480         }
482         // if sync'ed to bitstream, this requests add'l input;
483         // if PCM, this "kickstarts" the input,
484         // using settings per above call to DIB_getSync()
485         if (pDevExt->syncState != SYNC_AUTO) {
487             status = DIB_FTABLE_initFrame (device, &pDevExt->bufConfig);
488             if (status)
489                 return status;
491             // this situation may occur for various IEC types,
492             // w/ no matching PAF_SOURCE_ type is defined
493             // (see iecPafSource[] table for the latter mapping)
494             // most like cases are null & pause packets
495             if (pDevExt->sourceProgram == PAF_SOURCE_UNKNOWN)
496                 return DIBERR_SYNC;
498             // request timing frame
499             status = DIB_FTABLE_requestFrame (device, &pDevExt->bufConfig);
500             if (status)
501                 return status;
502         }
503     } //dstFrame->arg == PAF_SIO_REQUEST_AUTO
505     // .........................................................................
507     if ((pDevExt->syncState == SYNC_NONE) || (dstFrame->arg == PAF_SIO_REQUEST_SYNC)) {
509         Log_info0("DIB: At case: syncState == SYNC_NONE (or PAF_SIO_REQUEST_SYNC)");  // GJ Debug
511         // pass in external buffer config which used to initialize the internal view
512         status = DIB_FTABLE_reset (device, pBufConfig);
513         if (status)
514             return status;
516         status = DIB_FTABLE_getSync (device, &pDevExt->bufConfig);
517         if (status)
518             return status;
520         // since getSync resets sourceProgram to unknown at entry
521         // sourceProgram will remain unknown if no sync is returned
522         // (i.e. no need to reset it here)
523         if (pDevExt->syncState == SYNC_NONE)
524         {
525             Log_info0("Returning DIBERR_SYNC after DIB_FTABLE_getSync"); // GJ Debug
526             return DIBERR_SYNC;
527         }
529         // get input info (frameLength/etc)
530         status = DIB_FTABLE_initFrame (device, &pDevExt->bufConfig);
532         if (status)
533         {
534             Log_info1("Returning %d after DIB_FTABLE_initFrame", status); // GJ Debug
535             return status;
536         }
538         // request timing frame
539         status = DIB_FTABLE_requestFrame (device, &pDevExt->bufConfig);
540         if (status)
541         {
542             Log_info1("Returning %d after DIB_FTABLE_requestFrame", status); // GJ Debug
543             return status;
544         }
545         // update external view of bufConfig. In particular for slave force PCM
546         // this insures that the first decode will be processed with deliverZeros = 1
547         // which is necessary since the first decode of slave input occurs before the
548         // first slave input frame is actually captured.
549         *pBufConfig = pDevExt->bufConfig;
551     } //((pDevExt->syncState == SYNC_NONE) || (dstFrame->arg == PAF_SIO_REQUEST_SYNC))
553     // .........................................................................
555     if (dstFrame->arg == PAF_SIO_REQUEST_NEWFRAME) {
557         Log_info0("DIB: At case = PAF_SIO_REQUEST_NEWFRAME"); // GJ Debug
559         // wait for enough data to check for sync at expected location
560         status = DIB_FTABLE_waitForData (device, &pDevExt->bufConfig, pDevExt->bufConfig.frameLength);
561         if (status)
562         {
563             Log_info2("DIB_reclaim.%d DIB_FTABLE_waitForData returned %d", __LINE__, status); // GJ Debug
564             //TRACE((&TR_MOD, "DIB_reclaim.%d DIB_FTABLE_waitForData returned %d\n", __LINE__, status));
565             return status;
566         }
568         // if PCM, but not forced PCM, then scan for bitstream sync
569         // note that we we using the local view of bufConfig here and we update the
570         // public view afterwards.
571         if (pDevExt->syncState == SYNC_PCM) {
572             float sampleRate = PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD];
573             PAF_InpBufConfig *pBufConfig = &pDevExt->bufConfig;
574             Int ibMode = pBufConfig->pBufStatus->mode; // read mode register once
576             // normally no scanning done if sampleRate > 48kHz since bitstream input is highly unlikley.
577             if ((sampleRate <= SCANATSAMPLERATELIMIT) || pBufConfig->pBufStatus->scanAtHighSampleRateMode) {
578                 if (!pBufConfig->deliverZeros) {
579                     pDevExt->pcmTimeout = pBufConfig->lengthofData;
581                     // check zeroRunTrigger if needed
582                     if (ibMode != MODE_NO_ZERORUN) {
583                         if(pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger) {
584                             // set this flag one block late to allow for
585                             // transmission of all data in frame which contained zeroRunTrigger
586                             pBufConfig->deliverZeros = 1;
587                             pDevExt->pcmTimeout = 2 * pBufConfig->pBufStatus->unknownTimeout;
588                         } // > zeroRunTrigger
589                     } // !MODE_NO_ZERORUN
590                 } // !pBufConfig->deliverZeros
592                 // scan PCM data
593                 status = DIB_FTABLE_syncScan (device, pBufConfig, &pDevExt->pcmTimeout);
594                 if (status) {
595                     pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
596                     Log_info2("DIB_reclaim.%d DIB_FTABLE_syncScan returned %d", __LINE__, status); // GJ Debug
597                     //TRACE((&TR_MOD, "DIB_reclaim.%d DIB_FTABLE_syncScan returned %d\n", __LINE__, status));
598                     return status;
599                 }
601                 // if scan found something other than PCM, then exit with error
602                 if (pDevExt->syncState != SYNC_PCM)
603                 {
604                     Log_info1("DIB_reclaim.%d error: syncState != SYNC_PCM", __LINE__); // GJ Debug
605                     //TRACE((&TR_MOD, "DIB_reclaim.%d error: syncState != SYNC_PCM\n", __LINE__));
606                     return DIBERR_SYNC;
607                 }
609                 // if heeding zeroRunRestart control then return to unknown if necessary
610                 if ((ibMode == MODE_DEFAULT) &&
611                     (pDevExt->zeroCount >= 2*pBufConfig->pBufStatus->zeroRunRestart)) {
612                     // if zeroRunRestart me then reset input to unknown
613                     Log_info1("DIB_reclaim.%d error: zeroRunRestart, setting PAF_SOURCE_UNKNOWN", __LINE__); // GJ Debug
614                     //TRACE((&TR_MOD, "DIB_reclaim.%d error: zeroRunRestart, setting PAF_SOURCE_UNKNOWN\n", __LINE__));
615                     pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
616                     return DIBERR_SYNC;
617                 }
619                 // since in skeptical state we disallow returning to PCM when end of timeout contains zeros
620                 // note that we need not check the mode here since above logic prevents deliverZeros state.
621                 if (pBufConfig->deliverZeros && (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger))
622                 {
623                     //TRACE((&TR_MOD, "DIB_reclaim.%d set pcmTimeout = unknown timeout\n", __LINE__));
624                     pDevExt->pcmTimeout = 2 * pBufConfig->pBufStatus->unknownTimeout;
625                 }
626             } //scanAtHighSampleRate
627         } //SYNC_PCM
629         // clear this flag immediately to play new audio ASAP
630         // this check is OK for forced PCM since pcmTimeout and zeroCount are not
631         // updated
632         if (pDevExt->bufConfig.deliverZeros && !pDevExt->pcmTimeout &&
633             (pDevExt->zeroCount < 2 * pDevExt->bufConfig.pBufStatus->zeroRunTrigger))
634         {
635             pDevExt->bufConfig.deliverZeros = 0;
636         }
638         // update external view of buffer with local view we do this with current 
639         // frame info before the following update to the local view for the next 
640         // frame to be captured. Need to subtract headerSize from lengthofData
641         // since, at least for THD, it is needed by decoders.
642         *pBufConfig = pDevExt->bufConfig;
643         pBufConfig->lengthofData -= pDevExt->headerSize;
644         Log_info4("DIB_reclaim.%d lengthofData = %d; InISRCNT=%d; OutISRCNT=%d", __LINE__, pBufConfig->lengthofData, gIsrInputCnt, gIsrInputCnt); // GJ Debug
645         //TRACE((&TR_MOD, "DIB_reclaim.%d lengthofData = %d\n", __LINE__, pBufConfig->lengthofData));
647         // HACK: for DSD the frameLength needs to be the number of samples to generate.
648         if ((pDevExt->sourceSelect >= PAF_SOURCE_DSD1) &&
649             (pDevExt->sourceSelect <= PAF_SOURCE_DSD3))
650             pBufConfig->frameLength /= pBufConfig->stride;
651         Log_info2("DIB_reclaim.%d frameLength = %d", __LINE__, pBufConfig->frameLength); // GJ Debug
652         //TRACE((&TR_MOD, "DIB_reclaim.%d frameLength = %d\n", __LINE__, pBufConfig->frameLength));
654         // set external view to point at synch position of the frame guaranteed
655         // to be captured by above waitForData. Need to condition this against PCM since
656         // in that case pSync could point anywhere in the buffer to to syncScan. E.g.
657         // if there was a partial sync then pSync would point at that rather than
658         // at the beginning of the buffer.
659         // TODO: change syncScan to only update pDevExt->pSync when there is an actual sync
660         //       so that we can use this for both PCM and bitstream
661         if (pDevExt->syncState == SYNC_ONGOING) {
662             pBufConfig->pntr = pDevExt->pSync;
663             IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pDevExt->headerSize);
664         } //SYNC_ONGOING
666         // if a bitstream then need to update tail to bitstream sync location
667         // and check for next sync at expected location
668         // quick scan for sync. if decoding IEC but sync is missing then
669         // defer error until the next frame so that we decode all frames
670         // TODO: does this assume decoders have copied the entire input frame
671         //       i.e. it is ok to adjust the input buffer pointers.
672         // if successful then this sets
673         //      pSync = address of PA (for IEC)
674         status = DIB_FTABLE_initFrame (device, &pDevExt->bufConfig);
675         if (status) {
676             if (pBufConfig->pBufStatus->lastFrameMask & (1 << pDevExt->sourceProgram)) {
677                 pDevExt->deferredError = status;
678                 Log_info1("DIB_reclaim.%d last frame\n", __LINE__); // GJ Debug
679                 //TRACE((&TR_MOD, "DIB_reclaim.%d last frame\n", __LINE__));
680                 pBufConfig->pBufStatus->lastFrameFlag = 1;
681                 return 0;
682             }
683             else {
684                 Log_info1("DIB_reclaim.%d setting PAF_SOURCE_UNKNOWN", __LINE__); // GJ Debug
685                 //TRACE((&TR_MOD, "DIB_reclaim.%d setting PAF_SOURCE_UNKNOWN\n", __LINE__));
686                 pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
687                 return status;
688             }
689         }
691     } //(dstFrame->arg == PAF_SIO_REQUEST_NEWFRAME)
693     // .........................................................................
695     Log_info4("DIB_reclaim.%d exit status = %d, InISRCNT = %d OutISRCNT = %d", __LINE__, status, gIsrInputCnt, gIsrOutputCnt); // GJ Debug
696     //TRACE((&TR_MOD, "DIB_reclaim.%d exit status = %d\n", __LINE__, status));
698     return status;
699 } // DIB_reclaim
701 // -----------------------------------------------------------------------------
703 Int DIB_ctrl (DEV2_Handle  device, Uns code, Arg arg)
705     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
706     DEV2_Handle            pChild = (DEV2_Handle)&pDevExt->child;
707     Int status = 0;
710     switch (code) {
712         case PAF_SIO_CONTROL_GET_CHILD_DEVICE:
713             *((Arg *)arg) = (Arg) pChild;
714             break;
716             //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
718         case PAF_SIO_CONTROL_SET_DECSTATUSADDR:
719             pDevExt->pDecodeStatus = (PAF_DecodeStatus *) arg;
720             break;
722         case PAF_SIO_CONTROL_SET_PCMFRAMELENGTH:
723             pDevExt->pcmFrameLength = (XDAS_Int32) arg;
724             break;
726         case PAF_SIO_CONTROL_SET_SOURCESELECT:
727             pDevExt->sourceSelect = (XDAS_Int8) arg;
728             break;
730         case PAF_SIO_CONTROL_SET_AUTOREQUESTSIZE:
731             pDevExt->autoRequestSize = (XDAS_Int16) arg;
732             break;
734         case PAF_SIO_CONTROL_GET_SOURCEPROGRAM:
735             if (!arg)
736                 return DIBERR_UNSPECIFIED;
737             *((XDAS_Int8 *) arg) = pDevExt->sourceProgram;
738             break;
740         case PAF_SIO_CONTROL_SET_IALGADDR:
741             pDevExt->pSioIalg = (PAF_SIO_IALG_Obj *) arg;
742             break;
744             //,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
746         case PAF_SIO_CONTROL_OPEN:
747             pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
748             pDevExt->zeroCount = 0;
749             if (pDevExt->pInpBufStatus)
750                 pDevExt->pInpBufStatus->zeroRun = 0;
751             status = DEV2_ctrl (pChild, code, arg);
752             break;
754         case PAF_SIO_CONTROL_CLOSE:
755             if (pDevExt->pInpBufStatus)
756                 pDevExt->pInpBufStatus->zeroRun = 0;
757             status = DEV2_ctrl (pChild, code, arg);
758             break;
760         // return number of DMA events vs. request size
761         // only update if not in error state (i.e. status = 0)
762         case PAF_SIO_CONTROL_GET_NUM_EVENTS:
763             if (!arg)
764                 return DIBERR_UNSPECIFIED;
765             status = DEV2_ctrl (pChild, code, arg);
766             if (!status)
767                 *((Int *)arg) -= pDevExt->pcmFrameLength;
768             break;
770         // return net samples until next DIB_waitForData() should succeed w/o blocking
771         case PAF_SIO_CONTROL_GET_NUM_REMAINING:
772             if (!arg)
773                 return DIBERR_UNSPECIFIED;
774             status = DEV2_ctrl (pChild, code, arg);
775             *((Int *)arg) -= pDevExt->numSamplesExtra;
776             break;
778         default:
779             status = DEV2_ctrl (pChild, code, arg);
780             break;
781     }
783     return status;
784 } // DIB_ctrl
786 // -----------------------------------------------------------------------------
788 Int DIB_idle (DEV2_Handle device, Bool flush)
790     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
791     Int                    status;
794     while (!Queue_empty (device->todevice))
795         Queue_enqueue (device->fromdevice, Queue_dequeue (device->todevice));
797     while (!Queue_empty (device->fromdevice))
798         Queue_enqueue (&((SIO2_Handle) device)->framelist, Queue_dequeue (device->fromdevice));
800     status = DIB_FTABLE_reset (device, NULL);
801     if (status)
802         return status;
804     return 0;
805 } // DIB_idle
807 // -----------------------------------------------------------------------------
809 Int DIB_open (DEV2_Handle device, String name)
811     DIB_DeviceExtension   *pDevExt;
812     DEV2_Handle             pChild;
813     DEV2_Device            *entry;
814     DEV2_Frame             *frame;
815     Int                    status, i;
816         Error_Block eb;
818         Error_init(&eb);
820     name = DEV2_match (name, &entry);
821     if (entry == NULL) {
822         Log_info1("DEV2_match failed in DIB_open:", SIO2_ENODEV);
823         return SIO2_ENODEV;
824     }
826     // only one frame interface supported
827     if (device->nbufs != 1)
828         return SYS_EALLOC;
830     if (!(pDevExt = Memory_alloc (device->bufSeg, sizeof(DIB_DeviceExtension), 0, &eb)))
831     {
832         Log_info1("DIB Memory alloc failed in DIB_open:", SYS_EALLOC);
833         return SYS_EALLOC;
834     }
835     pDevExt->pcmFrameLength = 0;
836     pDevExt->sourceSelect  = PAF_SOURCE_NONE;
837     pDevExt->autoRequestSize = DEFAULT_AUTOREQUESTSIZE;
838     pDevExt->pInpBufStatus = NULL;
839     pDevExt->pDecodeStatus = NULL;
840     device->object = (Ptr)pDevExt;
842     pChild = (DEV2_Handle)&pDevExt->child;
843     pChild->fromdevice = Queue_create (NULL, &eb);
844     pChild->todevice = Queue_create (NULL, &eb);
845     if (pChild->fromdevice == NULL || pChild->todevice == NULL) {
846         Log_info1 ("DIB Queue_create failed in DIB_open:", SYS_EALLOC);
847         return SYS_EALLOC;
848     }
850     pChild->bufsize = 0;
851     pChild->nbufs = NUM_CHILD_BUFFERS;
852     pChild->bufSeg = device->bufSeg;
853     pChild->mode = device->mode;
854     pChild->timeout = device->timeout;
855     pChild->align = device->align;
856     pChild->devid = entry->devid;
857     pChild->params = entry->params;
858     pChild->fxns = *(DEV2_Fxns *)(entry->fxns);
859     ((SIO2_Handle)pChild)->model = ((SIO2_Handle)device)->model;
861     //Create frames and put them on the correct device queue.
862     // We only support ISSUERECLAIM mode so size = 0
863     Queue_construct(&((SIO2_Handle)pChild)->framelist, NULL); //Queue_new (&((SIO2_Handle)pChild)->framelist);
864     for (i=0; i < pChild->nbufs; i++) {
865         frame = DEV2_mkframe (0, 0, 0);
866         if (!frame)
867             return SYS_EALLOC;
868         Queue_put (&((SIO2_Handle)pChild)->framelist, frame);
869     }
871     // open underlying device
872     status = DEV2_open (pChild, name);
873     if (status)
874         return status;
876     // use dev match to fetch function table pointer for DIB
877     name = DEV2_match ("/DIB", &entry);
878     if (entry == NULL) {
879         Log_info1 ("DEV2_match for DIB in DIB_open:", SIO2_ENODEV);
880         return SIO2_ENODEV;
881     }
882     pDevExt->pFxns = (DIB_Fxns *) entry->fxns;
884     // set IEC frame length table pointer -- change in
885     // subsequent control call (not defined) to add new IEC type
886     pDevExt->pIECFrameLength = (XDAS_UInt16 *) iecFrameLength;
888     status = DIB_FTABLE_reset (device,NULL);
889     if (status)
890         return status;
892     return status;
893 } // DIB_open
895 // -----------------------------------------------------------------------------
896 // Although this is void it is still needed since BIOS calls all DEV inits on
897 // startup.
899 Void DIB_init (Void)
901 } // DIB_init
903 // -----------------------------------------------------------------------------
904 // Notes:
905 //   1. DIB_reset is called prior to this function being called.(see DIB_reclaim)
906 //   2. (1) ==> sizeofBuffer is an integral # of 2byte samples.
907 //   3. (2) ==> if we use a request size which is divisor of sizeofBuffer there
908 //              will be no wrap-around when requesting data for scanning.
909 //   4. (3) ==> we meet the interface requirement for syncScan which has no
910 //              circular arithmetic.
912 Int DIB_getSync (DEV2_Handle device, PAF_InpBufConfig *pBufConfig )
914     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
915     DEV2_Handle             pChild = (DEV2_Handle)&pDevExt->child;
916     int status;
917     Uns timeout,  syncBufSize, syncRequestSize;
918     Int ibMode = pBufConfig->pBufStatus->mode; // read mode register once
919     Int deliverZeros;
921     //..........................................................................
923     // implement local timeout so that we don't get 'stuck' here when input
924     // is all zeros + lock
925     if (pDevExt->syncState == SYNC_NONE) {
926         Uns localTimeout;
927         // latch value before resetting to PAF_SOURCE_UNKNOWN
928         Int sourceProgram = pDevExt->sourceProgram;
930         pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
932         // if here then guaranteed to have fresh reset
934         if (pDevExt->sourceSelect == PAF_SOURCE_PCM || pDevExt->sourceSelect == PAF_SOURCE_DSD1 ||
935             pDevExt->sourceSelect == PAF_SOURCE_DSD2 || pDevExt->sourceSelect == PAF_SOURCE_DSD3) {
936             timeout = 0;
938             // no zero run counting in force modes since no scanning
939             pBufConfig->pBufStatus->zeroRun = 0;
940             pDevExt->zeroCount = 0;
941         }
942         else if ((pDevExt->sourceSelect == PAF_SOURCE_PCMAUTO) &&
943                  ((sourceProgram == PAF_SOURCE_UNKNOWN) || (sourceProgram == PAF_SOURCE_PCM))) {
944             // if sourceselect is PCMAUTO then
945             //    if current input is a bistream then scan for normal timeout period
946             //    if current input is unknown or PCM then transition immediately to PCM
947             // this provides for *no* lossed PCM, detection of bitstreams, but some noise
948             // is possible.
949             timeout = 0;
950             pDevExt->zeroCount = 0;
951         }
952         else
953             timeout = 2*pBufConfig->pBufStatus->unknownTimeout;
955         // force request size to be a divisor of sizeofBuffer
956         syncRequestSize = NOMINAL_XFERSIZE;
957         if (pBufConfig->stride > 2)
958             syncRequestSize *= pBufConfig->stride;
959         syncBufSize = pBufConfig->sizeofBuffer / ((int) (pBufConfig->sizeofBuffer/syncRequestSize));
961         if (timeout) {
962             status = DIB_FTABLE_issueChild (device, pBufConfig, syncBufSize, 0);
963             if (status)
964                 return status;
965         }
967         localTimeout = timeout;
968         while ((timeout) && (pDevExt->syncState != SYNC_ONE)) {
970             status = DIB_FTABLE_issueChild (device, pBufConfig, syncBufSize, 0);
971             if (status)
972                 return status;
974             // get next block of data to scan
975             status = DIB_FTABLE_waitForData (device, pBufConfig, syncBufSize);
976             if (status)
977                 return status;
979             // this function updates the tail pointer
980             status = DIB_FTABLE_syncScan (device, pBufConfig, &timeout);
981             if (status)
982                 return status;
984             // if input is zero, i.e. haven't decremented at all,
985             // then break out and use more logic and
986             if (localTimeout < syncBufSize) {
987                 // Should this be 2 *? MAW
988                 if (timeout == 2*pBufConfig->pBufStatus->unknownTimeout)
989                     break;
990             }
991             else
992             {
993                 Log_info3("DIB: Inside DIB_getSync with syncState != SYNC_ONE. localTimeout = %d, syncBufSize  = %d, timeout = %d", localTimeout,syncBufSize, timeout); // GJ Debug
994                 localTimeout -= syncBufSize;
995             }
996         }
998         // if found sync then return to caller who will call 
999         // initFrame to get bitstream info and requestFrame for data
1000         if (pDevExt->syncState != SYNC_NONE)
1001             return 0;
1003     } //pDevExt->syncState == SYNC_NONE
1005     //..........................................................................
1007     // set default to zero -- we assume decode calls will not be made
1008     // before data is available since this must be master input. Will be changed below
1009     // as needed
1010     deliverZeros = 0;
1012     if (pDevExt->syncState == SYNC_AUTO) {
1013         timeout = pDevExt->pcmTimeout;
1014         deliverZeros = 1;
1015     }
1017     // if in zero run, and heeding full zeroRun control, then return to unknown if # zeros > trigger/Restart
1018     if (ibMode == MODE_DEFAULT) {
1019         if ((pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger) ||
1020             (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunRestart))
1021             return DIBERR_SYNC;
1022         // since we may have exited prematurely above we check timeout
1023         if (timeout)
1024             return DIBERR_SYNC;
1025     }
1026     // if heeding trigger but not restart then enter deliverZeros state of PCM
1027     else if (ibMode == MODE_NO_ZERORUNRESTART) {
1028         if (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger)
1029             deliverZeros = 1;
1030     }
1032     // here if timeout to PCM (includes force PCM)
1033     status = DIB_FTABLE_reset (device, pBufConfig);
1034     if (status)
1035         return status;
1037     // hack -- try 32bit then 16bit if necessary
1038     pBufConfig->sizeofElement = 4;
1039     status = SIO2_ctrl (pChild,(Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
1040     if(status) {
1041         pBufConfig->sizeofElement = 2;
1042         status = SIO2_ctrl (pChild, (Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
1043         if(status)
1044             return status;
1045     }
1047     // Force sizeofBuffer to be integral number of frame sizes. This ensures that the
1048     // pcm buffers will not need a circular wrap-around. We prevent this because
1049     // syncScan makes this assumption in order to perform an efficient scan.
1050     {
1051         int sizeofStride = pBufConfig->sizeofElement*pBufConfig->stride*pDevExt->pcmFrameLength;
1052         pBufConfig->sizeofBuffer = pBufConfig->allocation/sizeofStride*sizeofStride;
1053     }
1055     if (pDevExt->sourceSelect == PAF_SOURCE_DSD1 || pDevExt->sourceSelect == PAF_SOURCE_DSD2 ||
1056         pDevExt->sourceSelect == PAF_SOURCE_DSD3)
1057         pDevExt->sourceProgram = pDevExt->sourceSelect;
1058     else
1059         pDevExt->sourceProgram = PAF_SOURCE_PCM;
1061     if (pDevExt->sourceSelect == PAF_SOURCE_PCM || pDevExt->sourceSelect == PAF_SOURCE_DSD1 ||
1062         pDevExt->sourceSelect == PAF_SOURCE_DSD2 || pDevExt->sourceSelect == PAF_SOURCE_DSD3) {
1063         pDevExt->syncState = SYNC_PCM_FORCED;
1064         // set to one -- ensures that PCM decode calls made before data is
1065         // available will result in zero output.
1066         // (mostly needed for PA15 since, currently, all other frameworks
1067         // require a frame of data before the first decode call.
1068         deliverZeros = 1;
1069     }
1070     else
1071         pDevExt->syncState = SYNC_PCM;
1073     // update config struct
1074     pBufConfig->deliverZeros = deliverZeros;
1076     //..........................................................................
1078     return 0;
1079 } // DIB_getSync
1081 // -----------------------------------------------------------------------------
1083 int gWrapCtr=0;
1084 Int DIB_issueChild (DEV2_Handle device, PAF_InpBufConfig  *pBufConfig, int size, int forTotal)
1086     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *) device->object;
1087     DEV2_Handle             pChild  = (DEV2_Handle) &pDevExt->child;
1088     int                    bufEnd  = (int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer;
1089     DEV2_Frame             *dstFrame;
1090     int                    futureHead, status;
1091     int                    i, sizes[2];
1092     Ptr                    endAddr[2];
1093    
1096     // if seeking for total amount then adjust for difference
1097     if (forTotal) 
1098         size -= GetFutureAvail (pBufConfig);
1100     // return success if we needn't make any requests
1101     if (size <= 0)
1102         return 0;
1104     // assume if eight channel then using optimized dMAX routine which requires
1105     // requests which are a mulitple of 8 to operate correctly. If not a proper
1106     // multiple then we increase the requested size as needed. This information
1107     // is communicated to other portions of DIB indirectly through the update
1108     // of the futureHead pointer (here) and head pointer (in reclaim). To these
1109     // other portions it is a don't care as we ensure enough data requested will
1110     // be available at, the now slightly deferred, reclaim point. We assume that
1111     // the buffer is a multiple of 8 and so, by using this single statement, we
1112     // ensure all requests are a mulitple 8 even if they need to be split across
1113     // the buffer wrap point.
1114     if (pBufConfig->stride == 8)
1115         size = (size + 7) & ~0x7;
1117     // convert to bytes
1118     size = (size * pBufConfig->sizeofElement); //To Do: +2 GJ : Temporary, to get past initial hiccup.  // GJ Debug
1119     //size *= 4;
1121     // if request crosses circular buffer boundary then split into two requests
1122     futureHead = (int) pBufConfig->futureHead.pVoid + size;
1123     if (futureHead <= bufEnd) {
1124         sizes[0] = size;
1125         sizes[1] = 0;
1127         // If this request happens to be the rest of the buffer, then 
1128         // futureHead must be set to the beginning of the buffer.
1129         if (futureHead != bufEnd)
1130             endAddr[0] = (Ptr) futureHead;
1131         else
1132             endAddr[0] = pBufConfig->base.pVoid;
1133     }
1134     else {
1135         sizes[0] = bufEnd - (int) pBufConfig->futureHead.pVoid;
1136         sizes[1] = futureHead - bufEnd;
1137         endAddr[0] = pBufConfig->base.pVoid;
1138         endAddr[1] = (Ptr) ((int)pBufConfig->base.pVoid + sizes[1]);
1139     }
1141     for (i=0; i < 2; i++) {
1142         if (sizes[i]) {
1143             dstFrame = Queue_get (&((SIO2_Handle) pChild)->framelist);
1144             if (dstFrame == (DEV2_Frame *)&((SIO2_Handle) pChild)->framelist)
1145                 return DIBERR_UNSPECIFIED;
1146             dstFrame->arg = (Arg) pBufConfig;
1148             dstFrame->addr = pBufConfig->futureHead.pVoid;
1149             dstFrame->size = sizes[i];
1150             Queue_put (pChild->todevice, dstFrame);
1151             status = DEV2_issue (pChild);
1152             if (status)
1153                 return DIBERR_UNSPECIFIED;
1155             pBufConfig->futureHead.pVoid = endAddr[i];
1156             // GJ Debug
1157             if (i==1)
1158             {
1159                 gWrapCtr++;
1160                 Log_info4("DIB: Inside DIB_issueChild Wrap Around Point #%d, with Future Head: 0x%x, current addr: 0x%x, current size: %d", gWrapCtr, pBufConfig->futureHead.pVoid, dstFrame->addr, dstFrame->size ); // GJ Debug
1162             }
1163         }
1164     }
1166     return 0;
1167 } // DIB_issueChild
1169 // -----------------------------------------------------------------------------
1171 Int DIB_reclaimChild (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1173     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1174     DEV2_Handle              pChild = (DEV2_Handle)&pDevExt->child;
1175     DEV2_Frame              *srcFrame;
1176     int                     status, bufEnd;
1178     //Log_info3("DIB_reclaimChild.%d: Inside DEV2_reclaim(pChild) pChild = 0x%x DEV2_reclaim = 0x%x", __LINE__, pChild, &pChild->fxns.reclaim); // GJ Debug
1179     //TRACE((&TR_MOD, "DIB_reclaimChild.%d: calling DEV2_reclaim(pChild) pChild = 0x%x DEV2_reclaim = 0x%x", __LINE__, pChild, &pChild->fxns.reclaim));
1180     status = DEV2_reclaim (pChild);
1181     if (status)
1182     {
1183         Log_info2("DIB_reclaimChild.%d DEV2_reclaim() returned (%d) DIBERR_UNSPECIFIED", __LINE__, status); // GJ Debug
1184         //TRACE((&TR_MOD, "DIB_reclaimChild.%d DEV2_reclaim() returned (%d) DIBERR_UNSPECIFIED \n", __LINE__, status));
1185         return DIBERR_UNSPECIFIED;
1186     }
1188     //Log_info1("DIB_reclaimChild.%d calling Queue_get()", __LINE__); // GJ Debug
1189     //TRACE((&TR_MOD, "DIB_reclaimChild.%d calling Queue_get()\n", __LINE__));
1190     srcFrame = Queue_get (pChild->fromdevice);
1191     //Log_info2("DIB_reclaimChild.%d calling Queue_put(), srcFrame = 0x%x", __LINE__, srcFrame); // GJ Debug
1192     //TRACE((&TR_MOD, "DIB_reclaimChild.%d calling Queue_put(), srcFrame = 0x%x\n", __LINE__, srcFrame));
1193     Queue_put (&((SIO2_Handle) pChild)->framelist, srcFrame);
1195     // Only for non-fill requests do we update ptrs
1196     if (srcFrame->addr != NULL) {
1197         //Log_info2("DIB_reclaimChild.%d update pointers with srcFrame->size = %d", __LINE__, srcFrame->size); // GJ Debug
1198         //TRACE((&TR_MOD, "DIB_reclaimChild.%d update pointers\n", __LINE__));
1199         pBufConfig->head.pVoid = (Ptr) ((int)srcFrame->addr + srcFrame->size);
1201         // wrap, if necessary
1202         bufEnd = (int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer;
1203         if( (int) pBufConfig->head.pVoid >= bufEnd )
1204         {
1205             Log_info1("DIB_reclaimChild.%d wrap pointer", __LINE__); // GJ Debug
1206             //TRACE((&TR_MOD, "DIB_reclaimChild.%d wrap pointer\n", __LINE__));
1207             pBufConfig->head.pVoid = (Ptr) ((int) pBufConfig->base.pVoid + (int) pBufConfig->head.pVoid - bufEnd);
1208         }
1209     }
1211     Log_info2("DIB_reclaimChild.%d exit with status = %d", __LINE__, status); // GJ Debug
1212     //TRACE((&TR_MOD, "DIB_reclaimChild.%d exit with status = %d\n", __LINE__, status));
1214     return status;
1215 } // DIB_reclaimChild
1217 // -----------------------------------------------------------------------------
1218 // This function uses the local definition of frameLength and lengthofData in
1219 // pDevExt to request the next frame of data.
1221 Int DIB_requestFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1223     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1224     int status = 0;
1227     // if in steady state then update tail pointer to indicate we are done, i.e. no
1228     // longer own, the last frame of data.
1229     if (pDevExt->running > 1)
1230         IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pBufConfig->lengthofData);
1232     switch (pDevExt->syncState) {
1233         case SYNC_PCM:
1234         case SYNC_PCM_FORCED:
1235                     
1236             if (pDevExt->sourceSelect == PAF_SOURCE_DSD1)
1237                 pDevExt->frameLength = 256;
1238             else if (pDevExt->sourceSelect == PAF_SOURCE_DSD2)
1239                 pDevExt->frameLength = 128;
1240             else if (pDevExt->sourceSelect == PAF_SOURCE_DSD3)
1241                 pDevExt->frameLength = 64;
1242             else
1243                 pDevExt->frameLength = pDevExt->pcmFrameLength;
1245             pDevExt->lengthofData = pBufConfig->stride*pDevExt->frameLength;
1246             pDevExt->frameLength  = pDevExt->lengthofData;        
1248             // note that the following issueChild
1249             // doesn't *fetch* the data which will next be consumed,
1250             // but rather *replenishes* what's about to be consumed
1251             status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1252             break;
1254         case SYNC_ONE:
1255             // for the first issue we need to set the tail pointer to the bitstream sync
1256             pBufConfig->pntr = pDevExt->pSync;
1257             IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pDevExt->headerSize);
1258             status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->frameLength, 1);
1260             // HD codecs need extra time due to several factors
1261             //   time between first info call and starting output is non-negligible
1262             //   peak decoder MIPs
1263             //   reset time for decoders/ASPs
1264             if ((pDevExt->sourceProgram == PAF_SOURCE_DDP)   ||
1265                 (pDevExt->sourceProgram == PAF_SOURCE_DTSHD) ||
1266                 (pDevExt->sourceProgram == PAF_SOURCE_THD)   ||
1267                 (pDevExt->sourceProgram == PAF_SOURCE_DXP))
1268                 status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1270             pDevExt->syncState = SYNC_ONGOING;
1271             break;
1273         case SYNC_ONGOING:
1274             status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
1275             break;
1277     } //switch
1279     // update bufConfig with info for use in next reclaim call
1280     // the interface to DIB is based on a single frame. So the amount
1281     // of data requested in this issue is assumed to be what is wanted in the next
1282     // reclaim.
1283     pBufConfig->frameLength  = pDevExt->frameLength;
1284     pBufConfig->lengthofData = pDevExt->lengthofData;
1285     // enable to inspect input buffer.
1286     // if (pDevExt->lengthofData > 512)
1287     //     asm( " SWBP 0" );  // breakpoint
1290     if (pDevExt->running < 3)
1291         pDevExt->running++;
1293     // Goal is to align timing so synchronized with forthcoming
1294     // "DIB_waitForData (... pDevExt->lengthofData);"
1295     // in DIB_reclaim(), servicing PAF_SIO_REQUEST_NEWFRAME, for PAF_SOURCE_PCM/DSD?.
1296     // ** need to revise above DSD handling so it works w/ this calc. **
1297     {
1298         int futureAvail = GetFutureAvail (pBufConfig);
1299         // GetFutureAvail() returns 0 if full buffer requested or if no requests outstanding
1300         // -- 0 (empty) can't be right interpretation here, on account of foregoing issueChild()
1301         if( ! futureAvail)
1302             futureAvail = pBufConfig->sizeofBuffer / pBufConfig->sizeofElement; // total words in buffer
1303         pDevExt->numSamplesExtra = (XDAS_Int16) (futureAvail - pDevExt->frameLength);
1304     }
1306     return status;
1307 } // DIB_requestFrame
1309 // -----------------------------------------------------------------------------
1311 Int DIB_reset (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1313     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
1314     DEV2_Handle              pChild = (DEV2_Handle)&pDevExt->child;
1315     int status, numChan;
1318     //?? Do we need a shutdown to handle queue problems?
1319     // or are there no problems since we use one frame
1320     status = DEV2_idle (pChild, 1);
1321     if(status)
1322         return status;
1324     if (pBufConfig) {
1325         int sizeofStride;
1326         pBufConfig->pntr       = pBufConfig->base;
1327         pBufConfig->head       = pBufConfig->base;
1328         pBufConfig->futureHead = pBufConfig->base;
1330         pBufConfig->lengthofData = 0;
1332         //devices must? support 2byte words
1333         pBufConfig->sizeofElement = 2;
1334         status = SIO2_ctrl (pChild, (Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
1335         if(status)
1336             return status;
1338         status = DEV2_ctrl (pChild, PAF_SIO_CONTROL_GET_NUMCHANNELS, (Arg) &numChan);
1339         if(status)
1340             return status;
1341         pBufConfig->stride = numChan;
1343         // compute and use *effective buffer size*
1344         sizeofStride = pBufConfig->sizeofElement*pBufConfig->stride;
1345         pBufConfig->sizeofBuffer = pBufConfig->allocation/sizeofStride*sizeofStride;
1347         //hack -- save status context for use in close
1348         pDevExt->pInpBufStatus = pBufConfig->pBufStatus;
1349         pBufConfig->pBufStatus->lastFrameFlag = 0;
1351         pDevExt->bufConfig = *pBufConfig;
1352         pDevExt->pSync = pBufConfig->base;
1353     }
1355     pDevExt->syncState = SYNC_NONE;
1356     pDevExt->scanState = SCANNED_NONE;
1357     pDevExt->pcmTimeout = 0;
1358     pDevExt->deferredError = 0;
1360     pDevExt->numSamplesSinceDTS = 0;
1361     pDevExt->numSamplesExtra = 0;
1363     pDevExt->headerSize = 0;
1364     pDevExt->running = 0;
1366     return 0;
1367 } // DIB_reset
1369 // -----------------------------------------------------------------------------
1370 // Notes:
1371 //   1. The amount of data to be scanned will not result in a buffer wrap-around
1372 //   2. (1) is currently met from the two locations that call this function
1373 //          a. DIB_getSync
1374 //          b. DIB_reclaim (for PCM)
1375 //   3. We require that pTimeout != NULL since we dereference to make a const
1377 Int DIB_syncScan (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout)
1379     DIB_DeviceExtension   * restrict pDevExt = (DIB_DeviceExtension *)device->object;
1380     MdInt * restrict pTail, * restrict pShadowTail, * restrict pSync;
1381     MdInt *pLocalTail, pc;
1382     XDAS_Int8   scanState;
1383     XDAS_UInt32 zeroCount;
1384     int stride, numLeft, i, datId;
1385     int status, foundDTS = 0;
1386     Uns scanCount, pageSize;
1387     PAF_SIO_IALG_Obj    *pObj = pDevExt->pSioIalg;
1388     PAF_SIO_IALG_Config *pAlgConfig = &pObj->config;
1389     const int timeoutChanged = (*pTimeout != 2 * pBufConfig->pBufStatus->unknownTimeout);
1390     MdInt DTSHDSubType;
1392     // .........................................................................
1394     // works for both SYNC_NONE and SYNC_PCM
1395     numLeft = min (*pTimeout, GetNumAvail(pBufConfig));
1397     pTail = pBufConfig->pntr.pMdInt;
1398     pShadowTail = pBufConfig->pntr.pMdInt;
1400     // if scratch buffer present then assume it is needed for paging
1401     pageSize = numLeft*pBufConfig->sizeofElement;
1403     Log_info3("DIB: Entered DIB_syncScan with pTail = 0x%x & numLeft = %d, timeout = %d", pTail, numLeft, *pTimeout); // GJ Debug
1406     if ((pAlgConfig->numRec > 1) && pAlgConfig->pMemRec[1].base && (pAlgConfig->pMemRec[1].size >= pageSize)) {
1407         pTail = pAlgConfig->pMemRec[1].base;
1408         datId = DAT_copy ((void *) pShadowTail, (void *) pTail, pageSize);
1409         DAT_wait (datId);
1410     }
1412     if (pBufConfig->sizeofElement == 4) {
1413         Log_info0("DIB: SyncScan - Inside pBufConfig->sizeofElement == 4"); // GJ Debug
1414         stride = 2;
1415         pTail += 1; // point at MSB
1416         pShadowTail += 1;
1417     }
1418     else
1419         stride = 1;
1421     // .........................................................................
1423     // scan until out of available data or a sync found
1424     scanCount = 0;
1425     zeroCount = pDevExt->zeroCount;
1426     scanState = pDevExt->scanState;
1427     pSync     = pDevExt->pSync.pMdInt;
1429     Log_info3("DIB: Entered DIB_syncScan with zeroCount = %d & scanState = %d, pSync = 0x%x", zeroCount, scanState, pSync); // GJ Debug
1431     // scan until out of available data or a sync found
1432     for (i=0; i < numLeft; i++) {
1433         MdInt tail = pTail[i*stride];
1435         // assumes SCANNED_NONE = 0
1436         if (!scanState) {
1437             if (tail == IEC_PA) {
1438                 // since above code handles ongoing sync we are
1439                 //  safe to check for extended sync here. i.e.
1440                 //  two zeros before PA.
1441                 if (zeroCount >= 2) {
1442                     scanState = SCANNED_IEC_PA;
1443                     pSync = &pShadowTail[i*stride];
1444                 }
1445             }
1446             else if (tail == DTS14_SYNC_A) {
1447                 scanState = SCANNED_DTS14_SYNC_A;
1448                 pSync = &pShadowTail[i*stride];
1449             }
1450             else if (tail == DTS16_SYNC_A) {
1451                 scanState = SCANNED_DTS16_SYNC_A;
1452                 pSync = &pShadowTail[i*stride];
1453             }
1455             // limit count to prevent wrap around
1456             zeroCount = min (zeroCount+1,INT_MAX - 1);
1457             if (tail != 0x0000)
1458                 zeroCount = 0;
1460             // don't start counting until we get the first non-zero
1461             // sample while UNKNOWN. Note we don't have to worry
1462             // about the other scanCount increments since these
1463             // only occur after the first non-zero sample.
1464             //
1465             // so don't count unless
1466             //    . we are already started counting (in this call) ||
1467             //    . we started counting in an earlier scanForSync (timeout has changed) ||
1468             //    . the last sample was non-zero
1469             if (scanCount || (tail != 0x0000) || timeoutChanged)
1470             {
1471                 //Log_info3("DIB: DIB_syncScan scanCount = %d tail = %d timeoutChanged = %d", scanCount, tail, timeoutChanged); // GJ Debug
1472                 scanCount += 1;
1473             }
1476             continue;
1477         }
1479         // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1481         switch (scanState) {
1483             case SCANNED_DTS16_SYNC_A:
1484                 if (tail == DTS16_SYNC_B) {
1485                     scanState = SCANNED_DTS16_SYNC_B;
1486                     scanCount += 1;
1487                 }
1488                 else
1489                     scanState = SCANNED_NONE;
1490                 break;
1492                 // wait for header data to get payload size via
1493                 // nblks/fsize
1494             case SCANNED_DTS16_SYNC_B:
1495                 // use extended sync
1497                 if ((short)(tail & 0xFC00) == DTS16_SYNC_C) {
1498                     scanState = SCANNED_DTS16_SYNC_C;
1499                     scanCount += 1;
1500                 }
1501                 else
1502                     scanState = SCANNED_NONE;
1503                 break;
1505                 // `````````````````````````````````````````````````````````````````````````
1506                 // check for 2nd word of DTS-14 sync
1507             case SCANNED_DTS14_SYNC_A:
1508                 if (tail == DTS14_SYNC_B) {
1509                     scanState = SCANNED_DTS14_SYNC_B;
1510                     scanCount += 1;
1511                 }
1512                 else
1513                     scanState = SCANNED_NONE;
1514                 break;
1516                 // check for 3rd word of DTS-14 sync
1517             case SCANNED_DTS14_SYNC_B:
1518                 // if here then looking for extended 38 bit sync
1519                 if ((short)(tail & 0xFFF0) == DTS14_SYNC_C) {
1520                     scanState = SCANNED_DTS14_SYNC_C;
1521                     scanCount += 1;
1522                 }
1523                 else
1524                     scanState = SCANNED_NONE;
1525                 break;
1527                 // wait for header data to get payload size via
1528                 //   nblks/fsize
1529             case SCANNED_DTS14_SYNC_C:
1530                 scanState = SCANNED_DTS14_SYNC_D;
1531                 scanCount += 1;
1532                 break;
1534                 // `````````````````````````````````````````````````````````````````````````
1535                 // if here then all of header is buffered
1536             case SCANNED_DTS16_SYNC_C:
1537             case SCANNED_DTS14_SYNC_D:
1538                 // update sync to point at beginning of DTS header as syncScanDTS uses this info
1539                 pDevExt->scanState    = scanState;
1540                 pDevExt->pSync.pMdInt = pSync;
1541                 status = DIB_FTABLE_syncScanDTS (device, pBufConfig, pTimeout, (XDAS_UInt16 *) &pShadowTail[i*stride]);
1542                 scanState = pDevExt->scanState;
1543                 if (status)
1544                     return status;
1545                 foundDTS = 1;
1546                 if (pDevExt->syncState == SYNC_ONE)
1547                     goto syncScanExit;
1548                 break;
1550                 // `````````````````````````````````````````````````````````````````````````
1552                 // note that the round about detection of IEC only
1553                 // happens for the first sync so the extra states are OK.
1554             case SCANNED_IEC_PA:
1555                 if (tail == IEC_PB) {
1556                     scanState = SCANNED_IEC_PB;
1557                     scanCount += 1;
1558                     Log_info0("DIB: SyncScan Inside case - SCANNED_IEC_PA - if path"); // GJ Debug
1559                 }
1560                 else
1561                 {
1562                     Log_info0("DIB: SyncScan Inside case - SCANNED_IEC_PA - else path"); // GJ Debug
1563                     scanState = SCANNED_NONE;
1564                 }
1565                 break;
1567             case SCANNED_IEC_PB:
1568                 // Update scanCount here since, at this point, we are confident that
1569                 // this is a proper IEC stream. Regardless if we ignore it our not.
1570                 // Therefore we want to properly signal that this data has been scanned.
1571                 scanCount += 1;
1573                 // check for IEC pause packets at this time and if required ignore them.
1574                 // By construction we are guaranteed to have tail=PC at this time.
1575                 if ((pBufConfig->pBufStatus->mode == MODE_NO_ZERORUNRESTART) ||
1576                     (pBufConfig->pBufStatus->mode == MODE_NO_ZERORUN)) {
1577                     MdInt pc = tail & 0x1F;
1579                     if ((pc == 0) || (pc == 3)) {
1580                         scanState = SCANNED_NONE;
1581                         break;
1582                     }
1583                 }
1585                 scanState = SCANNED_IEC_PC;
1586                 break;
1588             case SCANNED_IEC_PC:
1589                 pLocalTail = pSync;
1590                 IncrementPtr (pBufConfig, (Ptr *)  &pLocalTail, 2);
1591                 pc = *pLocalTail & 0x1F;
1592                 pDevExt->headerSize = IEC_HEADER_SIZE;
1594                 Log_info0("DIB: Sync Scan - Inside case: SCANNED_IEC_PC"); // GJ Debug
1595                 // Handle DTSHD subtype (LBR)
1596                 if (pc == 0x11) {
1597                     pDevExt->headerSize +=6;
1598                     DTSHDSubType = (*pLocalTail & 0x700)>>8;
1599                 }
1600                 // DDP or THD
1601                 if (pc == 21 || pc ==22) {
1602                     TRACE((&TR_MOD, "Dolby: useIECSubType is 0x%x.\n", pBufConfig->pBufStatus->useIECSubType));
1603                     if (pBufConfig->pBufStatus->useIECSubType == 1) {
1604                         unsigned char IECSubType = *pLocalTail & 0x60;
1605                         TRACE((&TR_MOD, "Dolby: IECSubType is 0x%x.\n", IECSubType));
1606                         if (IECSubType != 0) {
1607                             pDevExt->sourceProgram = PAF_SOURCE_UNKNOWN;
1608                             pDevExt->frameLength = 0;
1609                         }
1610                     }
1611                 }
1612                 // don't know how to support other types
1613                 if (pc > 22)
1614                 {
1615                     Log_info1("DIB:  Unknown IEC type 0x%x encountered.\n", pc); // GJ Debug
1616                     return DIBERR_SYNC;
1617                 }
1619                 pDevExt->syncState = SYNC_ONE;
1620                 pBufConfig->pntr.pMdInt = pSync;
1621                 pDevExt->sourceProgram = iecPafSource[pc];
1623                 Log_info2("source is %d.  pc is %d.", iecPafSource[pc], pc); // GJ Debug 
1624                 //TRACE((&TR_MOD, "source is %d.  pc is %d.\n", iecPafSource[pc], pc));
1626                 if (pc == 0x11 && DTSHDSubType == 3 && (PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD] <=48000.0))
1627                     pDevExt->sourceProgram = PAF_SOURCE_DXP;    // LBR is 23
1628              
1629                 pDevExt->frameLength = pDevExt->pIECFrameLength[pc];
1630                 pDevExt->lengthofData = pDevExt->frameLength;
1631                 if (pc == 1)
1632                     pDevExt->frameLength = 4288;
1633                 else if (pc == 0x11) {
1634                     pDevExt->frameLength = (pDevExt->pIECFrameLength[pc] << DTSHDSubType);
1635                     pDevExt->lengthofData = pDevExt->frameLength;
1636                 }
1638                 goto syncScanExit;
1640         } // switch
1641     } // for
1643     // .............................................................................
1645 syncScanExit:
1646     Log_info4("DIB inside syncScanExit.  pTimeout = %d, scanCount = %d, zeroCount = %d, numLeft = %d", *pTimeout,scanCount, zeroCount, numLeft ); // GJ Debug
1647     pDevExt->zeroCount    = zeroCount;
1648     pDevExt->scanState    = scanState;
1649     pDevExt->pSync.pMdInt = pSync;
1651     if (pDevExt->zeroCount >= 2 * pBufConfig->pBufStatus->zeroRunTrigger)
1652         pBufConfig->pBufStatus->zeroRun = 1;
1653     else
1654         pBufConfig->pBufStatus->zeroRun = 0;
1656     // If detected an initial DTS sync in a previous buffer then add the
1657     // number of samples in this buffer to the tally.
1658     // TODO: should we add numLeft instead of lengthofData?
1659     if (!foundDTS && pDevExt->numSamplesSinceDTS)
1660         pDevExt->numSamplesSinceDTS += pBufConfig->lengthofData;
1662     if (*pTimeout > scanCount)
1663         *pTimeout -= scanCount;
1664     else {
1665         *pTimeout = 0;
1666         return 0;
1667     }
1669     // This flushes the current scanned buffer if a sync is not found
1670     // Note that this code is not executed when *pTimeout = 0. 
1671     // TODO: should this be moved elsewhere. Like in requestFrame?
1672     //       seems like this should be done in request frame for continuous modes
1673     //       and in getSync for traditional modes.
1674     //       What does it mean that this is not executed when we have timed out to PCM
1675     if (pDevExt->syncState == SYNC_NONE || pDevExt->syncState == SYNC_AUTO) {
1676         IncrementPtr (pBufConfig, (Ptr *) &pBufConfig->pntr.pMdInt, numLeft);
1677         return 0;
1678     }
1680     return 0;
1681 } // DIB_syncScan
1683 // -----------------------------------------------------------------------------
1684 // Assumes scanState is SCANNED_DTS16_SYNC_C or SCANNED_DTS14_SYNC_D
1686 Int DIB_syncScanDTS (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 *pTimeout, XDAS_UInt16 *pHeaderEnd)
1688     DIB_DeviceExtension  *pDevExt = (DIB_DeviceExtension *)device->object;
1689     Int sourceProgram = (pDevExt->scanState == SCANNED_DTS14_SYNC_D) ? PAF_SOURCE_DTS14  : PAF_SOURCE_DTS16;
1690     float sampleRate = PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD];
1691     MdInt *pLocalTail, pc, pd;
1692     int nblks;
1695     // compute repetition rate as predicted by DTS header
1696     pLocalTail = pDevExt->pSync.pMdInt;
1697     IncrementPtr (pBufConfig, (Ptr *) &pLocalTail, 2);
1698     pc = *pLocalTail;
1699     if (pDevExt->scanState == SCANNED_DTS16_SYNC_C)
1700         nblks = (pc & 0x01FC) >> 2;
1701     else {
1702         IncrementPtr (pBufConfig, (Ptr *) &pLocalTail, 1);
1703         pd = *pLocalTail;
1704         nblks = (pc & 0x7) << 4;
1705         nblks |= (pd & 0x3C00) >> 10;
1706     }
1708     // if samplerate > 44.1k and DTS16 bit CD then report as DTS-DVD
1709     // this is a work around to the possibility that DTS-DVD is being
1710     // sent but, due to the variance in input recording, we may have
1711     // missed the IEC header. This is predicated on the enable register
1712     if (pBufConfig->pBufStatus->reportDTS16AsDTSForLargeSampleRate &&
1713         (sampleRate > 44100) && (sourceProgram == PAF_SOURCE_DTS16))
1714         sourceProgram = PAF_SOURCE_DTS;
1716     // point at LSB, if neceesary, so that space calculation is correct
1717     if (pBufConfig->sizeofElement == 4)
1718         pHeaderEnd -= 1;
1720     // If in PCM mode then require double sync, at an appropriate spacing,
1721     // in order to determine DTS validity.
1722     if (pDevExt->syncState == SYNC_PCM) {
1723         int diff;
1725         // If we have started counting, i.e. found a previous sync,
1726         // then compute sync spacing.
1727         if (pDevExt->numSamplesSinceDTS) {
1728             // determine distance since last sync
1729             //    pHeaderEnd, which points at the end of the DTS header, is guaranteed
1730             //    to be in the active buffer. Whereas the pointer to the beginning of the header (pSync)
1731             //    may have occured in the previous buffer.
1732             diff = ((int) pHeaderEnd - (int) pBufConfig->pntr.pVoid);
1733             if (diff < 0)
1734                 diff += pBufConfig->sizeofBuffer;
1735             diff /= pBufConfig->sizeofElement;
1736             diff += pDevExt->numSamplesSinceDTS;
1738             // if spacing incorrect then reset sample count to
1739             // force next conditional to be true.
1740             if (diff != (nblks+1)*32*2)
1741                 pDevExt->numSamplesSinceDTS = 0;
1742         }
1744         // If this is the 1st sync detected or if this is the second sync
1745         // but the spacing between DTS syncs did not match that predicted by
1746         // NBLKS, then this is not DTS data. Therefore the previous DTS sync
1747         // word was not valid and so it is safe to reset the count based on
1748         // this secondary sync word. This latter sync may or may not be valid;
1749         // we don't know yet. In both cases init sync spacing count, reset
1750         // scan state, and continue. Note that there is a positive, albeit
1751         // quite small, probability of falsing in a pathological case where
1752         // the PCM data, interpreted as a DTS header and used to compute NBLKS,
1753         // actually matches the fake DTS syncs in the PCM file.
1754         if (!pDevExt->numSamplesSinceDTS) {
1755             diff = (int) pBufConfig->head.pVoid - (int) pHeaderEnd;
1756             if (diff <= 0)
1757                 diff += pBufConfig->sizeofBuffer;
1758             diff /= pBufConfig->sizeofElement;
1759             pDevExt->numSamplesSinceDTS = diff;
1760             pDevExt->scanState = SCANNED_NONE;
1761             return 0;
1762         }
1763     } //SYNC_PCM
1765     pDevExt->lengthofData = (nblks+1)*32*2;
1766     if (pDevExt->scanState == SCANNED_DTS16_SYNC_C)
1767         pDevExt->frameLength = pDevExt->lengthofData + 4;
1768     else
1769         pDevExt->frameLength = pDevExt->lengthofData + 6;
1771     pDevExt->syncState = SYNC_ONE;
1772     pBufConfig->pntr = pDevExt->pSync;
1773     pDevExt->sourceProgram = sourceProgram;
1775     return 0;
1776 } //DIB_syncScanDTS
1778 // -----------------------------------------------------------------------------
1779 // This function is responsible for verifying bitstream sync (if applicable) and
1780 // configuring the sizes of the next frame of data.
1782 Int DIB_initFrame (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
1784     DIB_DeviceExtension  * restrict pDevExt = (DIB_DeviceExtension *) device->object;
1785     MdInt * restrict pTail;
1786     MdInt pa, pb, pc;
1787     unsigned char DTSHDSubType;
1788     PAF_UnionPointer     ac3SearchPtr;
1791     // MID 810
1792     // TODO: is this needed anymore? can we combine above and this?
1793     // I don't think this is needed since pSync is guaranteed to be
1794     // valid under all cases where this function is called.
1795     if (!(pDevExt->scanState == SCANNED_DTS14_SYNC_D ||
1796           pDevExt->scanState == SCANNED_DTS16_SYNC_C ||
1797           pDevExt->scanState == SCANNED_IEC_PC ))
1798         return 0;
1800     // minimum possible distance from current IEC sync to next is 1856 words
1801     // capture this here before we update pSync following
1802     ac3SearchPtr = pDevExt->pSync; 
1804     // for steady state compute expected sync location
1805     if (pDevExt->syncState == SYNC_ONGOING) 
1806         IncrementPtr (pBufConfig, &pDevExt->pSync.pVoid, pBufConfig->lengthofData);
1808     pTail = pDevExt->pSync.pMdInt;
1809     pa = *pTail;
1810     IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1811     pb = *pTail;
1812     IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1813     pc = *pTail;
1814     IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1816     switch (pDevExt->scanState) {
1817         // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1819         case SCANNED_DTS14_SYNC_D:
1820             // check sync (extended sync checked above for 1st sync)
1821             if ((pa != DTS14_SYNC_A) || (pb != DTS14_SYNC_B) || ((pc & 0xFC00) != (DTS14_SYNC_C & 0xFC00)))
1822                 return DIBERR_SYNC;
1823             break;
1825             // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1827         case SCANNED_DTS16_SYNC_C:
1828             // check sync (extended sync checked above for 1st sync)
1829             if ((pa != DTS16_SYNC_A) || (pb != DTS16_SYNC_B))
1830                 return DIBERR_SYNC;
1831             break;
1833             // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1835         case SCANNED_IEC_PC:
1836             // check for sync
1837             //    special handling for AC3 variable bit rate (VBR)
1838             //       start looking for sync at max payload sync location and
1839             //       scan forward. Note that getSync() has waited for
1840             //       sufficient data to arrive so that we can determine reliably
1841             //       the presence or absence of a correct sync.
1843             if ((pa != IEC_PA) || (pb != IEC_PB)) {
1844                 PAF_SIO_IALG_Obj    *pObj = pDevExt->pSioIalg;
1845                 PAF_SIO_IALG_Config *pAlgConfig = &pObj->config;
1846                 int scan1, scan2, searchIdx, datId;
1847                 const int bufEnd = (int) pBufConfig->base.pVoid + pBufConfig->sizeofBuffer;
1850                 // only extend IEC search in the case of AC3
1851                 if (pDevExt->sourceProgram != PAF_SOURCE_AC3)
1852                     return DIBERR_SYNC;
1854                 // move search ptr to earliest possible location of next sync
1855                 IncrementPtr (pBufConfig, &ac3SearchPtr.pVoid, 1856);
1857                 // compute number of samples between earliest possible sync location
1858                 // (ac3SearchPtr) and latest possible sync location (head)
1859                 scan1 = (int) pBufConfig->head.pVoid - (int) ac3SearchPtr.pVoid;
1860                 if (scan1 < 0) {
1861                     // here if search will wrap around so split search into two
1862                     // halves to accomodate circular buffer
1863                     scan1 = bufEnd - (int) ac3SearchPtr.pVoid;
1864                     scan2 = (int) pBufConfig->head.pVoid - (int) pBufConfig->base.pVoid;
1865                 }
1866                 else
1867                     scan2 = 0;
1869                 // page if necessary (assume so if second memRec present)
1870                 if (pAlgConfig->numRec > 1) {
1871                     // if invalid buffer or if page buffer not big enough for either split then error
1872                     if (!pAlgConfig->pMemRec[1].base ||
1873                         (pAlgConfig->pMemRec[1].size < max(scan1,scan2)))
1874                         return DIBERR_UNSPECIFIED;
1876                     pTail = (MdInt *) pAlgConfig->pMemRec[1].base;
1877                     datId = DAT_copy (ac3SearchPtr.pVoid, (void *) pTail, scan1);
1878                     DAT_wait (datId);
1879                 }
1880                 else
1881                     pTail = ac3SearchPtr.pMdInt;
1883                 // convert to number of words
1884                 scan1 /= pBufConfig->sizeofElement;
1886                 // if non-zero must be IEC header, otherwise sync error
1887                 // update pointer after check so that it remains
1888                 // pointed at first non-zero word when breaking
1889                 searchIdx = 0;
1890                 while (scan1--) {
1891                     if (*pTail != 0) {
1892                         // force skip of any possible split scan since we found non-zero word
1893                         scan2 = 0;
1894                         break;
1895                     }
1896                     *pTail++;
1897                     searchIdx++;
1898                 }
1900                 // perform second half of circular buffer search if necessary
1901                 if (scan2) {
1902                     // page if necessary, note no need to check valid buffer
1903                     // or space since this is ensured in first scan
1904                     if (pAlgConfig->numRec > 1) {
1905                         pTail = (MdInt *) pAlgConfig->pMemRec[1].base;
1906                         datId = DAT_copy (pBufConfig->base.pVoid, (void *) pTail, scan2);
1907                         DAT_wait (datId);
1908                     }
1909                     else
1910                         pTail = pBufConfig->base.pMdInt;
1912                     // convert to number of words
1913                     scan2 /= pBufConfig->sizeofElement;
1915                     while (scan2--) {
1916                         if (*pTail != 0)
1917                             break;
1918                         *pTail++;
1919                         searchIdx++;
1920                     }
1921                 }
1923                 // if using paging buffer then translate search pointer back into circular buffer
1924                 if (pAlgConfig->numRec > 1) {
1925                     pTail = ac3SearchPtr.pMdInt;
1926                     IncrementPtr (pBufConfig, (Ptr *) &pTail, searchIdx);
1927                 }
1929                 // update sync in expection of success, if it is not a sync then no
1930                 // harm since it will be ignored then reset
1931                 pDevExt->pSync.pMdInt = pTail;
1933                 // above search only scans for the first non-zero word.
1934                 // here is common check to make sure that non-zero data is an IEC sync.
1935                 pa = *pTail;
1936                 IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1937                 pb = *pTail;
1938                 IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1939                 pc = *pTail;
1940                 IncrementPtr (pBufConfig, (Ptr *) &pTail, 1);
1941                 if ((pa != IEC_PA) || (pb != IEC_PB))
1942                     return DIBERR_SYNC;
1943             }
1945             // compute possible DTSHD sub type before masking pc
1946             DTSHDSubType = (pc & 0x700) >> 8;
1948             // mask pc to get data type only
1949             pc = pc & 0x1F;
1951             // don't know how to support other types
1952             // this also ensures that the below array access is bounded
1953             if (pc > 22)
1954                 return DIBERR_SYNC;
1956             // continuing frame must be same as current type otherwise
1957             // we return error to force reset of decode and input
1958             // classification state machines
1959             if (pDevExt->sourceProgram != iecPafSource[pc]) {
1960                 if (DTSHDSubType == 3 &&
1961                     (PAF_ASP_sampleRateHzTable[pBufConfig->pBufStatus->sampleRateStatus][PAF_SAMPLERATEHZ_STD] <= 48000.0))  {
1962                     if (pDevExt->sourceProgram != PAF_SOURCE_DXP)
1963                         return DIBERR_SYNC;
1964                 }
1965                 else
1966                     return DIBERR_SYNC;
1967             }
1968             break;
1970             // ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1971     } //switch
1973     return 0;
1974 } // DIB_initFrame
1976 // -----------------------------------------------------------------------------
1978 Int DIB_waitForData (DEV2_Handle device, PAF_InpBufConfig *pBufConfig, XDAS_UInt32 count )
1980     DIB_DeviceExtension  *pDevExt = (DIB_DeviceExtension *) device->object;
1981     DEV2_Handle            pChild = (DEV2_Handle) &pDevExt->child;
1982     Int status, lock;
1984     Log_info2("DIB_waitForData.%d count = %d", __LINE__, count); // GJ Debug
1985     //TRACE((&TR_MOD, "DIB_waitForData.%d count = %d\n", __LINE__, count));
1987     while (GetNumAvail(pBufConfig) < count) {
1988         PAF_SIO_InputStatus inputStatus;
1990         // query underlying device for lock status & check lock override register
1991         // dont wait without lock
1992         status = SIO2_ctrl (pChild, (Uns)PAF_SIO_CONTROL_GET_INPUT_STATUS, (Arg) &inputStatus);
1993         if (status)
1994         {
1995             Log_info2("DIB_waitForData.%d SIO2_ctrl() returned %d", __LINE__, status); // GJ Debug
1996             //TRACE((&TR_MOD, "DIB_waitForData.%d SIO2_ctrl() returned %d\n", __LINE__, status));
1997             return status;
1998         }
1999         lock = inputStatus.lock;
2000 #ifndef IGNORE_LOCK_OVERRIDE
2001         if ((pBufConfig->pBufStatus->lockOverride & (XDAS_Int8)0x80) == 0)
2002         {
2003             Log_info1("DIB_waitForData.%d lock = lockOverride\n", __LINE__); // GJ Debug
2004             //TRACE((&TR_MOD, "DIB_waitForData.%d lock = lockOverride\n", __LINE__));
2005             lock = pBufConfig->pBufStatus->lockOverride;
2006         }
2007 #endif
2008         if (!lock)
2009         {
2010             Log_info1("DIB_waitForData.%d no lock, return DIBERR_SYNC\n", __LINE__); // GJ Debug
2011             //TRACE((&TR_MOD, "DIB_waitForData.%d no lock, return DIBERR_SYNC\n", __LINE__));
2012             return DIBERR_SYNC;
2013         }
2014         // check that decoding still requested -- allows for status
2015         // register to be updated via IOS to cancel autoProcessing
2016         if (pDevExt->pDecodeStatus) {
2017             if (pDevExt->pDecodeStatus->sourceSelect == PAF_SOURCE_NONE)
2018             {
2019                 Log_info1("DIB_waitForData.%d sourceSelect is NONE, return DIBERR_SYNC", __LINE__); // GJ Debug
2020                 //TRACE((&TR_MOD, "DIB_waitForData.%d sourceSelect is NONE, return DIBERR_SYNC\n", __LINE__));
2021                 return DIBERR_SYNC;
2022             }
2023         }
2025         Log_info1("DIB_waitForData.%d calling DIB_FTABLE_reclaimChild()", __LINE__); // GJ Debug
2026         //TRACE((&TR_MOD, "DIB_waitForData.%d calling DIB_FTABLE_reclaimChild()\n", __LINE__));
2027         status = DIB_FTABLE_reclaimChild (device, pBufConfig);
2028         if(status)
2029         {
2030             Log_info2("DIB_waitForData.%d DIB_FTABLE_reclaimChild() returned %d", __LINE__, status); // GJ Debug
2031             //TRACE((&TR_MOD, "DIB_waitForData.%d DIB_FTABLE_reclaimChild() returned %d\n", __LINE__, status));
2032             return status;
2033         }
2034     }
2036     return 0;
2037 } // DIB_waitForData
2039 // -----------------------------------------------------------------------------
2040 #ifdef IEC_ENCODE
2042 // FS9 only supports PCM input so return error if not PCM.
2044 Int DIB_requestFrame_957 (DEV2_Handle device, PAF_InpBufConfig *pBufConfig)
2046     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *) device->object;
2047     int i, head, tail, avail, status;
2050     if (pDevExt->sourceProgram != PAF_SOURCE_PCM)
2051         return DIBERR_SYNC;
2053     // if in steady state then update tail pointer to indicate we are done, i.e. no
2054     // longer own, the last frame of data. 
2055     if (pDevExt->running > 1)
2056         IncrementPtr (pBufConfig, &pBufConfig->pntr.pVoid, pBufConfig->lengthofData);
2058     pDevExt->lengthofData = pBufConfig->stride*pDevExt->pcmFrameLength;
2059     pDevExt->frameLength  = pDevExt->lengthofData;        
2061     // note that due to MID 1037 it is required to check the return status after this call
2062     status = DIB_FTABLE_issueChild (device, pBufConfig, pDevExt->lengthofData, 0);
2063     if (status)
2064         return status;
2066     // add extra input delay to account for peak encoder mips
2067     for (i=0; i < 4; i++) {
2068         head = (int) pBufConfig->futureHead.pVoid;
2069         tail = (int) pBufConfig->pntr.pVoid;
2070         // compute how much data we have including outstanding requests
2071         if (head >= tail)
2072             avail = head - tail;
2073         else
2074             avail = head - tail + pBufConfig->sizeofBuffer;
2076         // convert to words
2077         avail /= pBufConfig->sizeofElement;
2078         if (avail < 4*pBufConfig->lengthofData) {
2079             status = DIB_FTABLE_issueChild (device, pBufConfig, pBufConfig->lengthofData, 0);
2080             if (status)
2081                 return status;
2082         }
2083     }
2085     pBufConfig->frameLength  = pDevExt->frameLength;
2086     pBufConfig->lengthofData = pDevExt->lengthofData;
2088     if (pDevExt->running < 3)
2089         pDevExt->running++;
2091     return 0;
2092 } // DIB_requestFrame_957
2094 #endif /* IEC_ENCODE */
2096 // -----------------------------------------------------------------------------
2098 #ifdef DSD_OVER_SPDIF
2100 Int DIB_requestFrame_patch (DEV2_Handle device, PAF_InpBufConfig *pBufConfig )
2102     DIB_DeviceExtension    *pDevExt = (DIB_DeviceExtension *)device->object;
2103     int status;
2105     status = DIB_requestFrame (device, pBufConfig);
2106     // For testing DSD over SPDIF i.e. 1 pin vs actual over 6 pin
2107     pDevExt->numSamplesExtra += pDevExt->lengthofData;
2108     pDevExt->lengthofData *=6;
2109     pDevExt->numSamplesExtra -= pDevExt->lengthofData;
2111     return status;
2112 } // DIB_requestFrame
2114 Int DIB_getSync_patch (DEV2_Handle device, PAF_InpBufConfig *pBufConfig )
2116     DIB_DeviceExtension   *pDevExt = (DIB_DeviceExtension *)device->object;
2117     DEV2_Handle             pChild = (DEV2_Handle)&pDevExt->child;
2118     int status;
2120     status=DIB_getSync (device, pBufConfig );
2121     if(status)
2122         return status;
2124     pBufConfig->sizeofElement = 2;
2125     status = SIO2_ctrl (pChild,(Uns)PAF_SIO_CONTROL_SET_WORDSIZE,pBufConfig->sizeofElement);
2126     if (status)
2127         return status;
2129     // compute and use *effective buffer size*
2130     {
2131         int sizeofStride = pBufConfig->sizeofElement*pBufConfig->stride;
2132         pBufConfig->sizeofBuffer = pBufConfig->allocation/sizeofStride*sizeofStride;
2133     }
2134     //..........................................................................
2136     return 0;
2137 } // DIB_getSync_patch
2139 #endif /* DSD_OVER_SPDIF */
2141 // -----------------------------------------------------------------------------