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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ieee1394/] [csr.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
 * CSR implementation, iso/bus manager implementation.
5
 *
6
 * Copyright (C) 1999 Andreas E. Bombe
7
 *               2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
8
 *
9
 * This code is licensed under the GPL.  See the file COPYING in the root
10
 * directory of the kernel sources for details.
11
 *
12
 *
13
 * Contributions:
14
 *
15
 * Manfred Weihs <weihs@ict.tuwien.ac.at>
16
 *        configuration ROM manipulation
17
 *
18
 */
19
 
20
#include <linux/string.h>
21
#include <linux/module.h> /* needed for MODULE_PARM */
22
#include <linux/param.h>
23
#include <linux/spinlock.h>
24
 
25
#include "ieee1394_types.h"
26
#include "hosts.h"
27
#include "ieee1394.h"
28
#include "highlevel.h"
29
 
30
/* Module Parameters */
31
/* this module parameter can be used to disable mapping of the FCP registers */
32
MODULE_PARM(fcp,"i");
33
MODULE_PARM_DESC(fcp, "FCP-registers");
34
static int fcp = 1;
35
 
36
static u16 csr_crc16(unsigned *data, int length)
37
{
38
        int check=0, i;
39
        int shift, sum, next=0;
40
 
41
        for (i = length; i; i--) {
42
                for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
43
                        sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf;
44
                        next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
45
                }
46
                check = next & 0xffff;
47
                data++;
48
        }
49
 
50
        return check;
51
}
52
 
53
static void host_reset(struct hpsb_host *host)
54
{
55
        host->csr.state &= 0x300;
56
 
57
        host->csr.bus_manager_id = 0x3f;
58
        host->csr.bandwidth_available = 4915;
59
        host->csr.channels_available_hi = 0xfffffffe;   /* pre-alloc ch 31 per 1394a-2000 */
60
        host->csr.channels_available_lo = ~0;
61
        host->csr.broadcast_channel = 0x80000000 | 31;
62
 
63
        if (host->is_irm) {
64
                if (host->driver->hw_csr_reg) {
65
                        host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
66
                }
67
        }
68
 
69
        host->csr.node_ids = host->node_id << 16;
70
 
71
        if (!host->is_root) {
72
                /* clear cmstr bit */
73
                host->csr.state &= ~0x100;
74
        }
75
 
76
        host->csr.topology_map[1] =
77
                cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1);
78
        host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16
79
                                                | host->selfid_count);
80
        host->csr.topology_map[0] =
81
                cpu_to_be32((host->selfid_count + 2) << 16
82
                            | csr_crc16(host->csr.topology_map + 1,
83
                                        host->selfid_count + 2));
84
 
85
        host->csr.speed_map[1] =
86
                cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1);
87
        host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16
88
                                             | csr_crc16(host->csr.speed_map+1,
89
                                                         0x3f1));
90
}
91
 
92
/*
93
 * HI == seconds (bits 0:2)
94
 * LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31)
95
 *
96
 * Convert to units and then to HZ, for comparison to jiffies.
97
 *
98
 * By default this will end up being 800 units, or 100ms (125usec per
99
 * unit).
100
 *
101
 * NOTE: The spec says 1/8000, but also says we can compute based on 1/8192
102
 * like CSR specifies. Should make our math less complex.
103
 */
104
static inline void calculate_expire(struct csr_control *csr)
105
{
106
        unsigned long units;
107
 
108
        /* Take the seconds, and convert to units */
109
        units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13;
110
 
111
        /* Add in the fractional units */
112
        units += (unsigned long)(csr->split_timeout_lo >> 19);
113
 
114
        /* Convert to jiffies */
115
        csr->expire = (unsigned long)(units * HZ) >> 13UL;
116
 
117
        /* Just to keep from rounding low */
118
        csr->expire++;
119
 
120
        HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%d", csr->expire, HZ);
121
}
122
 
123
 
124
static void add_host(struct hpsb_host *host)
125
{
126
        host->csr.lock = SPIN_LOCK_UNLOCKED;
127
 
128
        host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);
129
        host->csr.rom_version           = 0;
130
        host->csr.state                 = 0;
131
        host->csr.node_ids              = 0;
132
        host->csr.split_timeout_hi      = 0;
133
        host->csr.split_timeout_lo      = 800 << 19;
134
        calculate_expire(&host->csr);
135
        host->csr.cycle_time            = 0;
