OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ieee1394/] [ieee1394_transactions.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * IEEE 1394 for Linux
3
 *
4
 * Transaction support.
5
 *
6
 * Copyright (C) 1999 Andreas E. Bombe
7
 *
8
 * This code is licensed under the GPL.  See the file COPYING in the root
9
 * directory of the kernel sources for details.
10
 */
11
 
12
#include <linux/sched.h>
13
#include <linux/bitops.h>
14
#include <asm/errno.h>
15
#include <linux/interrupt.h>
16
 
17
#include "ieee1394.h"
18
#include "ieee1394_types.h"
19
#include "hosts.h"
20
#include "ieee1394_core.h"
21
#include "highlevel.h"
22
#include "nodemgr.h"
23
 
24
 
25
#define PREP_ASYNC_HEAD_ADDRESS(tc) \
26
        packet->tcode = tc; \
27
        packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
28
                | (1 << 8) | (tc << 4); \
29
        packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
30
        packet->header[2] = addr & 0xffffffff
31
 
32
 
33
static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
34
{
35
        PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
36
        packet->header_size = 12;
37
        packet->data_size = 0;
38
        packet->expect_response = 1;
39
}
40
 
41
static void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length)
42
{
43
        PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
44
        packet->header[3] = length << 16;
45
        packet->header_size = 16;
46
        packet->data_size = 0;
47
        packet->expect_response = 1;
48
}
49
 
50
static void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data)
51
{
52
        PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
53
        packet->header[3] = data;
54
        packet->header_size = 16;
55
        packet->data_size = 0;
56
        packet->expect_response = 1;
57
}
58
 
59
static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length)
60
{
61
        PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
62
        packet->header[3] = length << 16;
63
        packet->header_size = 16;
64
        packet->expect_response = 1;
65
        packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
66
}
67
 
68
static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
69
                     int length)
70
{
71
        PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
72
        packet->header[3] = (length << 16) | extcode;
73
        packet->header_size = 16;
74
        packet->data_size = length;
75
        packet->expect_response = 1;
76
}
77
 
78
static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
79
                     int tag, int sync)
80
{
81
        packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
82
                | (TCODE_ISO_DATA << 4) | sync;
83
 
84
        packet->header_size = 4;
85
        packet->data_size = length;
86
        packet->type = hpsb_iso;
87
        packet->tcode = TCODE_ISO_DATA;
88
}
89
 
90
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
91
{
92
        packet->header[0] = data;
93
        packet->header[1] = ~data;
94
        packet->header_size = 8;
95
        packet->data_size = 0;
96
        packet->expect_response = 0;
97
        packet->type = hpsb_raw;             /* No CRC added */
98
        packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */
99
}
100
 
101
static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
102
                                     int channel, int tag, int sync)
103
{
104
        packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
105
                          | (TCODE_STREAM_DATA << 4) | sync;
106
 
107
        packet->header_size = 4;
108
        packet->data_size = length;
109
        packet->type = hpsb_async;
110
        packet->tcode = TCODE_ISO_DATA;
111
}
112
 
113
/**
114
 * hpsb_get_tlabel - allocate a transaction label
115
 * @packet: the packet who's tlabel/tpool we set
116
 *
117
 * Every asynchronous transaction on the 1394 bus needs a transaction
118
 * label to match the response to the request.  This label has to be
119
 * different from any other transaction label in an outstanding request to
120
 * the same node to make matching possible without ambiguity.
121
 *
122
 * There are 64 different tlabels, so an allocated tlabel has to be freed
123
 * with hpsb_free_tlabel() after the transaction is complete (unless it's
124
 * reused again for the same target node).
125
 *
126
 * Return value: Zero on success, otherwise non-zero. A non-zero return
127
 * generally means there are no available tlabels. If this is called out
128
 * of interrupt or atomic context, then it will sleep until can return a
129
 * tlabel.
130
 */
131
int hpsb_get_tlabel(struct hpsb_packet *packet)
132
{
133
        unsigned long flags;
134
        struct hpsb_tlabel_pool *tp;
135
 
136
        tp = &packet->host->tpool[packet->node_id & NODE_MASK];
137
 
138
        if (in_interrupt()) {
139
                if (down_trylock(&tp->count))
140
                        return 1;
141
        } else {
142
                down(&tp->count);
143
        }
144
 
145
        spin_lock_irqsave(&tp->lock, flags);
146
 
147
        packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
148
        if (packet->tlabel > 63)
149
                packet->tlabel = find_first_zero_bit(tp->pool, 64);
150
        tp->next = (packet->tlabel + 1) % 64;
151
        /* Should _never_ happen */
152
        BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
153
        tp->allocations++;
154
        spin_unlock_irqrestore(&tp->lock, flags);
155
 
156
        return 0;
157
}
158
 
