root/trunk/libffado/src/rme/rme_avdevice.cpp

Revision 1671, 22.6 kB (checked in by jwoithe, 14 years ago)

RME: add some device-level support for stream configuration and control.
RME: make some comments clearer.
RME: remove some useless unreachable code.

Line 
1 /*
2  * Copyright (C) 2005-2009 by Jonathan Woithe
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #warning RME support is at an early development stage and is not functional
26
27 #include "config.h"
28
29 #include "rme/rme_avdevice.h"
30 #include "rme/fireface_def.h"
31 #include "rme/fireface_settings_ctrls.h"
32
33 #include "libieee1394/configrom.h"
34 #include "libieee1394/ieee1394service.h"
35
36 #include "debugmodule/debugmodule.h"
37
38 #include "devicemanager.h"
39
40 #include <string>
41 #include <stdint.h>
42 #include <assert.h>
43 #include "libutil/ByteSwap.h"
44
45 #include <iostream>
46 #include <sstream>
47
48 #include <libraw1394/csr.h>
49
50 // Known values for the unit version of RME devices
51 #define RME_UNITVERSION_FF800  0x0001
52 #define RME_UNITVERSION_FF400  0x0002
53
54 namespace Rme {
55
56 // The RME devices expect async packet data in little endian format (as
57 // opposed to bus order, which is big endian).  Therefore define our own
58 // 32-bit byteswap function to do this.
59 #if __BYTE_ORDER == __BIG_ENDIAN
60 static inline uint32_t
61 ByteSwapToDevice32(uint32_t d)
62 {
63     return byteswap_32(d);
64 }
65 ByteSwapFromDevice32(uint32_t d)
66 {
67     return byteswap_32(d);
68 }
69 #else
70 static inline uint32_t
71 ByteSwapToDevice32(uint32_t d)
72 {
73     return d;
74 }
75 static inline uint32_t
76 ByteSwapFromDevice32(uint32_t d)
77 {
78     return d;
79 }
80 #endif
81
82 Device::Device( DeviceManager& d,
83                       std::auto_ptr<ConfigRom>( configRom ))
84     : FFADODevice( d, configRom )
85     , m_rme_model( RME_MODEL_NONE )
86     , num_channels( 0 )
87     , frames_per_packet( 0 )
88     , speed800( 0 )
89     , iso_tx_channel( -1 )
90     , iso_rx_channel( -1 )
91     , m_MixerContainer( NULL )
92     , m_ControlContainer( NULL )
93 {
94     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Rme::Device (NodeID %d)\n",
95                  getConfigRom().getNodeId() );
96 }
97
98 Device::~Device()
99 {
100     if (iso_tx_channel>=0 && !get1394Service().freeIsoChannel(iso_tx_channel)) {
101         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free tx iso channel %d\n", iso_tx_channel);
102     }
103     if (iso_rx_channel>=0 && !get1394Service().freeIsoChannel(iso_rx_channel)) {
104         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free rx iso channel %d\n", iso_rx_channel);
105     }
106
107     destroyMixer();
108
109     if (dev_config != NULL) {
110         switch (rme_shm_close(dev_config)) {
111             case RSO_CLOSE:
112                 debugOutput( DEBUG_LEVEL_VERBOSE, "Configuration shared data object closed\n");
113                 break;
114             case RSO_CLOSE_DELETE:
115                 debugOutput( DEBUG_LEVEL_VERBOSE, "Configuration shared data object closed and deleted (no other users)\n");
116                 break;
117         }
118     }
119 }
120
121 bool
122 Device::buildMixer() {
123     signed int i;
124     bool result = true;
125
126     destroyMixer();
127     debugOutput(DEBUG_LEVEL_VERBOSE, "Building an RME mixer...\n");
128
129
130     // Non-mixer device controls
131     m_ControlContainer = new Control::Container(this, "Control");
132     if (!m_ControlContainer) {
133         debugError("Could not create control container\n");
134         destroyMixer();
135         return false;
136     }
137
138     result &= m_ControlContainer->addElement(
139         new RmeSettingsCtrl(*this, RME_CTRL_INFO_MODEL, 0,
140             "Model", "Model ID", ""));
141     result &= m_ControlContainer->addElement(
142         new RmeSettingsCtrl(*this, RME_CTRL_INFO_TCO_PRESENT, 0,
143             "TCO_present", "TCO is present", ""));
144
145     result &= m_ControlContainer->addElement(
146         new RmeSettingsCtrl(*this, RME_CTRL_PHANTOM_SW, 0,
147             "Phantom", "Phantom switches", ""));
148     result &= m_ControlContainer->addElement(
149         new RmeSettingsCtrl(*this, RME_CTRL_INPUT_LEVEL, 0,
150             "Input_level", "Input level", ""));
151     result &= m_ControlContainer->addElement(
152         new RmeSettingsCtrl(*this, RME_CTRL_OUTPUT_LEVEL, 0,
153             "Output_level", "Output level", ""));
154     result &= m_ControlContainer->addElement(
155         new RmeSettingsCtrl(*this, RME_CTRL_PHONES_LEVEL, 0,
156             "Phones_level", "Phones level", ""));
157
158     if (m_rme_model == RME_MODEL_FIREFACE400) {
159         // Instrument input options
160         for (i=3; i<=4; i++) {
161             char path[32], desc[64];
162             snprintf(path, sizeof(path), "Chan%d_opt_instr", i);
163             snprintf(desc, sizeof(desc), "Chan%d instrument option", i);
164             result &= m_ControlContainer->addElement(
165                 new RmeSettingsCtrl(*this, RME_CTRL_FF400_INSTR_SW, i,
166                     path, desc, ""));
167             snprintf(path, sizeof(path), "Chan%d_opt_pad", i);
168             snprintf(desc, sizeof(desc), "Chan%d pad option", i);
169             result &= m_ControlContainer->addElement(
170                 new RmeSettingsCtrl(*this, RME_CTRL_FF400_PAD_SW, i,
171                     path, desc, ""));
172         }
173
174         // Input/output gains
175         result &= m_ControlContainer->addElement(
176             new RmeSettingsMatrixCtrl(*this, RME_MATRIXCTRL_GAINS, "Gains"));
177     }
178
179     if (!result) {
180         debugWarning("One or more device control elements could not be created\n");
181         destroyMixer();
182         return false;
183     }
184
185     if (!addElement(m_ControlContainer)) {
186         debugWarning("Could not register mixer to device\n");
187         // clean up
188         destroyMixer();
189         return false;
190     }
191
192     return true;
193 }
194
195 bool
196 Device::destroyMixer() {
197     bool ret = true;
198     debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
199
200     if (m_MixerContainer == NULL) {
201         debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
202     } else
203     if (!deleteElement(m_MixerContainer)) {
204         debugError("Mixer present but not registered to the avdevice\n");
205         ret = false;
206     } else {
207         // remove and delete (as in free) child control elements
208         m_MixerContainer->clearElements(true);
209         delete m_MixerContainer;
210         m_MixerContainer = NULL;
211     }
212
213     // remove control container
214     if (m_ControlContainer == NULL) {
215         debugOutput(DEBUG_LEVEL_VERBOSE, "no controls to destroy...\n");
216     } else
217     if (!deleteElement(m_ControlContainer)) {
218         debugError("Controls present but not registered to the avdevice\n");
219         ret = false;
220     } else {
221         // remove and delete (as in free) child control elements
222         m_ControlContainer->clearElements(true);
223         delete m_ControlContainer;
224         m_ControlContainer = NULL;
225     }
226
227     return false;
228 }
229
230 bool
231 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
232 {
233     if (generic) {
234         return false;
235     } else {
236         // check if device is in supported devices list.  Note that the RME
237         // devices use the unit version to identify the individual devices.
238         // To avoid having to extend the configuration file syntax to
239         // include this at this point, we'll use the configuration file
240         // model ID to test against the device unit version.  This can be
241         // tidied up if the configuration file is extended at some point to
242         // include the unit version.
243         unsigned int vendorId = configRom.getNodeVendorId();
244         unsigned int unitVersion = configRom.getUnitVersion();
245
246         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, unitVersion );
247         return c.isValid(vme) && vme.driver == Util::Configuration::eD_RME;
248     }
249 }
250
251 FFADODevice *
252 Device::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
253 {
254     return new Device(d, configRom );
255 }
256
257 bool
258 Device::discover()
259 {
260     signed int i;
261     unsigned int vendorId = getConfigRom().getNodeVendorId();
262     // See note in Device::probe() about why we use the unit version here.
263     unsigned int unitVersion = getConfigRom().getUnitVersion();
264
265     Util::Configuration &c = getDeviceManager().getConfiguration();
266     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, unitVersion );
267
268     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_RME) {
269         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
270                      vme.vendor_name.c_str(),
271                      vme.model_name.c_str());
272     } else {
273         debugWarning("Device '%s %s' unsupported by RME driver (no generic RME support)\n",
274                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
275     }
276
277     if (unitVersion == RME_UNITVERSION_FF800) {
278         m_rme_model = RME_MODEL_FIREFACE800;
279     } else
280     if (unitVersion == RME_MODEL_FIREFACE400) {
281         m_rme_model = RME_MODEL_FIREFACE400;
282     } else {
283         debugError("Unsupported model\n");
284         return false;
285     }
286
287     // Set up the shared data object for configuration data
288     i = rme_shm_open(&dev_config);
289     if (i == RSO_OPEN_CREATED) {
290         debugOutput( DEBUG_LEVEL_VERBOSE, "New configuration shared data object created\n");
291     } else
292     if (i == RSO_OPEN_ATTACHED) {
293         debugOutput( DEBUG_LEVEL_VERBOSE, "Attached to existing configuration shared data object\n");
294     }
295     if (dev_config == NULL) {
296         debugOutput( DEBUG_LEVEL_WARNING, "Could not create/access shared configuration memory object, using process-local storage\n");
297         memset(&local_dev_config_obj, 0, sizeof(local_dev_config_obj));
298         dev_config = &local_dev_config_obj;
299     }
300     settings = &dev_config->settings;
301     tco_settings = &dev_config->tco_settings;
302
303     // If device is FF800, check to see if the TCO is fitted
304     if (m_rme_model == RME_MODEL_FIREFACE800) {
305         dev_config->tco_present = (read_tco(NULL, 0) == 0);
306     }
307     debugOutput(DEBUG_LEVEL_VERBOSE, "TCO present: %s\n",
308       dev_config->tco_present?"yes":"no");
309
310     init_hardware();
311
312     if (!buildMixer()) {
313         debugWarning("Could not build mixer\n");
314     }
315
316     // This is just for testing
317     read_device_flash_settings(NULL);
318
319     return true;
320 }
321
322 int
323 Device::getSamplingFrequency( ) {
324
325     // Retrieve the current sample rate.  For practical purposes this
326     // is the software rate currently in use.
327     return dev_config->software_freq;
328 }
329
330 int
331 Device::getConfigurationId()
332 {
333     return 0;
334 }
335
336 bool
337 Device::setDDSFrequency( int dds_freq )
338 {
339     // Set a fixed DDS frequency.  If the device is the clock master this
340     // will immediately be copied to the hardware DDS register.  Otherwise
341     // it will take effect as required at the time the sampling rate is
342     // changed or streaming is started.
343
344     // If the device is streaming, the new DDS rate must have the same
345     // multiplier as the software sample rate
346     if (hardware_is_streaming()) {
347         if (multiplier_of_freq(dds_freq) != multiplier_of_freq(dev_config->software_freq))
348             return false;
349     }
350
351     dev_config->dds_freq = dds_freq;
352     if (settings->clock_mode == FF_STATE_CLOCKMODE_MASTER) {
353         if (set_hardware_dds_freq(dds_freq) != 0)
354             return false;
355     }
356
357     return true;
358 }
359
360 bool
361 Device::setSamplingFrequency( int samplingFrequency )
362 {
363     // Request a sampling rate on behalf of software.  Software is limited
364     // to sample rates of 32k, 44.1k, 48k and the 2x/4x multiples of these.
365     // The user may lock the device to a much wider range of frequencies via
366     // the explicit DDS controls in the control panel.  If the explicit DDS
367     // control is active the software is limited to the "standard" speeds
368     // corresponding to the multiplier in use by the DDS.
369     //
370     // Similarly, if the device is externally clocked the software is
371     // limited to the external clock frequency.
372     //
373     // Otherwise the software has free choice of the software speeds noted
374     // above.
375
376     bool ret = -1;
377     signed int i, j;
378     signed int mult[3] = {1, 2, 4};
379     signed int base_freq[3] = {32000, 44100, 48000};
380     signed int freq = samplingFrequency;
381     FF_state_t state;
382     signed int fixed_freq = 0;
383
384     get_hardware_state(&state);
385
386     // If device is locked to a frequency via external clock, explicit
387     // setting of the DDS or by virtue of streaming being active, get that
388     // frequency.
389     if (state.clock_mode == FF_STATE_CLOCKMODE_AUTOSYNC) {
390         // FIXME: if synced to TCO, is autosync_freq valid?
391         fixed_freq = state.autosync_freq;
392     } else
393     if (dev_config->dds_freq > 0) {
394         fixed_freq = dev_config->dds_freq;
395     } else
396     if (hardware_is_streaming()) {
397         fixed_freq = dev_config->software_freq;
398     }
399
400     // If the device is running to a fixed frequency, software can only
401     // request frequencies with the same multiplier.  Similarly, the
402     // multiplier is locked in "master" clock mode if the device is
403     // streaming.
404     if (fixed_freq > 0) {
405         signed int fixed_mult = multiplier_of_freq(fixed_freq);
406         if (multiplier_of_freq(freq) != multiplier_of_freq(fixed_freq))
407             return -1;
408         for (j=0; j<3; j++) {
409             if (freq == base_freq[j]*fixed_mult) {
410                 ret = 0;
411                 break;
412             }
413         }
414     } else {
415         for (i=0; i<3; i++) {
416             for (j=0; j<3; j++) {
417                 if (freq == base_freq[j]*mult[i]) {
418                     ret = 0;
419                     break;
420                 }
421             }
422         }
423     }
424     // If requested frequency is unavailable, return -1
425     if (ret == -1)
426         return false;
427
428     // If a DDS frequency has been explicitly requested this is always
429     // used to programm the hardware DDS regardless of the rate requested
430     // by the software.  Otherwise we use the requested sampling rate.
431     if (dev_config->dds_freq > 0)
432         freq = dev_config->dds_freq;
433     if (set_hardware_dds_freq(freq) != 0)
434         return false;
435
436     dev_config->software_freq = samplingFrequency;
437     return true;
438 }
439
440 std::vector<int>
441 Device::getSupportedSamplingFrequencies()
442 {
443     std::vector<int> frequencies;
444     signed int i, j;
445     signed int mult[3] = {1, 2, 4};
446     signed int freq[3] = {32000, 44100, 48000};
447     FF_state_t state;
448
449     get_hardware_state(&state);
450
451     // Generate the list of supported frequencies.  If the device is
452     // externally clocked the frequency is limited to the external clock
453     // frequency.  If the device is running the multiplier is fixed.
454     if (state.clock_mode == FF_STATE_CLOCKMODE_AUTOSYNC) {
455         // FIXME: if synced to TCO, is autosync_freq valid?
456         frequencies.push_back(state.autosync_freq);
457     } else
458     if (state.is_streaming) {
459         unsigned int fixed_mult = multiplier_of_freq(dev_config->software_freq);
460         for (j=0; j<3; j++) {
461             frequencies.push_back(freq[j]*fixed_mult);
462         }
463     } else {
464         for (i=0; i<3; i++) {
465             for (j=0; j<3; j++) {
466                 frequencies.push_back(freq[j]*mult[i]);
467             }
468         }
469     }
470     return frequencies;
471 }
472
473 FFADODevice::ClockSourceVector
474 Device::getSupportedClockSources() {
475     FFADODevice::ClockSourceVector r;
476     return r;
477 }
478
479 bool
480 Device::setActiveClockSource(ClockSource s) {
481     return false;
482 }
483
484 FFADODevice::ClockSource
485 Device::getActiveClockSource() {
486     ClockSource s;
487     return s;
488 }
489
490 bool
491 Device::lock() {
492
493     return true;
494 }
495
496
497 bool
498 Device::unlock() {
499
500     return true;
501 }
502
503 void
504 Device::showDevice()
505 {
506     unsigned int vendorId = getConfigRom().getNodeVendorId();
507     unsigned int modelId = getConfigRom().getModelId();
508
509     Util::Configuration &c = getDeviceManager().getConfiguration();
510     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
511
512     debugOutput(DEBUG_LEVEL_VERBOSE,
513         "%s %s at node %d\n", vme.vendor_name.c_str(), vme.model_name.c_str(), getNodeId());
514 }
515
516 bool
517 Device::prepare() {
518
519     signed int mult, bandwidth;
520     signed int freq;
521     signed int err = 0;
522
523     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing Device...\n" );
524
525     freq = getSamplingFrequency();
526     if (freq <= 0) {
527         debugOutput(DEBUG_LEVEL_ERROR, "Can't continue: sampling frequency not set\n");
528         return false;
529     }
530
531     // The number of frames transmitted in a single packet is solely
532     // determined by the sample rate.
533     mult = multiplier_of_freq(getSamplingFrequency());
534     switch (mult) {
535         case 2: frames_per_packet = 15; break;
536         case 4: frames_per_packet = 25; break;
537     default:
538         frames_per_packet = 7;
539     }
540
541     // The number of active channels depends on sample rate and whether
542     // bandwidth limitation is active.  First set up the number of analog
543     // channels (which differs between devices), then add SPDIF channels if
544     // relevant.  Finally, the number of channels available from each ADAT
545     // interface depends on sample rate: 0 at 4x, 4 at 2x and 8 at 1x.
546     if (m_rme_model == RME_MODEL_FIREFACE800)
547         num_channels = 10;
548     else
549         num_channels = 8;
550     if (settings->limit_bandwidth != FF_SWPARAM_BWLIMIT_ANALOG_ONLY)
551         num_channels += 2;
552     if (settings->limit_bandwidth==FF_SWPARAM_BWLIMIT_NO_ADAT2 ||
553         settings->limit_bandwidth==FF_SWPARAM_BWLIMIT_SEND_ALL_CHANNELS)
554         num_channels += (mult==4?0:(mult==2?4:8));
555     if (settings->limit_bandwidth==FF_SWPARAM_BWLIMIT_SEND_ALL_CHANNELS)
556         num_channels += (mult==4?0:(mult==2?4:8));
557
558     // Bandwidth is calculated here.  For the moment we assume the device
559     // is connected at S400, so 1 allocation unit is 1 transmitted byte.
560     // There is 25 allocation units of protocol overhead per packet.  Each
561     // channel of audio data is sent/received as a 32 bit integer.
562     bandwidth = 25 + num_channels*4*frames_per_packet;
563
564     // Both the FF400 and FF800 require we allocate a tx iso channel.  The
565     // rx channel is also allocated for the FF400.  The FF800 chooses
566     // the rx channel to be used but does not handle the bus-level
567     // channel/bandwidth allocation/
568     if (iso_tx_channel < 0) {
569         iso_tx_channel = get1394Service().allocateIsoChannelGeneric(bandwidth);
570     }
571
572     if (iso_rx_channel < 0) {
573         if (m_rme_model == RME_MODEL_FIREFACE800) {
574             unsigned int stat[4];
575             get_hardware_streaming_status(stat, 4);
576             // CHECKME: does this work before streaming has been initialised?
577             iso_rx_channel = stat[2] & 63;
578             iso_rx_channel = get1394Service().allocateFixedIsoChannelGeneric(iso_rx_channel, bandwidth);
579         } else {
580             iso_rx_channel = get1394Service().allocateIsoChannelGeneric(bandwidth);
581         }
582     }
583  
584     if (iso_tx_channel>=0 && iso_rx_channel>=0) {
585         err = hardware_init_streaming(dev_config->hardware_freq, iso_tx_channel) != 0;
586         if (err) {
587             debugFatal("Could not intialise device streaming system\n");
588         }
589     } else {
590         err = 1;
591         debugFatal("Could not allocate iso channels\n");
592     }
593
594     if (err) {
595         if (iso_tx_channel >= 0)
596             get1394Service().freeIsoChannel(iso_tx_channel);
597         if (iso_rx_channel >= 0)
598             get1394Service().freeIsoChannel(iso_rx_channel);
599         return false;
600     }
601
602     // get the device specific and/or global SP configuration
603     Util::Configuration &config = getDeviceManager().getConfiguration();
604     // base value is the config.h value
605     float recv_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
606     float xmit_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
607
608     // we can override that globally
609     config.getValueForSetting("streaming.spm.recv_sp_dll_bw", recv_sp_dll_bw);
610     config.getValueForSetting("streaming.spm.xmit_sp_dll_bw", xmit_sp_dll_bw);
611
612     // or override in the device section
613     config.getValueForDeviceSetting(getConfigRom().getNodeVendorId(), getConfigRom().getModelId(), "recv_sp_dll_bw", recv_sp_dll_bw);
614     config.getValueForDeviceSetting(getConfigRom().getNodeVendorId(), getConfigRom().getModelId(), "xmit_sp_dll_bw", xmit_sp_dll_bw);
615
616     // Other things to be done:
617     //  * create a receive stream processor, set DLL bandwidth, add ports
618     //  * create a transmit stream processor, set DLL bandwidth, add ports
619
620     return true;
621 }
622
623 int
624 Device::getStreamCount() {
625         return 0; // one receive, one transmit
626 }
627
628 Streaming::StreamProcessor *
629 Device::getStreamProcessorByIndex(int i) {
630     return NULL;
631 }
632
633 bool
634 Device::startStreamByIndex(int i) {
635     // The RME does not allow separate enabling of the transmit and receive
636     // streams.  Therefore we start all streaming when index 0 is referenced
637     // and silently ignore the start requests for other streams
638     // (unconditionally flagging them as being successful).
639     if (i == 0) {
640         if (hardware_start_streaming(iso_rx_channel) != 0)
641             return false;
642     }
643     return true;
644 }
645
646 bool
647 Device::stopStreamByIndex(int i) {
648     // See comments in startStreamByIndex() as to why we act only when stream
649     // 0 is requested.
650     if (i == 0) {
651         if (hardware_stop_streaming() != 0)
652             return false;
653     }
654     return true;
655 }
656
657 unsigned int
658 Device::readRegister(fb_nodeaddr_t reg) {
659
660     quadlet_t quadlet;
661    
662     quadlet = 0;
663     if (get1394Service().read(0xffc0 | getNodeId(), reg, 1, &quadlet) <= 0) {
664         debugError("Error doing RME read from register 0x%06x\n",reg);
665     }
666     return ByteSwapFromDevice32(quadlet);
667 }
668
669 signed int
670 Device::readBlock(fb_nodeaddr_t reg, quadlet_t *buf, unsigned int n_quads) {
671
672     unsigned int i;
673
674     if (get1394Service().read(0xffc0 | getNodeId(), reg, n_quads, buf) <= 0) {
675         debugError("Error doing RME block read of %d quadlets from register 0x%06x\n",
676             n_quads, reg);
677         return -1;
678     }
679     for (i=0; i<n_quads; i++) {
680        buf[i] = ByteSwapFromDevice32(buf[i]);
681     }
682
683     return 0;
684 }
685
686 signed int
687 Device::writeRegister(fb_nodeaddr_t reg, quadlet_t data) {
688
689     unsigned int err = 0;
690     data = ByteSwapToDevice32(data);
691     if (get1394Service().write(0xffc0 | getNodeId(), reg, 1, &data) <= 0) {
692         err = 1;
693         debugError("Error doing RME write to register 0x%06x\n",reg);
694     }
695     return (err==0)?0:-1;
696 }
697
698 signed int
699 Device::writeBlock(fb_nodeaddr_t reg, quadlet_t *data, unsigned int n_quads) {
700 //
701 // Write a block of data to the device starting at address "reg".  Note that
702 // the conditional byteswap is done "in place" on data, so the contents of
703 // data may be modified by calling this function.
704 //
705     unsigned int err = 0;
706     unsigned int i;
707
708     for (i=0; i<n_quads; i++) {
709       data[i] = ByteSwapToDevice32(data[i]);
710     }
711     if (get1394Service().write(0xffc0 | getNodeId(), reg, n_quads, data) <= 0) {
712         err = 1;
713         debugError("Error doing RME block write of %d quadlets to register 0x%06x\n",
714           n_quads, reg);
715     }
716     return (err==0)?0:-1;
717 }
718                  
719 }
Note: See TracBrowser for help on using the browser.