136
        host->csr.bus_time              = 0;
137
        host->csr.bus_manager_id        = 0x3f;
138
        host->csr.bandwidth_available   = 4915;
139
        host->csr.channels_available_hi = 0xfffffffe;   /* pre-alloc ch 31 per 1394a-2000 */
140
        host->csr.channels_available_lo = ~0;
141
        host->csr.broadcast_channel = 0x80000000 | 31;
142
 
143
        if (host->is_irm) {
144
                if (host->driver->hw_csr_reg) {
145
                        host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
146
                }
147
        }
148
}
149
 
150
int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
151
        size_t size, unsigned char rom_version)
152
{
153
        unsigned long flags;
154
        int ret;
155
 
156
        spin_lock_irqsave(&host->csr.lock, flags);
157
        if (rom_version != host->csr.rom_version)
158
                 ret = -1;
159
        else if (size > (CSR_CONFIG_ROM_SIZE << 2))
160
                 ret = -2;
161
        else {
162
                 memcpy(host->csr.rom,new_rom,size);
163
                 host->csr.rom_size=size;
164
                 host->csr.rom_version++;
165
                 ret=0;
166
        }
167
        spin_unlock_irqrestore(&host->csr.lock, flags);
168
        return ret;
169
}
170
 
171
int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
172
        size_t buffersize, size_t *rom_size, unsigned char *rom_version)
173
{
174
        unsigned long flags;
175
        int ret;
176
 
177
        spin_lock_irqsave(&host->csr.lock, flags);
178
        *rom_version=host->csr.rom_version;
179
        *rom_size=host->csr.rom_size;
180
        if (buffersize < host->csr.rom_size)
181
                 ret = -1;
182
        else {
183
                 memcpy(buffer,host->csr.rom,host->csr.rom_size);
184
                 ret=0;
185
        }
186
        spin_unlock_irqrestore(&host->csr.lock, flags);
187
        return ret;
188
}
189
 
190
 
191
/* Read topology / speed maps and configuration ROM */
192
static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
193
                     u64 addr, size_t length, u16 fl)
194
{
195
        unsigned long flags;
196
        int csraddr = addr - CSR_REGISTER_BASE;
197
        const char *src;
198
 
199
        spin_lock_irqsave(&host->csr.lock, flags);
200
 
201
        if (csraddr < CSR_TOPOLOGY_MAP) {
202
                if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
203
                        spin_unlock_irqrestore(&host->csr.lock, flags);
204
                        return RCODE_ADDRESS_ERROR;
205
                }
206
                src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;
207
        } else if (csraddr < CSR_SPEED_MAP) {
208
                src = ((char *)host->csr.topology_map) + csraddr
209
                        - CSR_TOPOLOGY_MAP;
210
        } else {
211
                src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;
212
        }
213
 
214
        memcpy(buffer, src, length);
215
        spin_unlock_irqrestore(&host->csr.lock, flags);
216
        return RCODE_COMPLETE;
217
}
218
 
219
 
220
#define out if (--length == 0) break
221
 
222
static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
223
                     u64 addr, size_t length, u16 flags)