159
/**
160
 * hpsb_free_tlabel - free an allocated transaction label
161
 * @packet: packet whos tlabel/tpool needs to be cleared
162
 *
163
 * Frees the transaction label allocated with hpsb_get_tlabel().  The
164
 * tlabel has to be freed after the transaction is complete (i.e. response
165
 * was received for a split transaction or packet was sent for a unified
166
 * transaction).
167
 *
168
 * A tlabel must not be freed twice.
169
 */
170
void hpsb_free_tlabel(struct hpsb_packet *packet)
171
{
172
        unsigned long flags;
173
        struct hpsb_tlabel_pool *tp;
174
 
175
        tp = &packet->host->tpool[packet->node_id & NODE_MASK];
176
 
177
        BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
178
 
179
        spin_lock_irqsave(&tp->lock, flags);
180
        BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
181
        spin_unlock_irqrestore(&tp->lock, flags);
182
 
183
        up(&tp->count);
184
}
185
 
186
 
187
 
188
int hpsb_packet_success(struct hpsb_packet *packet)
189
{
190
        switch (packet->ack_code) {
191
        case ACK_PENDING:
192
                switch ((packet->header[1] >> 12) & 0xf) {
193
                case RCODE_COMPLETE:
194
                        return 0;
195
                case RCODE_CONFLICT_ERROR:
196
                        return -EAGAIN;
197
                case RCODE_DATA_ERROR:
198
                        return -EREMOTEIO;
199
                case RCODE_TYPE_ERROR:
200
                        return -EACCES;
201
                case RCODE_ADDRESS_ERROR:
202
                        return -EINVAL;
203
                default:
204
                        HPSB_ERR("received reserved rcode %d from node %d",
205
                                 (packet->header[1] >> 12) & 0xf,
206
                                 packet->node_id);
207
                        return -EAGAIN;
208
                }
209
                HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
210
 
211
        case ACK_BUSY_X:
212
        case ACK_BUSY_A:
213
        case ACK_BUSY_B:
214
                return -EBUSY;
215
 
216
        case ACK_TYPE_ERROR:
217
                return -EACCES;
218
 
219
        case ACK_COMPLETE:
220
                if (packet->tcode == TCODE_WRITEQ
221
                    || packet->tcode == TCODE_WRITEB) {
222
                        return 0;
223
                } else {
224
                        HPSB_ERR("impossible ack_complete from node %d "
225
                                 "(tcode %d)", packet->node_id, packet->tcode);
226
                        return -EAGAIN;
227
                }
228
 
229
 
230
        case ACK_DATA_ERROR:
231
                if (packet->tcode == TCODE_WRITEB
232
                    || packet->tcode == TCODE_LOCK_REQUEST) {
233
                        return -EAGAIN;
234
                } else {
235
                        HPSB_ERR("impossible ack_data_error from node %d "
236
                                 "(tcode %d)", packet->node_id, packet->tcode);
237
                        return -EAGAIN;
238
                }
239
 
240
        case ACKX_NONE:
241
        case ACKX_SEND_ERROR:
242
        case ACKX_ABORTED:
243
        case ACKX_TIMEOUT:
244
                /* error while sending */
245
                return -EAGAIN;
246
 
247
        default:
248
                HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
249
                         packet->ack_code, packet->node_id, packet->tcode);
250
                return -EAGAIN;
251
        }
252
 
253
        HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
254
}
255
 
256
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
257
                                         u64 addr, size_t length)
258
{
259
        struct hpsb_packet *packet;
260
 
261
        if (length == 0)
262
                return NULL;
263
 
264
        packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
265
        if (!packet)
266
                return NULL;
267
 
268
        packet->host = host;
269
        packet->node_id = node;
270
 
271
        if (hpsb_get_tlabel(packet)) {
272
                free_hpsb_packet(packet);
273
                return NULL;
274
        }
275
 
276
        if (length == 4)
277
                fill_async_readquad(packet, addr);
278
        else
279
                fill_async_readblock(packet, addr, length);
280
 
281
        return packet;
282
}
283
 
284
struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node,
285
                                           u64 addr, quadlet_t *buffer, size_t length)
