cmp.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "cmp.h"
  2. #include <ieee1394.h>
  3. #include <nodemgr.h>
  4. #include <highlevel.h>
  5. #include <ohci1394.h>
  6. #include <hosts.h>
  7. #include <ieee1394_core.h>
  8. #include <ieee1394_transactions.h>
  9. #include "avc_api.h"
  10. typedef struct _OPCR
  11. {
  12. BYTE PTPConnCount : 6 ; // Point to point connect. counter
  13. BYTE BrConnCount : 1 ; // Broadcast connection counter
  14. BYTE OnLine : 1 ; // On Line
  15. BYTE ChNr : 6 ; // Channel number
  16. BYTE Res : 2 ; // Reserved
  17. BYTE PayloadHi : 2 ; // Payoad high bits
  18. BYTE OvhdID : 4 ; // Overhead ID
  19. BYTE DataRate : 2 ; // Data Rate
  20. BYTE PayloadLo ; // Payoad low byte
  21. } OPCR ;
  22. #define FIRESAT_SPEED IEEE1394_SPEED_400
  23. /* hpsb_lock is being removed from the kernel-source,
  24. * therefor we define our own 'firesat_hpsb_lock'*/
  25. int send_packet_and_wait(struct hpsb_packet *packet);
  26. int firesat_hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
  27. u64 addr, int extcode, quadlet_t * data, quadlet_t arg) {
  28. struct hpsb_packet *packet;
  29. int retval = 0;
  30. BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
  31. packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
  32. if (!packet)
  33. return -ENOMEM;
  34. packet->generation = generation;
  35. retval = send_packet_and_wait(packet);
  36. if (retval < 0)
  37. goto hpsb_lock_fail;
  38. retval = hpsb_packet_success(packet);
  39. if (retval == 0) {
  40. *data = packet->data[0];
  41. }
  42. hpsb_lock_fail:
  43. hpsb_free_tlabel(packet);
  44. hpsb_free_packet(packet);
  45. return retval;
  46. }
  47. static int cmp_read(struct firesat *firesat, void *buffer, u64 addr, size_t length) {
  48. int ret;
  49. if(down_interruptible(&firesat->avc_sem))
  50. return -EINTR;
  51. ret = hpsb_read(firesat->host, firesat->nodeentry->nodeid, firesat->nodeentry->generation,
  52. addr, buffer, length);
  53. up(&firesat->avc_sem);
  54. return ret;
  55. }
  56. static int cmp_lock(struct firesat *firesat, quadlet_t *data, u64 addr, quadlet_t arg, int ext_tcode) {
  57. int ret;
  58. if(down_interruptible(&firesat->avc_sem))
  59. return -EINTR;
  60. ret = firesat_hpsb_lock(firesat->host, firesat->nodeentry->nodeid, firesat->nodeentry->generation,
  61. addr, ext_tcode, data, arg);
  62. up(&firesat->avc_sem);
  63. return ret;
  64. }
  65. //try establishing a point-to-point connection (may be interrupted by a busreset
  66. int try_CMPEstablishPPconnection(struct firesat *firesat, int output_plug, int iso_channel) {
  67. unsigned int BWU; //bandwidth to allocate
  68. quadlet_t old_oPCR,test_oPCR = 0x0;
  69. u64 oPCR_address=0xfffff0000904ull+(output_plug << 2);
  70. int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4);
  71. printk(KERN_INFO "%s: nodeid = %d\n",__func__,firesat->nodeentry->nodeid);
  72. if (result < 0) {
  73. printk("%s: cannot read oPCR\n", __func__);
  74. return result;
  75. } else {
  76. printk(KERN_INFO "%s: oPCR = %08x\n",__func__,test_oPCR);
  77. do {
  78. OPCR *hilf= (OPCR*) &test_oPCR;
  79. if (!hilf->OnLine) {
  80. printk("%s: Output offline; oPCR: %08x\n", __func__, test_oPCR);
  81. return -EBUSY;
  82. } else {
  83. quadlet_t new_oPCR;
  84. old_oPCR=test_oPCR;
  85. if (hilf->PTPConnCount) {
  86. if (hilf->ChNr != iso_channel) {
  87. printk("%s: Output plug has already connection on channel %u; cannot change it to channel %u\n",__func__,hilf->ChNr,iso_channel);
  88. return -EBUSY;
  89. } else
  90. printk(KERN_INFO "%s: Overlaying existing connection; connection counter was: %u\n",__func__, hilf->PTPConnCount);
  91. BWU=0; //we allocate no bandwidth (is this necessary?)
  92. } else {
  93. hilf->ChNr=iso_channel;
  94. hilf->DataRate=FIRESAT_SPEED;
  95. hilf->OvhdID=0; //FIXME: that is for worst case -> optimize
  96. BWU=hilf->OvhdID?hilf->OvhdID*32:512;
  97. BWU += (hilf->PayloadLo + (hilf->PayloadHi << 8) +3) * (2 << (3-hilf->DataRate));
  98. /* if (allocate_1394_resources(iso_channel,BWU))
  99. {
  100. cout << "Allocation of resources failed\n";
  101. return -2;
  102. }*/
  103. }
  104. hilf->PTPConnCount++;
  105. new_oPCR=test_oPCR;
  106. printk(KERN_INFO "%s: trying compare_swap...\n",__func__);
  107. printk(KERN_INFO "%s: oPCR_old: %08x, oPCR_new: %08x\n",__func__, old_oPCR, new_oPCR);
  108. result=cmp_lock(firesat, &test_oPCR, oPCR_address, old_oPCR, 2);
  109. if (result < 0) {
  110. printk("%s: cannot compare_swap oPCR\n",__func__);
  111. return result;
  112. }
  113. if ((old_oPCR != test_oPCR) && (!((OPCR*) &old_oPCR)->PTPConnCount))
  114. {
  115. printk("%s: change of oPCR failed -> freeing resources\n",__func__);
  116. // hilf= (OPCR*) &new_oPCR;
  117. // unsigned int BWU=hilf->OvhdID?hilf->OvhdID*32:512;
  118. // BWU += (hilf->Payload+3) * (2 << (3-hilf->DataRate));
  119. /* if (deallocate_1394_resources(iso_channel,BWU))
  120. {
  121. cout << "Deallocation of resources failed\n";
  122. return -3;
  123. }*/
  124. }
  125. }
  126. }
  127. while (old_oPCR != test_oPCR);
  128. }
  129. return 0;
  130. }
  131. //try breaking a point-to-point connection (may be interrupted by a busreset
  132. int try_CMPBreakPPconnection(struct firesat *firesat, int output_plug,int iso_channel) {
  133. quadlet_t old_oPCR,test_oPCR;
  134. u64 oPCR_address=0xfffff0000904ull+(output_plug << 2);
  135. int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4);
  136. printk(KERN_INFO "%s\n",__func__);
  137. if (result < 0) {
  138. printk("%s: cannot read oPCR\n", __func__);
  139. return result;
  140. } else {
  141. do {
  142. OPCR *hilf= (OPCR*) &test_oPCR;
  143. if (!hilf->OnLine || !hilf->PTPConnCount || hilf->ChNr != iso_channel) {
  144. printk("%s: Output plug does not have PtP-connection on that channel; oPCR: %08x\n", __func__, test_oPCR);
  145. return -EINVAL;
  146. } else {
  147. quadlet_t new_oPCR;
  148. old_oPCR=test_oPCR;
  149. hilf->PTPConnCount--;
  150. new_oPCR=test_oPCR;
  151. // printk(KERN_INFO "%s: trying compare_swap...\n", __func__);
  152. result=cmp_lock(firesat, &test_oPCR, oPCR_address, old_oPCR, 2);
  153. if (result < 0) {
  154. printk("%s: cannot compare_swap oPCR\n",__func__);
  155. return result;
  156. }
  157. }
  158. } while (old_oPCR != test_oPCR);
  159. /* hilf = (OPCR*) &old_oPCR;
  160. if (hilf->PTPConnCount == 1) { // if we were the last owner of this connection
  161. cout << "deallocating 1394 resources\n";
  162. unsigned int BWU=hilf->OvhdID?hilf->OvhdID*32:512;
  163. BWU += (hilf->PayloadLo + (hilf->PayloadHi << 8) +3) * (2 << (3-hilf->DataRate));
  164. if (deallocate_1394_resources(iso_channel,BWU))
  165. {
  166. cout << "Deallocation of resources failed\n";
  167. return -3;
  168. }
  169. }*/
  170. }
  171. return 0;
  172. }
  173. static void complete_packet(void *data) {
  174. complete((struct completion *) data);
  175. }
  176. int send_packet_and_wait(struct hpsb_packet *packet) {
  177. struct completion done;
  178. int retval;
  179. init_completion(&done);
  180. hpsb_set_packet_complete_task(packet, complete_packet, &done);
  181. retval = hpsb_send_packet(packet);
  182. if (retval == 0)
  183. wait_for_completion(&done);
  184. return retval;
  185. }