224
{
225
        int csraddr = addr - CSR_REGISTER_BASE;
226
        int oldcycle;
227
        quadlet_t ret;
228
 
229
        if ((csraddr | length) & 0x3)
230
                return RCODE_TYPE_ERROR;
231
 
232
        length /= 4;
233
 
234
        switch (csraddr) {
235
        case CSR_STATE_CLEAR:
236
                *(buf++) = cpu_to_be32(host->csr.state);
237
                out;
238
        case CSR_STATE_SET:
239
                *(buf++) = cpu_to_be32(host->csr.state);
240
                out;
241
        case CSR_NODE_IDS:
242
                *(buf++) = cpu_to_be32(host->csr.node_ids);
243
                out;
244
 
245
        case CSR_RESET_START:
246
                return RCODE_TYPE_ERROR;
247
 
248
                /* address gap - handled by default below */
249
 
250
        case CSR_SPLIT_TIMEOUT_HI:
251
                *(buf++) = cpu_to_be32(host->csr.split_timeout_hi);
252
                out;
253
        case CSR_SPLIT_TIMEOUT_LO:
254
                *(buf++) = cpu_to_be32(host->csr.split_timeout_lo);
255
                out;
256
 
257
                /* address gap */
258
                return RCODE_ADDRESS_ERROR;
259
 
260
        case CSR_CYCLE_TIME:
261
                oldcycle = host->csr.cycle_time;
262
                host->csr.cycle_time =
263
                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
264
 
265
                if (oldcycle > host->csr.cycle_time) {
266
                        /* cycle time wrapped around */
267
                        host->csr.bus_time += 1 << 7;
268
                }
269
                *(buf++) = cpu_to_be32(host->csr.cycle_time);
270
                out;
271
        case CSR_BUS_TIME:
272
                oldcycle = host->csr.cycle_time;
273
                host->csr.cycle_time =
274
                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
275
 
276
                if (oldcycle > host->csr.cycle_time) {
277
                        /* cycle time wrapped around */
278
                        host->csr.bus_time += (1 << 7);
279
                }
280
                *(buf++) = cpu_to_be32(host->csr.bus_time
281
                                       | (host->csr.cycle_time >> 25));
282
                out;
283
 
284
                /* address gap */
285
                return RCODE_ADDRESS_ERROR;
286
 
287
        case CSR_BUSY_TIMEOUT:
288
                /* not yet implemented */
289
                return RCODE_ADDRESS_ERROR;
290
 
291
        case CSR_BUS_MANAGER_ID:
292
                if (host->driver->hw_csr_reg)
293
                        ret = host->driver->hw_csr_reg(host, 0, 0, 0);
294
                else
295
                        ret = host->csr.bus_manager_id;
296
 
297
                *(buf++) = cpu_to_be32(ret);
298
                out;
299
        case CSR_BANDWIDTH_AVAILABLE:
300
                if (host->driver->hw_csr_reg)
301
                        ret = host->driver->hw_csr_reg(host, 1, 0, 0);
302
                else
303
                        ret = host->csr.bandwidth_available;
304
 
305
                *(buf++) = cpu_to_be32(ret);
306
                out;
307
        case CSR_CHANNELS_AVAILABLE_HI:
308
                if (host->driver->hw_csr_reg)
309
                        ret = host->driver->hw_csr_reg(host, 2, 0, 0);
310
                else
311
                        ret = host->csr.channels_available_hi;
312
 
313
                *(buf++) = cpu_to_be32(ret);
314
                out;
315
        case CSR_CHANNELS_AVAILABLE_LO:
316
                if (host->driver->hw_csr_reg)
317
                        ret = host->driver->hw_csr_reg(host, 3, 0, 0);
318
                else
319
                        ret = host->csr.channels_available_lo;
320
 
321
                *(buf++) = cpu_to_be32(ret);
322
                out;
323
 
324
        case CSR_BROADCAST_CHANNEL:
325
                *(buf++) = cpu_to_be32(host->csr.broadcast_channel);
326
                out;
327
 
328
                /* address gap to end - fall through to default */
329
        default:
330
                return RCODE_ADDRESS_ERROR;
331
        }
332
 
333
        return RCODE_COMPLETE;
334
}
335
 
336
static int write_regs(struct hpsb_host *host, int nodeid, int destid,
337
                      quadlet_t *data, u64 addr, size_t length, u16 flags)
338
{
339
        int csraddr = addr - CSR_REGISTER_BASE;
340
 
341
        if ((csraddr | length) & 0x3)
342
                return RCODE_TYPE_ERROR;
343
 
344
        length /= 4;
345
 
346
        switch (csraddr) {
347
        case CSR_STATE_CLEAR:
348
                /* FIXME FIXME FIXME */
349
                printk("doh, someone wants to mess with state clear\n");
350
                out;
351
        case CSR_STATE_SET:
352
                printk("doh, someone wants to mess with state set\n");
353
                out;
354
 
355
        case CSR_NODE_IDS:
356
                host->csr.node_ids &= NODE_MASK << 16;
357
                host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);
358
                host->node_id = host->csr.node_ids >> 16;
359
                host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6);
360
                out;
361
 
362
        case CSR_RESET_START:
363
                /* FIXME - perform command reset */
364
                out;
365
 
366
                /* address gap */
367
                return RCODE_ADDRESS_ERROR;
368
 
369
        case CSR_SPLIT_TIMEOUT_HI:
370
                host->csr.split_timeout_hi =
371
                        be32_to_cpu(*(data++)) & 0x00000007;
372
                calculate_expire(&host->csr);
373
                out;
374
        case CSR_SPLIT_TIMEOUT_LO:
