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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [ieee1394/] [ieee1394_transactions.c] - Blame information for rev 67

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

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

powered by: WebSVN 2.1.0

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