OSDN Git Service

bonding: fix panic when taking bond interface down before removing module
[linux-kernel-docs/linux-2.4.36.git] / drivers / ieee1394 / csr.c
1 /*
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 }