375
                host->csr.split_timeout_lo =
376
                        be32_to_cpu(*(data++)) & 0xfff80000;
377
                calculate_expire(&host->csr);
378
                out;
379
 
380
                /* address gap */
381
                return RCODE_ADDRESS_ERROR;
382
 
383
        case CSR_CYCLE_TIME:
384
                /* should only be set by cycle start packet, automatically */
385
                host->csr.cycle_time = be32_to_cpu(*data);
386
                host->driver->devctl(host, SET_CYCLE_COUNTER,
387
                                       be32_to_cpu(*(data++)));
388
                out;
389
        case CSR_BUS_TIME:
390
                host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80;
391
                out;
392
 
393
                /* address gap */
394
                return RCODE_ADDRESS_ERROR;
395
 
396
        case CSR_BUSY_TIMEOUT:
397
                /* not yet implemented */
398
                return RCODE_ADDRESS_ERROR;
399
 
400
        case CSR_BUS_MANAGER_ID:
401
        case CSR_BANDWIDTH_AVAILABLE:
402
        case CSR_CHANNELS_AVAILABLE_HI:
403
        case CSR_CHANNELS_AVAILABLE_LO:
404
                /* these are not writable, only lockable */
405
                return RCODE_TYPE_ERROR;
406
 
407
        case CSR_BROADCAST_CHANNEL:
408
                /* only the valid bit can be written */
409
                host->csr.broadcast_channel = (host->csr.broadcast_channel & ~0x40000000)
410
                        | (be32_to_cpu(*data) & 0x40000000);
411
                out;
412
 
413
                /* address gap to end - fall through */
414
        default:
415
                return RCODE_ADDRESS_ERROR;
416
        }
417
 
418
        return RCODE_COMPLETE;
419
}
420
 
421
#undef out
422
 
423
 
424
static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
425
                     u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl)
426
{
427
        int csraddr = addr - CSR_REGISTER_BASE;
428
        unsigned long flags;
429
        quadlet_t *regptr = NULL;
430
 
431
        if (csraddr & 0x3)
432
                return RCODE_TYPE_ERROR;
433
 
434
        if (csraddr < CSR_BUS_MANAGER_ID || csraddr > CSR_CHANNELS_AVAILABLE_LO
435
            || extcode != EXTCODE_COMPARE_SWAP)
436
                goto unsupported_lockreq;
437
 
438
        data = be32_to_cpu(data);
439
        arg = be32_to_cpu(arg);
440
 
441
        /* Is somebody releasing the broadcast_channel on us? */
442
        if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x1)) {
443
                /* Note: this is may not be the right way to handle
444
                 * the problem, so we should look into the proper way
445
                 * eventually. */
446
                HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
447
                          "broadcast channel 31.  Ignoring.",
448
                          NODE_BUS_ARGS(host, nodeid));
449
 
450
                data &= ~0x1;   /* keep broadcast channel allocated */
451
        }
452
 
453
        if (host->driver->hw_csr_reg) {
454
                quadlet_t old;
455
 
456
                old = host->driver->
457
                        hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
458
                                   data, arg);
459
 
460
                *store = cpu_to_be32(old);
461
                return RCODE_COMPLETE;
462
        }
463
 
464
        spin_lock_irqsave(&host->csr.lock, flags);
465
 
