7 #include <ieee1394_core.h>
8 #include <ieee1394_transactions.h>
13 BYTE PTPConnCount : 6 ; // Point to point connect. counter
14 BYTE BrConnCount : 1 ; // Broadcast connection counter
15 BYTE OnLine : 1 ; // On Line
17 BYTE ChNr : 6 ; // Channel number
18 BYTE Res : 2 ; // Reserved
20 BYTE PayloadHi : 2 ; // Payoad high bits
21 BYTE OvhdID : 4 ; // Overhead ID
22 BYTE DataRate : 2 ; // Data Rate
24 BYTE PayloadLo ; // Payoad low byte
27 #define FIRESAT_SPEED IEEE1394_SPEED_400
29 /* hpsb_lock is being removed from the kernel-source,
30 * therefor we define our own 'firesat_hpsb_lock'*/
32 int send_packet_and_wait(struct hpsb_packet *packet);
34 int firesat_hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
35 u64 addr, int extcode, quadlet_t * data, quadlet_t arg) {
37 struct hpsb_packet *packet;
40 BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
42 packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
46 packet->generation = generation;
47 retval = send_packet_and_wait(packet);
51 retval = hpsb_packet_success(packet);
54 *data = packet->data[0];
58 hpsb_free_tlabel(packet);
59 hpsb_free_packet(packet);
65 static int cmp_read(struct firesat *firesat, void *buffer, u64 addr, size_t length) {
67 if(down_interruptible(&firesat->avc_sem))
70 ret = hpsb_read(firesat->host, firesat->nodeentry->nodeid, firesat->nodeentry->generation,
71 addr, buffer, length);
73 up(&firesat->avc_sem);
77 static int cmp_lock(struct firesat *firesat, quadlet_t *data, u64 addr, quadlet_t arg, int ext_tcode) {
79 if(down_interruptible(&firesat->avc_sem))
82 ret = firesat_hpsb_lock(firesat->host, firesat->nodeentry->nodeid, firesat->nodeentry->generation,
83 addr, ext_tcode, data, arg);
85 up(&firesat->avc_sem);
89 //try establishing a point-to-point connection (may be interrupted by a busreset
90 int try_CMPEstablishPPconnection(struct firesat *firesat, int output_plug, int iso_channel) {
91 unsigned int BWU; //bandwidth to allocate
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);
97 printk(KERN_INFO "%s: nodeid = %d\n",__func__,firesat->nodeentry->nodeid);
100 printk("%s: cannot read oPCR\n", __func__);
103 printk(KERN_INFO "%s: oPCR = %08x\n",__func__,test_oPCR);
105 OPCR *hilf= (OPCR*) &test_oPCR;
108 printk("%s: Output offline; oPCR: %08x\n", __func__, 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);
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?)
122 hilf->ChNr=iso_channel;
123 hilf->DataRate=FIRESAT_SPEED;
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))
130 cout << "Allocation of resources failed\n";
135 hilf->PTPConnCount++;
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);
142 printk("%s: cannot compare_swap oPCR\n",__func__);
145 if ((old_oPCR != test_oPCR) && (!((OPCR*) &old_oPCR)->PTPConnCount))
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))
154 cout << "Deallocation of resources failed\n";
160 while (old_oPCR != test_oPCR);
165 //try breaking a point-to-point connection (may be interrupted by a busreset
166 int try_CMPBreakPPconnection(struct firesat *firesat, int output_plug,int iso_channel) {
167 quadlet_t old_oPCR,test_oPCR;
169 u64 oPCR_address=0xfffff0000904ull+(output_plug << 2);
170 int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4);
172 printk(KERN_INFO "%s\n",__func__);
175 printk("%s: cannot read oPCR\n", __func__);
179 OPCR *hilf= (OPCR*) &test_oPCR;
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);
187 hilf->PTPConnCount--;
190 // printk(KERN_INFO "%s: trying compare_swap...\n", __func__);
191 result=cmp_lock(firesat, &test_oPCR, oPCR_address, old_oPCR, 2);
193 printk("%s: cannot compare_swap oPCR\n",__func__);
198 } while (old_oPCR != test_oPCR);
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))
207 cout << "Deallocation of resources failed\n";
215 static void complete_packet(void *data) {
216 complete((struct completion *) data);
219 int send_packet_and_wait(struct hpsb_packet *packet) {
220 struct completion done;
223 init_completion(&done);
224 hpsb_set_packet_complete_task(packet, complete_packet, &done);
225 retval = hpsb_send_packet(packet);
227 wait_for_completion(&done);