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