466
        switch (csraddr) {
467
        case CSR_BUS_MANAGER_ID:
468
                regptr = &host->csr.bus_manager_id;
469
                *store = cpu_to_be32(*regptr);
470
                if (*regptr == arg)
471
                        *regptr = data;
472
                break;
473
 
474
        case CSR_BANDWIDTH_AVAILABLE:
475
        {
476
                quadlet_t bandwidth;
477
                quadlet_t old;
478
                quadlet_t new;
479
 
480
                regptr = &host->csr.bandwidth_available;
481
                old = *regptr;
482
 
483
                /* bandwidth available algorithm adapted from IEEE 1394a-2000 spec */
484
                if (arg > 0x1fff) {
485
                        *store = cpu_to_be32(old);      /* change nothing */
486
                        break;
487
                }
488
                data &= 0x1fff;
489
                if (arg >= data) {
490
                        /* allocate bandwidth */
491
                        bandwidth = arg - data;
492
                        if (old >= bandwidth) {
493
                                new = old - bandwidth;
494
                                *store = cpu_to_be32(arg);
495
                                *regptr = new;
496
                        } else {
497
                                *store = cpu_to_be32(old);
498
                        }
499
                } else {
500
                        /* deallocate bandwidth */
501
                        bandwidth = data - arg;
502
                        if (old + bandwidth < 0x2000) {
503
                                new = old + bandwidth;
504
                                *store = cpu_to_be32(arg);
505
                                *regptr = new;
506
                        } else {
507
                                *store = cpu_to_be32(old);
508
                        }
509
                }
510
                break;
511
        }
512
 
513
        case CSR_CHANNELS_AVAILABLE_HI:
514
        {
515
                /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */
516
                quadlet_t affected_channels = arg ^ data;
517
 
518
                regptr = &host->csr.channels_available_hi;
519
 
520
                if ((arg & affected_channels) == (*regptr & affected_channels)) {
521
                        *regptr ^= affected_channels;
522
                        *store = cpu_to_be32(arg);
523
                } else {
524
                        *store = cpu_to_be32(*regptr);
525
                }
526
 
527
                break;
528
        }
529
 
530
        case CSR_CHANNELS_AVAILABLE_LO:
531
        {
532
                /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */
533
                quadlet_t affected_channels = arg ^ data;
534
 
535
                regptr = &host->csr.channels_available_lo;
536
 
537
                if ((arg & affected_channels) == (*regptr & affected_channels)) {
538
                        *regptr ^= affected_channels;
539
                        *store = cpu_to_be32(arg);
540
                } else {
541
                        *store = cpu_to_be32(*regptr);
542
                }
543
                break;
544
        }
545
        }
546
 
547
        spin_unlock_irqrestore(&host->csr.lock, flags);
548
 
549
        return RCODE_COMPLETE;
550
 
551
 unsupported_lockreq:
552
        switch (csraddr) {
553
        case CSR_STATE_CLEAR:
554
        case CSR_STATE_SET:
555
        case CSR_RESET_START:
556
        case CSR_NODE_IDS:
557
        case CSR_SPLIT_TIMEOUT_HI:
558
        case CSR_SPLIT_TIMEOUT_LO:
559
        case CSR_CYCLE_TIME:
560
        case CSR_BUS_TIME:
561
        case CSR_BROADCAST_CHANNEL:
562
                return RCODE_TYPE_ERROR;
563
 
564
        case CSR_BUSY_TIMEOUT:
565
                /* not yet implemented - fall through */
566
        default:
567
                return RCODE_ADDRESS_ERROR;
568
        }
569
}
570
 
571
static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
572
                       u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl)
573
{
574
        int csraddr = addr - CSR_REGISTER_BASE;
575
        unsigned long flags;
576
 
577
        data = be64_to_cpu(data);
578
        arg = be64_to_cpu(arg);
579
 
580
        if (csraddr & 0x3)
581
                return RCODE_TYPE_ERROR;
582
 
583
        if (csraddr != CSR_CHANNELS_AVAILABLE
584
            || extcode != EXTCODE_COMPARE_SWAP)
585
                goto unsupported_lock64req;
586
 
587
        /* Is somebody releasing the broadcast_channel on us? */
588
        if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x100000000ULL)) {
589
                /* Note: this is may not be the right way to handle
590
                 * the problem, so we should look into the proper way
591
                 * eventually. */
592
                HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
593
                          "broadcast channel 31.  Ignoring.",
594
                          NODE_BUS_ARGS(host, nodeid));
595
 
596
                data &= ~0x100000000ULL;        /* keep broadcast channel allocated */
597
        }
598
 
599
        if (host->driver->hw_csr_reg) {
600
                quadlet_t data_hi, data_lo;
601
                quadlet_t arg_hi, arg_lo;
602
                quadlet_t old_hi, old_lo;
603
 
604
                data_hi = data >> 32;
605
                data_lo = data & 0xFFFFFFFF;
606
                arg_hi = arg >> 32;
607
                arg_lo = arg & 0xFFFFFFFF;
608
 
609
                old_hi = host->driver->hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
610
                                                  data_hi, arg_hi);
611
 
612
                old_lo = host->driver->hw_csr_reg(host, ((csraddr + 4) - CSR_BUS_MANAGER_ID) >> 2,
613
                                                  data_lo, arg_lo);
614
 
615
                *store = cpu_to_be64(((octlet_t)old_hi << 32) | old_lo);