286
{
287
        struct hpsb_packet *packet;
288
 
289
        if (length == 0)
290
                return NULL;
291
 
292
        packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
293
        if (!packet)
294
                return NULL;
295
 
296
        if (length % 4) { /* zero padding bytes */
297
                packet->data[length >> 2] = 0;
298
        }
299
        packet->host = host;
300
        packet->node_id = node;
301
 
302
        if (hpsb_get_tlabel(packet)) {
303
                free_hpsb_packet(packet);
304
                return NULL;
305
        }
306
 
307
        if (length == 4) {
308
                fill_async_writequad(packet, addr, buffer ? *buffer : 0);
309
        } else {
310
                fill_async_writeblock(packet, addr, length);
311
                if (buffer)
312
                        memcpy(packet->data, buffer, length);
313
        }
314
 
315
        return packet;
316
}
317
 
318
struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, int length,
319
                                           int channel, int tag, int sync)
320
{
321
        struct hpsb_packet *packet;
322
 
323
        if (length == 0)
324
                return NULL;
325
 
326
        packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
327
        if (!packet)
328
                return NULL;
329
 
330
        if (length % 4) { /* zero padding bytes */
331
                packet->data[length >> 2] = 0;
332
        }
333
        packet->host = host;
334
 
335
        if (hpsb_get_tlabel(packet)) {
336
                free_hpsb_packet(packet);
337
                return NULL;
338
        }
339
 
340
        fill_async_stream_packet(packet, length, channel, tag, sync);
341
        if (buffer)
342
                memcpy(packet->data, buffer, length);
343
 
344
        return packet;
345
}
346
 
347
struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
348
                                         u64 addr, int extcode, quadlet_t *data,
349
                                         quadlet_t arg)
350
{
351
        struct hpsb_packet *p;
352
        u32 length;
353
 
354
        p = alloc_hpsb_packet(8);
355
        if (!p) return NULL;
356
 
357
        p->host = host;
358
        p->node_id = node;
359
        if (hpsb_get_tlabel(p)) {
360
                free_hpsb_packet(p);
361
                return NULL;
362
        }
363
 
364
        switch (extcode) {
365
        case EXTCODE_FETCH_ADD:
366
        case EXTCODE_LITTLE_ADD:
367
                length = 4;
368
                if (data)
369
                        p->data[0] = *data;
370
                break;
371
        default:
372
                length = 8;
373
                if (data) {
374
                        p->data[0] = arg;
375
                        p->data[1] = *data;
376
                }
377
                break;
378
        }
379
        fill_async_lock(p, addr, extcode, length);
380
 
381
        return p;
382
}
383
 
384
struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
385
                                           u64 addr, int extcode, octlet_t *data,
386
                                           octlet_t arg)
387
{
388
        struct hpsb_packet *p;
389
        u32 length;
390
 
391
        p = alloc_hpsb_packet(16);
392
        if (!p) return NULL;
393
 
394
        p->host = host;
395
        p->node_id = node;
396
        if (hpsb_get_tlabel(p)) {
397
                free_hpsb_packet(p);
398
                return NULL;
399
        }
400
 
401
        switch (extcode) {
402
        case EXTCODE_FETCH_ADD:
403
        case EXTCODE_LITTLE_ADD:
404
                length = 8;
405
                if (data) {
406
                        p->data[0] = *data >> 32;
407
                        p->data[1] = *data & 0xffffffff;
408
                }
409
                break;
410
        default:
411
                length = 16;
412
                if (data) {
413
                        p->data[0] = arg >> 32;
414
                        p->data[1] = arg & 0xffffffff;
415
                        p->data[2] = *data >> 32;
416
                        p->data[3] = *data & 0xffffffff;
417
                }
418
                break;
419
        }
420
        fill_async_lock(p, addr, extcode, length);
421
 
422
        return p;
423
}
424
 
425
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
426
                                        quadlet_t data)
427
{
428
        struct hpsb_packet *p;
429
 
430
        p = alloc_hpsb_packet(0);
431
        if (!p) return NULL;
432
 
433
        p->host = host;
434
        fill_phy_packet(p, data);
435
 
436
        return p;
437
}
438
 
439
struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
440
                                        int length, int channel,
441
                                        int tag, int sync)
442
{
443
        struct hpsb_packet *p;
444
 
445
        p = alloc_hpsb_packet(length);
446
        if (!p) return NULL;
447
 
448
        p->host = host;
449
        fill_iso_packet(p, length, channel, tag, sync);
450
 
451
        p->generation = get_hpsb_generation(host);
452
 
453
        return p;
454
}
455
 
456
/*
457
 * FIXME - these functions should probably read from / write to user space to
458
 * avoid in kernel buffers for user space callers
459
 */
460
 
461
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
462
              u64 addr, quadlet_t *buffer, size_t length)
