1394util.c
Upload User: shyika
Upload Date: 2017-11-25
Package Size: 1227k
Code Size: 13k
Category:

Video Capture

Development Platform:

Unix_Linux

  1. /*
  2.     unicap
  3.     Copyright (C) 2004  Arne Caspari
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.
  12.     You should have received a copy of the GNU General Public License
  13.     along with this program; if not, write to the Free Software
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15. */
  16. #include <config.h>
  17. #include <netinet/in.h> // for ntohl
  18. #include <errno.h>
  19. #ifdef RAW1394_1_1_API
  20. #include <libraw1394/raw1394.h>
  21. #include <libraw1394/csr.h>
  22. #endif
  23. #ifdef RAW1394_1_0_API
  24. #include <raw1394.h>
  25. #include <csr.h>
  26. #endif
  27. #include <unistd.h>
  28. #include <stdio.h>
  29. #include <errno.h>
  30. #include "1394util.h"
  31. #include <unicap_status.h>
  32. #if DCAM_DEBUG
  33. #define DEBUG
  34. #endif
  35. #include <debug.h>
  36. #define MAXTRIES 20
  37. #define DELAY 1000000
  38. #define EXTCODE_COMPARE_SWAP     0x2
  39. #define MAX_BANDWIDTH            0x1333 // Check this! Should be 0x1000 ???
  40. int cooked1394_read( raw1394handle_t handle, 
  41.      nodeid_t node, 
  42.      nodeaddr_t addr,
  43.      size_t length, 
  44.      quadlet_t *buffer ) 
  45. {
  46. int retval, i;
  47. for( i=0; i < MAXTRIES; i++ ) 
  48. {
  49. retval = raw1394_read( handle, node, addr, length, buffer );
  50. if( retval >= 0 )
  51. {
  52.    return retval; /* Everything is OK */
  53. }
  54. if( errno != EAGAIN )
  55. {
  56.    break;
  57. }
  58. /*  usleep(DELAY); */
  59. }
  60. #ifdef DEBUG
  61. perror("Error while reading from IEEE1394: ");
  62. #endif
  63. return retval;
  64. }
  65. int cooked1394_write( raw1394handle_t handle, 
  66.       nodeid_t node, 
  67.       nodeaddr_t addr,
  68.       size_t length, 
  69.       quadlet_t *data) 
  70. {
  71. int retval, i;
  72. for( i=0; i < MAXTRIES; i++ ) 
  73. {
  74. /*  usleep( DELAY ); */
  75. sleep( 1 );
  76. retval = raw1394_write( handle, node, addr, length, data );
  77. if( retval >= 0 )
  78. {
  79.    return retval; /* Everything is OK */
  80. }
  81. if( errno != EAGAIN ){ 
  82.    break;
  83. }
  84. }
  85. #ifdef DEBUG
  86. perror( "Error while writing to IEEE1394: " );
  87. #endif
  88. return retval;
  89. }
  90. /*
  91.  * Obtain the global unique identifier of a node from its configuration ROM.
  92.  * The GUID can also be read from a filled out Rom_info structure, but this
  93.  * method is of course faster than reading the whole configuration ROM and can
  94.  * for instance be used to obtain a hash key for caching Rom_info structures
  95.  * in memory.
  96.  * IN:  phyID: Physical ID of the node to read from
  97.  *      hi: Pointer to an integer which should receive the HI quadlet
  98.  *      hi: Pointer to an integer which should receive the LOW quadlet
  99.  */
  100. unsigned long long get_guid(raw1394handle_t handle, int phyID ) 
  101. {
  102. unsigned int hiquad;
  103. unsigned int loquad;
  104. unsigned long long guid = 0;
  105. if ( cooked1394_read( handle, 
  106.       0xffC0 | phyID, 
  107.       CSR_REGISTER_BASE + CSR_CONFIG_ROM + 0x0C, 
  108.       4, 
  109.       &hiquad ) < 0 ) 
  110. return 0; 
  111. }
  112. if ( cooked1394_read( handle, 
  113.       0xffC0 | phyID, 
  114.       CSR_REGISTER_BASE + CSR_CONFIG_ROM + 0x10, 
  115.       4, 
  116.       &loquad ) < 0 ) 
  117. return 0; 
  118. }
  119. hiquad = ntohl( hiquad );
  120. loquad = ntohl( loquad );
  121. guid = ( ( unsigned long long ) hiquad ) << 32;
  122. guid += loquad;
  123. return guid;
  124. }
  125. unsigned int get_unit_spec_ID( raw1394handle_t handle, int phyID )
  126. {
  127. unsigned int unit_dir_offset;
  128. unsigned int spec_ID;
  129. if( cooked1394_read( handle, 
  130.      0xffc0 | phyID, 
  131.      CSR_REGISTER_BASE + CSR_CONFIG_ROM + 0x24, 
  132.      4, 
  133.      &unit_dir_offset ) < 0 )
  134. {
  135. TRACE( "failed to read unit_dir _offsetn" );
  136. return 0;
  137. }
  138. unit_dir_offset = ntohl( unit_dir_offset );
  139. unit_dir_offset &= 0x00ffffff;
  140. TRACE( "unit_dir_offset: %xn", unit_dir_offset );
  141. if( cooked1394_read( handle, 
  142.      0xffc0 | phyID, 
  143.      CSR_REGISTER_BASE + CSR_CONFIG_ROM + 0x24 + unit_dir_offset + 0x8, 
  144.      4, 
  145.      &spec_ID ) < 0 )
  146. {
  147. return 0;
  148. }
  149. spec_ID = ntohl( spec_ID );
  150. spec_ID &= 0x00ffffff;
  151. return spec_ID;
  152. }
  153. unsigned int get_unit_sw_version( raw1394handle_t handle, int phyID )
  154. {
  155. unsigned int unit_dir_offset;
  156. unsigned int sw_version;
  157. if( cooked1394_read( handle, 
  158.      0xffc0 | phyID, 
  159.      CSR_REGISTER_BASE + CSR_CONFIG_ROM + 0x24, 
  160.      4, 
  161.      &unit_dir_offset ) < 0 )
  162. {
  163. TRACE( "failed to read unit_dir _offsetn" );
  164. return 0;
  165. }
  166. unit_dir_offset = ntohl( unit_dir_offset );
  167. unit_dir_offset &= 0x00ffffff;
  168. TRACE( "unit_dir_offset: %xn", unit_dir_offset );
  169. if( cooked1394_read( handle, 
  170.      0xffc0 | phyID, 
  171.      CSR_REGISTER_BASE + CSR_CONFIG_ROM + 0x24 + unit_dir_offset + 0xc, 
  172.      4, 
  173.      &sw_version ) < 0 )
  174. {
  175. return 0;
  176. }
  177. sw_version = ntohl( sw_version );
  178. sw_version &= 0x00ffffff;
  179. return sw_version;
  180. }
  181. /*
  182.   allocate the first free channel for isochronous transmission using compare & swap
  183.   
  184.   returns: < 0 if channel could not be allocated
  185.            or the allocated channel
  186.  */
  187. int _1394util_find_free_channel( raw1394handle_t raw1394handle )
  188. {
  189. quadlet_t buffer;
  190. int channel = -1;
  191. if( 0 > cooked1394_read( raw1394handle, 
  192.  raw1394_get_irm_id( raw1394handle ), 
  193.  CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, 
  194.  sizeof( quadlet_t ), 
  195.  &buffer ) )
  196. {
  197. TRACE( "Failed to get CSR_CHANNELS_AVAILABLE_LOn" );
  198. return -1;
  199. }
  200. buffer = ntohl( buffer );
  201. for( channel = 0; ( !( buffer & ( 1 << channel ) ) ) && channel < 32; channel++ )
  202. {
  203. }
  204. if( channel > 31 ) // none found in the lower range
  205. {
  206. if( 0 > cooked1394_read( raw1394handle, 
  207.  raw1394_get_irm_id( raw1394handle ), 
  208.  CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 
  209.  sizeof( quadlet_t ), 
  210.  &buffer ) )
  211. {
  212. TRACE( "Failed to get CSR_CHANNELS_AVAILABLE_HIn" );
  213. return -1;
  214. }
  215. buffer = ntohl( buffer );
  216. for( channel = 0; ( !( buffer & ( 1<<channel ) ) ) && ( channel < 32 ); channel++ )
  217. {
  218. }
  219. channel+=32;
  220. }//if( channel > 31
  221. if( channel > 63 )
  222. {
  223. TRACE( "No free channel foundn" );
  224. return -1;
  225. }
  226. else
  227. {
  228. quadlet_t data, arg, result;
  229. arg   = htonl( buffer );
  230. data  = htonl( buffer & ~( 1<<channel ) );
  231. if( 0 > raw1394_lock( raw1394handle, 
  232.       raw1394_get_irm_id( raw1394handle ), 
  233.       channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 
  234.       EXTCODE_COMPARE_SWAP, 
  235.       data, 
  236.       arg, 
  237.       &result ) )
  238. {
  239. TRACE( "Channel allocation failedn" );
  240. return -1;
  241. }
  242. // is the following thread safe? I do not think so!
  243. if( 0 > cooked1394_read( raw1394handle, raw1394_get_irm_id( raw1394handle ), 
  244.  channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 
  245.  sizeof( quadlet_t ), 
  246.  &buffer ) )
  247. {
  248. TRACE( "Failed to read back available channelsn" );
  249. return -1;
  250. }
  251. if( buffer != data )
  252. {
  253. TRACE( "Validation of channel failedn" );
  254. return -1;
  255. }
  256. }
  257. return channel;
  258. }
  259. /*
  260.   free a channel
  261.  */
  262. unicap_status_t _1394util_free_channel( raw1394handle_t raw1394handle, int channel )
  263. {
  264. quadlet_t buffer;
  265. if( 0 <= cooked1394_read( raw1394handle, raw1394_get_irm_id( raw1394handle ),
  266.   channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
  267.   sizeof( quadlet_t ),
  268.   &buffer ) )
  269. {
  270. int channel_bit = channel > 31 ? channel - 32 : channel;
  271. quadlet_t data, arg, result;
  272. buffer = htonl( buffer );
  273. if( buffer & ( 1<<channel_bit ) )
  274. { // channel already marked as free
  275. TRACE( "Trying to free an unallocated channeln" );
  276. TRACE( "channels: %xn", buffer );
  277. return STATUS_CHANNEL_ALREADY_FREE;
  278. }
  279. arg   = htonl( buffer );
  280. data  = htonl( buffer | ( 1<<channel_bit ) );
  281. if( 0 > raw1394_lock( raw1394handle, 
  282.       raw1394_get_irm_id( raw1394handle ), 
  283.       channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 
  284.       EXTCODE_COMPARE_SWAP, 
  285.       data, 
  286.       arg, 
  287.       &result ) )
  288. {
  289. TRACE( "Failed to free channeln" );
  290. return STATUS_FAILURE;
  291. }
  292. if( arg != htonl( buffer ) )
  293. {
  294. TRACE( "Free channel validation failedn" );
  295. return STATUS_FAILURE;
  296. }
  297. return STATUS_SUCCESS;
  298. }
  299. TRACE( "Read failedn" );
  300. return STATUS_FAILURE;
  301. }
  302. /*
  303.   try to allocate channel on the bus
  304.   returns: status
  305.  */
  306. unicap_status_t _1394util_allocate_channel( raw1394handle_t raw1394handle, int channel )
  307. {
  308. quadlet_t buffer;
  309. if( 0 > cooked1394_read( raw1394handle, 
  310.  raw1394_get_irm_id( raw1394handle ), 
  311.  CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, 
  312.  sizeof( quadlet_t ), 
  313.  &buffer ) )
  314. {
  315. TRACE( "Failed to get CSR_CHANNELS_AVAILABLE_LOn" );
  316. return STATUS_FAILURE;
  317. }
  318. buffer = ntohl( buffer );
  319. if( channel > 31 ) // none found in the lower range
  320. {
  321. if( 0 > cooked1394_read( raw1394handle, 
  322.  raw1394_get_irm_id( raw1394handle ), 
  323.  CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 
  324.  sizeof( quadlet_t ), 
  325.  &buffer ) )
  326. {
  327. TRACE( "Failed to get CSR_CHANNELS_AVAILABLE_HIn" );
  328. return -1;
  329. }
  330. buffer = ntohl( buffer );
  331. }//if( channel > 31
  332. if( channel > 63 )
  333. {
  334. TRACE( "Channel number too highn" );
  335. return STATUS_INVALID_PARAMETER;
  336. }
  337. else
  338. {
  339. quadlet_t data, arg, result;
  340. arg   = htonl( buffer );
  341. data  = htonl( buffer & ~( 1<<channel ) );
  342. if( 0 > raw1394_lock( raw1394handle, 
  343.       raw1394_get_irm_id( raw1394handle ), 
  344.       channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, 
  345.       EXTCODE_COMPARE_SWAP, 
  346.       data, 
  347.       arg, 
  348.       &result ) )
  349. {
  350. TRACE( "Channel allocation failedn" );
  351. return STATUS_FAILURE;
  352. }
  353. if( arg != buffer )
  354. {
  355. TRACE( "Allocate channel validation failedn" );
  356. return STATUS_FAILURE;
  357. }
  358. }
  359. return STATUS_SUCCESS;
  360. }
  361. unicap_status_t _1394util_allocate_bandwidth( raw1394handle_t raw1394handle, int bandwidth )
  362. {
  363. quadlet_t buffer;
  364. if( 0 > cooked1394_read( raw1394handle, 
  365.  raw1394_get_irm_id( raw1394handle ), 
  366.  CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, 
  367.  sizeof( quadlet_t ), 
  368.  &buffer ) )
  369. {
  370. TRACE( "Failed to get CSR_BANDWIDTH_AVAILABLEn" );
  371. return STATUS_FAILURE;
  372. }
  373. buffer = ntohl( buffer );
  374. if( (int)(buffer - bandwidth) < 0 )
  375. {
  376. TRACE( "Insufficient bandwidthn" );
  377. return STATUS_FAILURE;
  378. }
  379. else
  380. {
  381. quadlet_t data, arg, result;
  382. arg = htonl( buffer );
  383. data = htonl( buffer - bandwidth );
  384. if( 0 > raw1394_lock( raw1394handle, 
  385.       raw1394_get_irm_id( raw1394handle ), 
  386.       CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
  387.       EXTCODE_COMPARE_SWAP, 
  388.       data, 
  389.       arg, 
  390.       &result ) )
  391. {
  392. TRACE( "Failed to allocate bandwidthn" );
  393. return STATUS_FAILURE;
  394. }
  395. if( arg != htonl( buffer ) )
  396. {
  397. TRACE( "Allocate bandwidth validation failedn" );
  398. return STATUS_FAILURE;
  399. }
  400. }
  401. return STATUS_SUCCESS;
  402. }
  403. /*
  404.   free bandwidth
  405.  
  406.   no checking if more bw than allocated is freed!
  407.  */
  408. int _1394util_free_bandwidth( raw1394handle_t raw1394handle, int bandwidth )
  409. {
  410. quadlet_t buffer;
  411. if( 0 > cooked1394_read( raw1394handle, 
  412.  raw1394_get_irm_id( raw1394handle ), 
  413.  CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, 
  414.  sizeof( quadlet_t ), 
  415.  &buffer ) )
  416. {
  417. TRACE( "Failed to get CSR_BANDWIDTH_AVAILABLEn" );
  418. return STATUS_FAILURE;
  419. }
  420. buffer = ntohl( buffer );
  421. TRACE( "Available bandwidth: 0x%x ( %d )n", buffer, buffer );
  422. if( (int)(buffer + bandwidth) > MAX_BANDWIDTH )
  423. { // just a warning!
  424. TRACE( "Freeing of bandwidth gives more than the maximum allowed ( or the bus is > 400Mbps )n" );
  425. }
  426. else
  427. {
  428. quadlet_t data, arg, result;
  429. arg = htonl( buffer );
  430. data = htonl( buffer + bandwidth );
  431. if( 0 > raw1394_lock( raw1394handle, 
  432.       raw1394_get_irm_id( raw1394handle ), 
  433.       CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
  434.       EXTCODE_COMPARE_SWAP, 
  435.       data, 
  436.       arg, 
  437.       &result ) )
  438. {
  439. TRACE( "Failed to allocate bandwidthn" );
  440. return STATUS_FAILURE;
  441. }
  442. if( arg != htonl( buffer ) )
  443. {
  444. TRACE( "Allocate bandwidth validation failed: arg = %x, buffer = %xn", arg, htonl( buffer ) );
  445. return STATUS_FAILURE;
  446. }
  447. }
  448. return STATUS_SUCCESS;
  449. }
  450. /*
  451.   return the bw available on the bus. for convenience only, value could change any time
  452.  */
  453. int _1394util_get_available_bandwidth( raw1394handle_t raw1394handle )
  454. {
  455. quadlet_t buffer;
  456. if( 0 > cooked1394_read( raw1394handle, 
  457.  raw1394_get_irm_id( raw1394handle ), 
  458.  CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, 
  459.  sizeof( quadlet_t ), 
  460.  &buffer ) )
  461. {
  462. TRACE( "Failed to get CSR_BANDWIDTH_AVAILABLEn" );
  463. return -1;
  464. }
  465. buffer =  ntohl( buffer );
  466. return buffer;
  467. }
  468. unsigned long bswap( unsigned long v )
  469. {
  470. unsigned long r;
  471. r = ( v>>24 ) | 
  472. ( ( ( v>>16 ) & 0xff ) << 8 ) |
  473. ( ( ( v>>8 ) & 0xff ) << 16 ) |
  474. ( ( ( v ) & 0xff ) << 24 );
  475. return r;
  476. }
  477. quadlet_t bitswap( quadlet_t value )
  478. {
  479. quadlet_t tmp = 0;
  480. int i;
  481. for( i = 0; i < 32; i++ )
  482. {
  483. tmp |= ( ( ( value >>( 31-i ) ) & 1 ) << i );
  484. }
  485. return tmp;
  486. }