616
        } else {
617
                octlet_t old;
618
                octlet_t affected_channels = arg ^ data;
619
 
620
                spin_lock_irqsave(&host->csr.lock, flags);
621
 
622
                old = ((octlet_t)host->csr.channels_available_hi << 32) | host->csr.channels_available_lo;
623
 
624
                if ((arg & affected_channels) == (old & affected_channels)) {
625
                        host->csr.channels_available_hi ^= (affected_channels >> 32);
626
                        host->csr.channels_available_lo ^= (affected_channels & 0xffffffff);
627
                        *store = cpu_to_be64(arg);
628
                } else {
629
                        *store = cpu_to_be64(old);
630
                }
631
 
632
                spin_unlock_irqrestore(&host->csr.lock, flags);
633
        }
634
 
635
        /* Is somebody erroneously releasing the broadcast_channel on us? */
636
        if (host->csr.channels_available_hi & 0x1)
637
                host->csr.channels_available_hi &= ~0x1;
638
 
639
        return RCODE_COMPLETE;
640
 
641
 unsupported_lock64req:
642
        switch (csraddr) {
643
        case CSR_STATE_CLEAR:
644
        case CSR_STATE_SET:
645
        case CSR_RESET_START:
646
        case CSR_NODE_IDS:
647
        case CSR_SPLIT_TIMEOUT_HI:
648
        case CSR_SPLIT_TIMEOUT_LO:
649
        case CSR_CYCLE_TIME:
650
        case CSR_BUS_TIME:
651
        case CSR_BUS_MANAGER_ID:
652
        case CSR_BROADCAST_CHANNEL:
653
        case CSR_BUSY_TIMEOUT:
654
        case CSR_BANDWIDTH_AVAILABLE:
655
                return RCODE_TYPE_ERROR;
656
 
657
        default:
658
                return RCODE_ADDRESS_ERROR;
659
        }
660
}
661
 
662
static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
663
                     quadlet_t *data, u64 addr, size_t length, u16 flags)
664
{
665
        int csraddr = addr - CSR_REGISTER_BASE;
666
 
667
        if (length > 512)
668
                return RCODE_TYPE_ERROR;
669
 
670
        switch (csraddr) {
671
        case CSR_FCP_COMMAND:
672
                highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length);
673
                break;
674
        case CSR_FCP_RESPONSE:
675
                highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length);
676
                break;
677
        default:
678
                return RCODE_TYPE_ERROR;
679
        }
680
 
681
        return RCODE_COMPLETE;
682
}
683
 
684
 
685
static struct hpsb_highlevel csr_highlevel = {
686
        .name =         "standard registers",
687
        .add_host =     add_host,
688
        .host_reset =   host_reset,
689
};
690
 
691
 
692
static struct hpsb_address_ops map_ops = {
693
        .read = read_maps,
694
};
695
 
696
static struct hpsb_address_ops fcp_ops = {
697
        .write = write_fcp,
698
};
699
 
700
static struct hpsb_address_ops reg_ops = {
701
        .read = read_regs,
702
        .write = write_regs,
703
        .lock = lock_regs,
704
        .lock64 = lock64_regs,
705
};
706
 
707
void init_csr(void)
708
{
709
        hpsb_register_highlevel(&csr_highlevel);
710
 
711
        hpsb_register_addrspace(&csr_highlevel, &reg_ops, CSR_REGISTER_BASE,
712
                                CSR_REGISTER_BASE + CSR_CONFIG_ROM);
713
        hpsb_register_addrspace(&csr_highlevel, &map_ops,
714
                                CSR_REGISTER_BASE + CSR_CONFIG_ROM,
715
                                CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
716
        if (fcp) {
717
                hpsb_register_addrspace(&csr_highlevel, &fcp_ops,
718
                                CSR_REGISTER_BASE + CSR_FCP_COMMAND,
719
                                CSR_REGISTER_BASE + CSR_FCP_END);
720
        }
721
        hpsb_register_addrspace(&csr_highlevel, &map_ops,
722
                                CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
723
                                CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
724
        hpsb_register_addrspace(&csr_highlevel, &map_ops,
725
                                CSR_REGISTER_BASE + CSR_SPEED_MAP,
726
                                CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
727
}
728
 
729
void cleanup_csr(void)
730
{
731
        hpsb_unregister_highlevel(&csr_highlevel);
732
}

powered by: WebSVN 2.1.0

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