463
{
464
        struct hpsb_packet *packet;
465
        int retval = 0;
466
 
467
        if (length == 0)
468
                return -EINVAL;
469
 
470
        BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
471
 
472
        packet = hpsb_make_readpacket(host, node, addr, length);
473
 
474
        if (!packet) {
475
                return -ENOMEM;
476
        }
477
 
478
        packet->generation = generation;
479
        if (!hpsb_send_packet(packet)) {
480
                retval = -EINVAL;
481
                goto hpsb_read_fail;
482
        }
483
 
484
        down(&packet->state_change);
485
        down(&packet->state_change);
486
        retval = hpsb_packet_success(packet);
487
 
488
        if (retval == 0) {
489
                if (length == 4) {
490
                        *buffer = packet->header[3];
491
                } else {
492
                        memcpy(buffer, packet->data, length);
493
                }
494
        }
495
 
496
hpsb_read_fail:
497
        hpsb_free_tlabel(packet);
498
        free_hpsb_packet(packet);
499
 
500
        return retval;
501
}
502
 
503
 
504
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
505
               u64 addr, quadlet_t *buffer, size_t length)
506
{
507
        struct hpsb_packet *packet;
508
        int retval;
509
 
510
        if (length == 0)
511
                return -EINVAL;
512
 
513
        BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
514
 
515
        packet = hpsb_make_writepacket (host, node, addr, buffer, length);
516
 
517
        if (!packet)
518
                return -ENOMEM;
519
 
520
        packet->generation = generation;
521
        if (!hpsb_send_packet(packet)) {
522
                retval = -EINVAL;
523
                goto hpsb_write_fail;
524
        }
525
 
526
        down(&packet->state_change);
527
        down(&packet->state_change);
528
        retval = hpsb_packet_success(packet);
529
 
530
hpsb_write_fail:
531
        hpsb_free_tlabel(packet);
532
        free_hpsb_packet(packet);
533
 
534
        return retval;
535
}
536
 
537
 
538
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
539
              u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
540
{
541
        struct hpsb_packet *packet;
542
        int retval = 0;
543
 
544
        BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
545
 
546
        packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
547
        if (!packet)
548
                return -ENOMEM;
549
 
550
        packet->generation = generation;
551
        if (!hpsb_send_packet(packet)) {
552
                retval = -EINVAL;
553
                goto hpsb_lock_fail;
554
        }
555
        down(&packet->state_change);
556
        down(&packet->state_change);
557
        retval = hpsb_packet_success(packet);
558
 
559
        if (retval == 0) {
560
                *data = packet->data[0];
561
        }
562
 
563
hpsb_lock_fail:
564
        hpsb_free_tlabel(packet);
565
        free_hpsb_packet(packet);
566
 
567
        return retval;
568
}
569
 
570
int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
571
                u64 addr, int extcode, octlet_t *data, octlet_t arg)
572
{
573
        struct hpsb_packet *packet;
574
        int retval = 0;
575
 
576
        BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
577
 
578
        packet = hpsb_make_lock64packet(host, node, addr, extcode, data, arg);
579
        if (!packet)
580
                return -ENOMEM;
581
 
582
        packet->generation = generation;
583
        if (!hpsb_send_packet(packet)) {
584
                retval = -EINVAL;
585
                goto hpsb_lock64_fail;
586
        }
587
        down(&packet->state_change);
588
        down(&packet->state_change);
589
        retval = hpsb_packet_success(packet);
590
 
591
        if (retval == 0)
592
                *data = (u64)packet->data[1] << 32 | packet->data[0];
593
 
594
hpsb_lock64_fail:
595
        hpsb_free_tlabel(packet);
596
        free_hpsb_packet(packet);
597
 
598
        return retval;
599
}
600
 
601
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
602
                   quadlet_t *buffer, size_t length, u32 specifier_id,
603
                   unsigned int version)
604
{
605
        struct hpsb_packet *packet;
606
        int retval = 0;
607
        u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
608
        u8 specifier_id_lo = specifier_id & 0xff;
609
 
610
        HPSB_VERBOSE("Send GASP: channel = %d, length = %Zd", channel, length);
611
 
612
        length += 8;
613
 
614
        packet = hpsb_make_streampacket(host, NULL, length, channel, 3, 0);
615
        if (!packet)
616
                return -ENOMEM;
617
 
618
        packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
619
        packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
620
 
621
        memcpy(&(packet->data[2]), buffer, length - 8);
622
 
623
        packet->generation = generation;
624
 
625
        packet->no_waiter = 1;
626
 
627
        if (!hpsb_send_packet(packet)) {
628
                free_hpsb_packet(packet);
629
                retval = -EINVAL;
630
        }
631
 
632
        return retval;
633
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.