BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / audio / echo / generic / C3gDco.cpp
blobeb29b5de62c5c9c2e1f047829cab6f6eb24a9574
1 // ****************************************************************************
2 //
3 // C3gDco.cpp
4 //
5 // Implementation file for EchoGals generic driver 3G DSP
6 // interface class.
7 //
8 // ----------------------------------------------------------------------------
9 //
10 // This file is part of Echo Digital Audio's generic driver library.
11 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
12 // All rights reserved
13 // www.echoaudio.com
15 // This library is free software; you can redistribute it and/or
16 // modify it under the terms of the GNU Lesser General Public
17 // License as published by the Free Software Foundation; either
18 // version 2.1 of the License, or (at your option) any later version.
20 // This library is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 // Lesser General Public License for more details.
25 // You should have received a copy of the GNU Lesser General Public
26 // License along with this library; if not, write to the Free Software
27 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 // ****************************************************************************
31 #include "CEchoGals.h"
32 #include "C3gDco.h"
34 #include "Echo3gDSP.c"
35 #include "3G_ASIC.c"
37 /****************************************************************************
39 Construction and destruction
41 ****************************************************************************/
43 //===========================================================================
45 // Constructor
47 //===========================================================================
49 C3gDco::C3gDco
51 PDWORD pdwRegBase, // Virtual ptr to DSP registers
52 PCOsSupport pOsSupport
53 ) : CDspCommObject( pdwRegBase, pOsSupport )
55 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base fixme put this in base class
57 m_dwOriginalBoxType = NO3GBOX;
58 m_dwCurrentBoxType = m_dwOriginalBoxType;
59 SetChannelCounts();
60 m_bBoxTypeSet = FALSE;
62 m_fHasVmixer = FALSE;
64 m_wNumMidiOut = 1; // # MIDI out channels
65 m_wNumMidiIn = 1; // # MIDI in channels
67 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 );
68 m_pDspCommPage->dw3gFreqReg = SWAP( (DWORD) (E3G_MAGIC_NUMBER / 48000) - 2);
70 m_bHasASIC = TRUE;
72 m_pwDspCodeToLoad = pwEcho3gDSP;
74 m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA;
76 m_bProfessionalSpdif = FALSE;
77 m_bNonAudio = FALSE;
79 } // C3gDco::C3gDco( DWORD dwPhysRegBase )
83 //===========================================================================
85 // Destructor
87 //===========================================================================
89 C3gDco::~C3gDco()
91 } // C3gDco::~C3gDco()
95 //===========================================================================
97 // Supported digital modes depend on what kind of box you have
99 //===========================================================================
101 DWORD C3gDco::GetDigitalModes()
103 DWORD dwModes;
105 dwModes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
106 ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
107 ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
109 return dwModes;
113 /****************************************************************************
115 Hardware setup and config
117 ****************************************************************************/
119 //===========================================================================
121 // 3G has an ASIC in the external box
123 //===========================================================================
125 BOOL C3gDco::LoadASIC()
127 DWORD dwControlReg;
129 if ( m_bASICLoaded == TRUE )
130 return TRUE;
132 ECHO_DEBUGPRINTF(("C3gDco::LoadASIC\n"));
135 // Give the DSP a few milliseconds to settle down
137 m_pOsSupport->OsSnooze( 2000 );
140 // Load the ASIC
142 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_3G_ASIC,
143 pb3g_asic,
144 sizeof(pb3g_asic) ) )
145 return FALSE;
148 // Give the ASIC a whole second to set up
150 m_pOsSupport->OsSnooze( 1000000 );
153 // See if it worked
155 CheckAsicStatus();
158 // Set up the control register if the load succeeded -
160 // 48 kHz, internal clock, S/PDIF RCA mode
162 if ( m_bASICLoaded )
164 dwControlReg = E3G_48KHZ;
165 WriteControlReg( dwControlReg, E3G_FREQ_REG_DEFAULT, TRUE); // TRUE == force write
168 ECHO_DEBUGPRINTF(("\t3G ASIC loader finished\n"));
170 return m_bASICLoaded;
172 } // BOOL C3gDco::LoadASIC()
176 //===========================================================================
178 // Set the input clock
180 //===========================================================================
182 ECHOSTATUS C3gDco::SetInputClock(WORD wClock)
184 DWORD dwControlReg,dwSampleRate;
185 ECHOSTATUS Status;
187 ECHO_DEBUGPRINTF( ("C3gDco::SetInputClock:\n") );
190 // Mask off the clock select bits
192 dwControlReg = GetControlRegister();
193 dwControlReg &= E3G_CLOCK_CLEAR_MASK;
196 // New clock
198 switch (wClock)
200 case ECHO_CLOCK_INTERNAL :
201 ECHO_DEBUGPRINTF(("\tsetting internal clock\n"));
203 m_wInputClock = ECHO_CLOCK_INTERNAL; // prevent recursion
205 dwSampleRate = GetSampleRate();
206 if ((dwSampleRate < 32000) || (dwSampleRate > 100000))
207 dwSampleRate = 48000;
209 SetSampleRate(dwSampleRate);
210 return ECHOSTATUS_OK;
213 case ECHO_CLOCK_WORD:
214 dwControlReg |= E3G_WORD_CLOCK;
216 if ( E3G_CLOCK_DETECT_BIT_WORD96 & GetInputClockDetect() )
218 dwControlReg |= E3G_DOUBLE_SPEED_MODE;
220 else
222 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
224 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to WORD\n" ) );
225 break;
228 case ECHO_CLOCK_SPDIF :
229 if ( DIGITAL_MODE_ADAT == GetDigitalMode() )
231 return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
234 dwControlReg |= E3G_SPDIF_CLOCK;
235 if ( E3G_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() )
237 dwControlReg |= E3G_DOUBLE_SPEED_MODE;
239 else
241 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
244 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to SPDIF\n" ) );
245 break;
248 case ECHO_CLOCK_ADAT :
249 if ( DIGITAL_MODE_ADAT != GetDigitalMode() )
251 return ECHOSTATUS_CLOCK_NOT_AVAILABLE;
254 dwControlReg |= E3G_ADAT_CLOCK;
255 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
256 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to ADAT\n" ) );
257 break;
260 default :
261 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for 3G\n",wClock));
262 ECHO_DEBUGBREAK();
263 return ECHOSTATUS_CLOCK_NOT_SUPPORTED;
267 // Winner! Try to write the hardware
269 Status = WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE );
270 if (ECHOSTATUS_OK == Status)
271 m_wInputClock = wClock;
273 return Status;
275 } // ECHOSTATUS C3gDco::SetInputClock
279 //===========================================================================
281 // SetSampleRate
283 // Set the audio sample rate for 3G
285 //===========================================================================
287 DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate )
289 DWORD dwControlReg,dwNewClock,dwBaseRate,dwFreqReg;
291 ECHO_DEBUGPRINTF(("3G set sample rate to %ld\n",dwNewSampleRate));
294 // Only set the clock for internal mode. If the clock is not set to
295 // internal, try and re-set the input clock; this more transparently
296 // handles switching between single and double-speed mode
298 if ( GetInputClock() != ECHO_CLOCK_INTERNAL )
300 ECHO_DEBUGPRINTF( ( "C3gDco::SetSampleRate: Cannot set sample rate - "
301 "clock not set to ECHO_CLOCK_INTERNAL\n" ) );
304 // Save the rate anyhow
306 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
309 // Set the input clock to the current value
311 SetInputClock( m_wInputClock );
313 return dwNewSampleRate;
317 // Get the control register & clear the appropriate bits
319 dwControlReg = GetControlRegister();
320 dwControlReg &= E3G_CLOCK_CLEAR_MASK;
323 // Set the sample rate
325 switch ( dwNewSampleRate )
327 case 96000 :
328 dwNewClock = E3G_96KHZ;
329 break;
331 case 88200 :
332 dwNewClock = E3G_88KHZ;
333 break;
335 case 48000 :
336 dwNewClock = E3G_48KHZ;
337 break;
339 case 44100 :
340 dwNewClock = E3G_44KHZ;
341 break;
343 case 32000 :
344 dwNewClock = E3G_32KHZ;
345 break;
347 default :
348 dwNewClock = E3G_CONTINUOUS_CLOCK;
349 if (dwNewSampleRate > 50000)
350 dwNewClock |= E3G_DOUBLE_SPEED_MODE;
351 break;
354 dwControlReg |= dwNewClock;
355 SetSpdifBits(&dwControlReg,dwNewSampleRate);
357 ECHO_DEBUGPRINTF(("\tdwNewClock 0x%lx dwControlReg 0x%lx\n",dwNewClock,dwControlReg));
360 // Set up the frequency reg
362 dwBaseRate = dwNewSampleRate;
363 if (dwBaseRate > 50000)
364 dwBaseRate /= 2;
366 if (dwBaseRate < 32000)
367 dwBaseRate = 32000;
369 dwFreqReg = E3G_MAGIC_NUMBER / dwBaseRate - 2;
370 if (dwFreqReg > E3G_FREQ_REG_MAX)
371 dwFreqReg = E3G_FREQ_REG_MAX;
374 // Tell the DSP about it - DSP reads both control reg & freq reg
376 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg, dwFreqReg) )
378 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate );
380 ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: %ld clock %lx\n", dwNewSampleRate, dwControlReg) );
382 else
384 ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: could not set sample rate %ld\n", dwNewSampleRate) );
386 dwNewSampleRate = SWAP( m_pDspCommPage->dwSampleRate );
389 return dwNewSampleRate;
391 } // DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate )
395 //===========================================================================
397 // SetDigitalMode
399 //===========================================================================
401 ECHOSTATUS C3gDco::SetDigitalMode
403 BYTE byNewMode
406 DWORD dwControlReg;
407 WORD wInvalidClock;
410 // See if the current input clock doesn't match the new digital mode
412 switch (byNewMode)
414 case DIGITAL_MODE_SPDIF_RCA :
415 case DIGITAL_MODE_SPDIF_OPTICAL :
416 wInvalidClock = ECHO_CLOCK_ADAT;
417 break;
419 case DIGITAL_MODE_ADAT :
420 wInvalidClock = ECHO_CLOCK_SPDIF;
421 break;
423 default :
424 wInvalidClock = 0xffff;
425 break;
428 if (wInvalidClock == GetInputClock())
430 SetInputClock( ECHO_CLOCK_INTERNAL );
431 SetSampleRate( 48000 );
436 // Clear the current digital mode
438 dwControlReg = GetControlRegister();
439 dwControlReg &= E3G_DIGITAL_MODE_CLEAR_MASK;
442 // Tweak the control reg
444 switch ( byNewMode )
446 default :
447 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED;
449 case DIGITAL_MODE_SPDIF_OPTICAL :
450 dwControlReg |= E3G_SPDIF_OPTICAL_MODE;
451 // fall through
453 case DIGITAL_MODE_SPDIF_RCA :
454 break;
456 case DIGITAL_MODE_ADAT :
457 dwControlReg |= E3G_ADAT_MODE;
458 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE;
459 break;
463 // Write the control reg
465 WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE );
467 m_byDigitalMode = byNewMode;
469 ECHO_DEBUGPRINTF( ("C3gDco::SetDigitalMode to %ld\n",
470 (DWORD) m_byDigitalMode) );
472 return ECHOSTATUS_OK;
474 } // ECHOSTATUS C3gDco::SetDigitalMode
478 //===========================================================================
480 // WriteControlReg
482 //===========================================================================
484 ECHOSTATUS C3gDco::WriteControlReg
486 DWORD dwControlReg,
487 DWORD dwFreqReg,
488 BOOL fForceWrite
491 ECHOSTATUS Status;
493 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg 0x%lx 0x%lx\n",dwControlReg,dwFreqReg));
496 // New value OK?
498 Status = ValidateCtrlReg(dwControlReg);
499 if (ECHOSTATUS_OK != Status)
500 return Status;
503 // Ready to go?
505 if ( !m_bASICLoaded )
507 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - ASIC not loaded\n"));
508 return( ECHOSTATUS_ASIC_NOT_LOADED );
511 if ( !WaitForHandshake() )
513 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - no handshake\n"));
514 return ECHOSTATUS_DSP_DEAD;
518 // Write the control register
520 if ( fForceWrite ||
521 (dwControlReg != GetControlRegister()) ||
522 (dwFreqReg != Get3gFreqReg())
525 m_pDspCommPage->dw3gFreqReg = SWAP( dwFreqReg );
526 SetControlRegister( dwControlReg );
528 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: Setting 0x%lx, 0x%lx\n",
529 dwControlReg,dwFreqReg) );
531 ClearHandshake();
532 return SendVector( DSP_VC_WRITE_CONTROL_REG );
534 else
536 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: not written, no change\n") );
539 return ECHOSTATUS_OK;
541 } // ECHOSTATUS C3gDco::WriteControlReg
544 //===========================================================================
546 // SetSpdifBits
548 //===========================================================================
550 void C3gDco::SetSpdifBits(DWORD *pdwCtrlReg,DWORD dwSampleRate)
552 DWORD dwCtrlReg;
554 dwCtrlReg = *pdwCtrlReg;
557 // Clean out the old status bits
559 dwCtrlReg &= E3G_SPDIF_FORMAT_CLEAR_MASK;
562 // Sample rate
564 switch (dwSampleRate)
566 case 32000 :
567 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0 |
568 E3G_SPDIF_SAMPLE_RATE1;
569 break;
571 case 44100 :
572 if (m_bProfessionalSpdif)
573 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0;
574 break;
576 case 48000 :
577 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE1;
578 break;
582 // Professional mode?
584 if (m_bProfessionalSpdif)
585 dwCtrlReg |= E3G_SPDIF_PRO_MODE;
588 // Non-audio data?
590 if (m_bNonAudio)
591 dwCtrlReg |= E3G_SPDIF_NOT_AUDIO;
594 // Always stereo, 24 bit, copy permit
596 dwCtrlReg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | E3G_SPDIF_COPY_PERMIT;
598 *pdwCtrlReg = dwCtrlReg;
600 } // SetSpdifBits
603 //===========================================================================
605 // SetSpdifOutNonAudio
607 // Set the state of the non-audio status bit in the S/PDIF out status bits
609 //===========================================================================
611 void C3gDco::SetSpdifOutNonAudio(BOOL bNonAudio)
613 DWORD dwControlReg;
615 m_bNonAudio = bNonAudio;
617 dwControlReg = GetControlRegister();
618 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate ));
619 WriteControlReg( dwControlReg, Get3gFreqReg() );
623 //===========================================================================
625 // Set the S/PDIF output format
627 //===========================================================================
629 void C3gDco::SetProfessionalSpdif
631 BOOL bNewStatus
634 DWORD dwControlReg;
636 m_bProfessionalSpdif = bNewStatus;
638 dwControlReg = GetControlRegister();
639 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate ));
640 WriteControlReg( dwControlReg, Get3gFreqReg() );
642 } // void C3gDco::SetProfessionalSpdif( ... )
645 //===========================================================================
647 // ASIC status check
649 // 3G ASIC status check returns different values depending on what kind of box
650 // is hooked up
652 //===========================================================================
654 BOOL C3gDco::CheckAsicStatus()
656 DWORD dwBoxStatus,dwBoxType;
658 if ( !WaitForHandshake() )
660 ECHO_DEBUGPRINTF(("CheckAsicStatus - no handshake!\n"));
661 return FALSE;
665 // Send the vector command
667 m_pDspCommPage->dwExtBoxStatus = SWAP( (DWORD) E3G_ASIC_NOT_LOADED);
668 m_bASICLoaded = FALSE;
669 ClearHandshake();
670 SendVector( DSP_VC_TEST_ASIC );
673 // Wait for return from DSP
675 if ( !WaitForHandshake() )
677 ECHO_DEBUGPRINTF(("CheckAsicStatus - no handshake after VC\n"));
678 m_pwDspCode = NULL;
679 m_ullLastLoadAttemptTime = 0; // so LoadFirmware will try again right away
680 return FALSE;
684 // What box type was set?
686 dwBoxStatus = SWAP(m_pDspCommPage->dwExtBoxStatus);
687 if (E3G_ASIC_NOT_LOADED == dwBoxStatus)
689 ECHO_DEBUGPRINTF(("CheckAsicStatus - ASIC not loaded\n"));
690 dwBoxType = NO3GBOX;
692 else
694 dwBoxType = dwBoxStatus & E3G_BOX_TYPE_MASK;
695 m_bASICLoaded = TRUE;
696 ECHO_DEBUGPRINTF(("CheckAsicStatus - read box type %x\n",dwBoxType));
699 m_dwCurrentBoxType = dwBoxType;
702 // Has the box type already been set?
704 if (m_bBoxTypeSet)
707 // Did the ASIC load?
708 // Was the box type correct?
710 if ( (NO3GBOX == dwBoxType) ||
711 (dwBoxType != m_dwOriginalBoxType) )
713 ECHO_DEBUGPRINTF(("CheckAsicStatus - box type mismatch - original %x, got %x\n",m_dwOriginalBoxType,dwBoxType));
714 return FALSE;
717 ECHO_DEBUGPRINTF(("CheckAsicStatus - ASIC ok\n"));
718 m_bASICLoaded = TRUE;
719 return TRUE;
723 // First ASIC load - determine the box type and set up for that kind of box
725 m_dwOriginalBoxType = dwBoxType;
726 m_bBoxTypeSet = TRUE;
728 SetChannelCounts();
731 // Set the bad board flag if no external box
733 if (NO3GBOX == dwBoxType)
735 ECHO_DEBUGPRINTF(("CheckAsicStatus - no external box\n"));
736 m_bBadBoard = TRUE;
739 return m_bASICLoaded;
741 } // BOOL C3gDco::CheckAsicStatus()
744 //===========================================================================
746 // SetPhantomPower
748 //===========================================================================
750 void C3gDco::SetPhantomPower(BOOL fPhantom)
752 DWORD dwControlReg;
754 dwControlReg = GetControlRegister();
755 if (fPhantom)
757 dwControlReg |= E3G_PHANTOM_POWER;
759 else
761 dwControlReg &= ~E3G_PHANTOM_POWER;
764 WriteControlReg( dwControlReg, Get3gFreqReg() );
768 //===========================================================================
770 // Set channel counts for the current box type
772 //===========================================================================
774 void C3gDco::SetChannelCounts()
776 char *pszName;
777 WORD ch,i;
779 switch (m_dwOriginalBoxType)
781 case GINA3G :
782 m_wNumPipesOut = 14;
783 m_wNumPipesIn = 10;
784 m_wFirstDigitalBusOut = 6;
785 m_wFirstDigitalBusIn = 2;
787 pszName = "Gina3G";
788 break;
791 case NO3GBOX :
792 case LAYLA3G :
793 default :
794 m_wNumPipesOut = 16;
795 m_wNumPipesIn = 16;
796 m_wFirstDigitalBusOut = 8;
797 m_wFirstDigitalBusIn = 8;
799 pszName = "Layla3G";
800 break;
803 m_wNumBussesOut = m_wNumPipesOut;
804 m_wNumBussesIn = m_wNumPipesIn;
805 strcpy( m_szCardName, pszName);
808 // Build a channel mask for ADAT inputs & outputs 3-8
809 // OK to use bus # here since this hardware has no virtual outputs
811 m_Adat38Mask.Clear();
812 ch = m_wFirstDigitalBusOut + 2;
813 for (i = 0; i < 6; i++)
815 m_Adat38Mask.SetIndexInMask(ch);
816 ch++;
819 ch += m_wFirstDigitalBusIn + 2;
820 for (i = 0; i < 6; i++)
822 m_Adat38Mask.SetIndexInMask(ch);
823 ch++;
828 //===========================================================================
830 // Return the 3G box type
832 //===========================================================================
834 void C3gDco::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType)
836 if (NULL != pOriginalBoxType)
837 *pOriginalBoxType = m_dwOriginalBoxType;
839 if (NULL != pCurrentBoxType)
841 CheckAsicStatus();
843 *pCurrentBoxType = m_dwCurrentBoxType;
846 } // Get3gBoxType
850 //===========================================================================
852 // Fill out an ECHOGALS_METERS struct using the current values in the
853 // comm page. This method is overridden for vmixer cards.
855 //===========================================================================
857 ECHOSTATUS C3gDco::GetAudioMeters
859 PECHOGALS_METERS pMeters
862 pMeters->iNumPipesOut = 0;
863 pMeters->iNumPipesIn = 0;
866 // Output
868 DWORD dwCh = 0;
869 WORD i;
871 pMeters->iNumBussesOut = (INT32) m_wNumBussesOut;
872 for (i = 0; i < m_wNumBussesOut; i++)
874 pMeters->iBusOutVU[i] =
875 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) );
877 pMeters->iBusOutPeak[i] =
878 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) );
880 dwCh++;
883 pMeters->iNumBussesIn = (INT32) m_wNumBussesIn;
884 dwCh = E3G_MAX_OUTPUTS;
885 for (i = 0; i < m_wNumBussesIn; i++)
887 pMeters->iBusInVU[i] =
888 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->VUMeter[ dwCh ]) );
889 pMeters->iBusInPeak[i] =
890 DSP_TO_GENERIC( ((INT32) (INT8) m_pDspCommPage->PeakMeter[ dwCh ]) );
892 dwCh++;
895 return ECHOSTATUS_OK;
897 } // GetAudioMeters
901 //===========================================================================
903 // Utility function; returns TRUE if double speed mode is set
905 //===========================================================================
907 BOOL C3gDco::DoubleSpeedMode(DWORD *pdwNewCtrlReg)
909 DWORD dwControlReg;
911 if (NULL == pdwNewCtrlReg)
912 dwControlReg = GetControlRegister();
913 else
914 dwControlReg = *pdwNewCtrlReg;
916 if (0 != (dwControlReg & E3G_DOUBLE_SPEED_MODE))
917 return TRUE;
919 return FALSE;
923 //===========================================================================
925 // Utility function; validates a new control register value. Prevents
926 // speed change while transport is running
928 //===========================================================================
930 ECHOSTATUS C3gDco::ValidateCtrlReg(DWORD dwNewControlReg)
932 BOOL fCurrDoubleSpeed,fNewDoubleSpeed;
935 // Return OK if transport is off
937 if (m_cmActive.IsEmpty())
938 return ECHOSTATUS_OK;
941 // Get the new and current state of things
943 fNewDoubleSpeed = DoubleSpeedMode(&dwNewControlReg);
944 fCurrDoubleSpeed = DoubleSpeedMode(NULL);
947 // OK to change?
949 if (fCurrDoubleSpeed != fNewDoubleSpeed)
951 ECHO_DEBUGPRINTF(("Can't switch to speeds with transport active\n"));
952 return ECHOSTATUS_INVALID_CHANNEL;
955 return ECHOSTATUS_OK;
958 // **** C3gDco.cpp ****