import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.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
23 #include "ieee1394_types.h"
24 #include "hosts.h"
25 #include "ieee1394.h"
26 #include "highlevel.h"
27
28 /* Module Parameters */
29 /* this module parameter can be used to disable mapping of the FCP registers */
30 MODULE_PARM(fcp,"i");
31 MODULE_PARM_DESC(fcp, "FCP-registers");
32 static int fcp = 1;
33
34 static u16 csr_crc16(unsigned *data, int length)
35 {
36         int check=0, i;
37         int shift, sum, next=0;
38
39         for (i = length; i; i--) {
40                 for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
41                         sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf;
42                         next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
43                 }
44                 check = next & 0xffff;
45                 data++;
46         }
47
48         return check;
49 }
50
51 static void host_reset(struct hpsb_host *host)
52 {
53         host->csr.state &= 0x300;
54
55         host->csr.bus_manager_id = 0x3f;
56         host->csr.bandwidth_available = 4915;
57         host->csr.channels_available_hi = ~0;
58         host->csr.channels_available_lo = ~0;
59
60         host->csr.node_ids = host->node_id << 16;
61
62         if (!host->is_root) {
63                 /* clear cmstr bit */
64                 host->csr.state &= ~0x100;
65         }
66
67         host->csr.topology_map[1] = 
68                 cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1);
69         host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16 
70                                                 | host->selfid_count);
71         host->csr.topology_map[0] = 
72                 cpu_to_be32((host->selfid_count + 2) << 16
73                             | csr_crc16(host->csr.topology_map + 1,
74                                         host->selfid_count + 2));
75
76         host->csr.speed_map[1] = 
77                 cpu_to_be32(be32_to_cpu(host->csr.speed_map[1]) + 1);
78         host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16 
79                                              | csr_crc16(host->csr.speed_map+1,
80                                                          0x3f1));
81 }
82
83
84 static void add_host(struct hpsb_host *host)
85 {
86         host->csr.lock = SPIN_LOCK_UNLOCKED;
87
88         host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);
89         host->csr.rom_version           = 0;
90         host->csr.state                 = 0;
91         host->csr.node_ids              = 0;
92         host->csr.split_timeout_hi      = 0;
93         host->csr.split_timeout_lo      = 800 << 19;
94         host->csr.cycle_time            = 0;
95         host->csr.bus_time              = 0;
96         host->csr.bus_manager_id        = 0x3f;
97         host->csr.bandwidth_available   = 4915;
98         host->csr.channels_available_hi = ~0;
99         host->csr.channels_available_lo = ~0;
100 }
101
102 int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, 
103         size_t size, unsigned char rom_version)
104 {
105         int ret,flags;
106         spin_lock_irqsave(&host->csr.lock, flags); 
107         if (rom_version != host->csr.rom_version)
108                  ret = -1;
109         else if (size > (CSR_CONFIG_ROM_SIZE << 2))
110                  ret = -2;
111         else {
112                  memcpy(host->csr.rom,new_rom,size);
113                  host->csr.rom_size=size;
114                  host->csr.rom_version++;
115                  ret=0;
116         }
117         spin_unlock_irqrestore(&host->csr.lock, flags);
118         return ret;
119 }
120
121 int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, 
122         size_t buffersize, size_t *rom_size, unsigned char *rom_version)
123 {
124         int ret,flags;
125         spin_lock_irqsave(&host->csr.lock, flags); 
126         *rom_version=host->csr.rom_version;
127         *rom_size=host->csr.rom_size;
128         if (buffersize < host->csr.rom_size)
129                  ret = -1;
130         else {
131                  memcpy(buffer,host->csr.rom,host->csr.rom_size);
132                  ret=0;
133         }
134         spin_unlock_irqrestore(&host->csr.lock, flags);
135         return ret;
136 }
137
138
139 /* Read topology / speed maps and configuration ROM */
140 static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
141                      u64 addr, unsigned int length, u16 fl)
142 {
143         int csraddr = addr - CSR_REGISTER_BASE;
144         const char *src;
145         int flags;
146
147         spin_lock_irqsave(&host->csr.lock, flags); 
148
149         if (csraddr < CSR_TOPOLOGY_MAP) {
150                 if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
151                         return RCODE_ADDRESS_ERROR;
152                 }
153                 src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;
154         } else if (csraddr < CSR_SPEED_MAP) {
155                 src = ((char *)host->csr.topology_map) + csraddr 
156                         - CSR_TOPOLOGY_MAP;
157         } else {
158                 src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;
159         }
160
161         memcpy(buffer, src, length);
162         spin_unlock_irqrestore(&host->csr.lock, flags);
163         return RCODE_COMPLETE;
164 }
165
166
167 #define out if (--length == 0) break
168
169 static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
170                      u64 addr, unsigned int length, u16 flags)
171 {
172         int csraddr = addr - CSR_REGISTER_BASE;
173         int oldcycle;
174         quadlet_t ret;
175         
176         if ((csraddr | length) & 0x3)
177                 return RCODE_TYPE_ERROR;
178
179         length /= 4;
180
181         switch (csraddr) {
182         case CSR_STATE_CLEAR:
183                 *(buf++) = cpu_to_be32(host->csr.state);
184                 out;
185         case CSR_STATE_SET:
186                 *(buf++) = cpu_to_be32(host->csr.state);
187                 out;
188         case CSR_NODE_IDS:
189                 *(buf++) = cpu_to_be32(host->csr.node_ids);
190                 out;
191
192         case CSR_RESET_START:
193                 return RCODE_TYPE_ERROR;
194
195                 /* address gap - handled by default below */
196
197         case CSR_SPLIT_TIMEOUT_HI:
198                 *(buf++) = cpu_to_be32(host->csr.split_timeout_hi);
199                 out;
200         case CSR_SPLIT_TIMEOUT_LO:
201                 *(buf++) = cpu_to_be32(host->csr.split_timeout_lo);
202                 out;
203
204                 /* address gap */
205                 return RCODE_ADDRESS_ERROR;
206
207         case CSR_CYCLE_TIME:
208                 oldcycle = host->csr.cycle_time;
209                 host->csr.cycle_time =
210                         host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
211
212                 if (oldcycle > host->csr.cycle_time) {
213                         /* cycle time wrapped around */
214                         host->csr.bus_time += 1 << 7;
215                 }
216                 *(buf++) = cpu_to_be32(host->csr.cycle_time);
217                 out;
218         case CSR_BUS_TIME:
219                 oldcycle = host->csr.cycle_time;
220                 host->csr.cycle_time =
221                         host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
222
223                 if (oldcycle > host->csr.cycle_time) {
224                         /* cycle time wrapped around */
225                         host->csr.bus_time += (1 << 7);
226                 }
227                 *(buf++) = cpu_to_be32(host->csr.bus_time 
228                                        | (host->csr.cycle_time >> 25));
229                 out;
230
231                 /* address gap */
232                 return RCODE_ADDRESS_ERROR;
233
234         case CSR_BUSY_TIMEOUT:
235                 /* not yet implemented */
236                 return RCODE_ADDRESS_ERROR;
237
238         case CSR_BUS_MANAGER_ID:
239                 if (host->driver->hw_csr_reg)
240                         ret = host->driver->hw_csr_reg(host, 0, 0, 0);
241                 else
242                         ret = host->csr.bus_manager_id;
243
244                 *(buf++) = cpu_to_be32(ret);
245                 out;
246         case CSR_BANDWIDTH_AVAILABLE:
247                 if (host->driver->hw_csr_reg)
248                         ret = host->driver->hw_csr_reg(host, 1, 0, 0);
249                 else
250                         ret = host->csr.bandwidth_available;
251
252                 *(buf++) = cpu_to_be32(ret);
253                 out;
254         case CSR_CHANNELS_AVAILABLE_HI:
255                 if (host->driver->hw_csr_reg)
256                         ret = host->driver->hw_csr_reg(host, 2, 0, 0);
257                 else
258                         ret = host->csr.channels_available_hi;
259
260                 *(buf++) = cpu_to_be32(ret);
261                 out;
262         case CSR_CHANNELS_AVAILABLE_LO:
263                 if (host->driver->hw_csr_reg)
264                         ret = host->driver->hw_csr_reg(host, 3, 0, 0);
265                 else
266                         ret = host->csr.channels_available_lo;
267
268                 *(buf++) = cpu_to_be32(ret);
269                 out;
270
271                 /* address gap to end - fall through to default */
272         default:
273                 return RCODE_ADDRESS_ERROR;
274         }
275
276         return RCODE_COMPLETE;
277 }
278
279 static int write_regs(struct hpsb_host *host, int nodeid, int destid,
280                       quadlet_t *data, u64 addr, unsigned int length, u16 flags)
281 {
282         int csraddr = addr - CSR_REGISTER_BASE;
283         
284         if ((csraddr | length) & 0x3)
285                 return RCODE_TYPE_ERROR;
286
287         length /= 4;
288
289         switch (csraddr) {
290         case CSR_STATE_CLEAR:
291                 /* FIXME FIXME FIXME */
292                 printk("doh, someone wants to mess with state clear\n");
293                 out;
294         case CSR_STATE_SET:
295                 printk("doh, someone wants to mess with state set\n");
296                 out;
297
298         case CSR_NODE_IDS:
299                 host->csr.node_ids &= NODE_MASK << 16;
300                 host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);
301                 host->node_id = host->csr.node_ids >> 16;
302                 host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6);
303                 out;
304
305         case CSR_RESET_START:
306                 /* FIXME - perform command reset */
307                 out;
308
309                 /* address gap */
310                 return RCODE_ADDRESS_ERROR;
311
312         case CSR_SPLIT_TIMEOUT_HI:
313                 host->csr.split_timeout_hi = 
314                         be32_to_cpu(*(data++)) & 0x00000007;
315                 out;
316         case CSR_SPLIT_TIMEOUT_LO:
317                 host->csr.split_timeout_lo = 
318                         be32_to_cpu(*(data++)) & 0xfff80000;
319                 out;
320
321                 /* address gap */
322                 return RCODE_ADDRESS_ERROR;
323
324         case CSR_CYCLE_TIME:
325                 /* should only be set by cycle start packet, automatically */
326                 host->csr.cycle_time = be32_to_cpu(*data);
327                 host->driver->devctl(host, SET_CYCLE_COUNTER,
328                                        be32_to_cpu(*(data++)));
329                 out;
330         case CSR_BUS_TIME:
331                 host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80;
332                 out;
333
334                 /* address gap */
335                 return RCODE_ADDRESS_ERROR;
336
337         case CSR_BUSY_TIMEOUT:
338                 /* not yet implemented */
339                 return RCODE_ADDRESS_ERROR;
340
341         case CSR_BUS_MANAGER_ID:
342         case CSR_BANDWIDTH_AVAILABLE:
343         case CSR_CHANNELS_AVAILABLE_HI:
344         case CSR_CHANNELS_AVAILABLE_LO:
345                 /* these are not writable, only lockable */
346                 return RCODE_TYPE_ERROR;
347
348                 /* address gap to end - fall through */
349         default:
350                 return RCODE_ADDRESS_ERROR;
351         }
352
353         return RCODE_COMPLETE;
354 }
355
356 #undef out
357
358
359 static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
360                      u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl)
361 {
362         int csraddr = addr - CSR_REGISTER_BASE;
363         unsigned long flags;
364         quadlet_t *regptr = NULL;
365
366         if (csraddr & 0x3)
367                 return RCODE_TYPE_ERROR;
368
369         if (csraddr < CSR_BUS_MANAGER_ID || csraddr > CSR_CHANNELS_AVAILABLE_LO
370             || extcode != EXTCODE_COMPARE_SWAP)
371                 goto unsupported_lockreq;
372
373         data = be32_to_cpu(data);
374         arg = be32_to_cpu(arg);
375
376         if (host->driver->hw_csr_reg) {
377                 quadlet_t old;
378
379                 old = host->driver->
380                         hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
381                                    data, arg);
382
383                 *store = cpu_to_be32(old);
384                 return RCODE_COMPLETE;
385         }
386
387         spin_lock_irqsave(&host->csr.lock, flags);
388
389         switch (csraddr) {
390         case CSR_BUS_MANAGER_ID:
391                 regptr = &host->csr.bus_manager_id;
392                 break;
393
394         case CSR_BANDWIDTH_AVAILABLE:
395                 regptr = &host->csr.bandwidth_available;
396                 break;
397
398         case CSR_CHANNELS_AVAILABLE_HI:
399                 regptr = &host->csr.channels_available_hi;
400                 break;
401
402         case CSR_CHANNELS_AVAILABLE_LO:
403                 regptr = &host->csr.channels_available_lo;
404                 break;
405         }
406
407         *store = cpu_to_be32(*regptr);
408         if (*regptr == arg) *regptr = data;
409         spin_unlock_irqrestore(&host->csr.lock, flags);
410
411         return RCODE_COMPLETE;
412
413  unsupported_lockreq:
414         switch (csraddr) {
415         case CSR_STATE_CLEAR:
416         case CSR_STATE_SET:
417         case CSR_RESET_START:
418         case CSR_NODE_IDS:
419         case CSR_SPLIT_TIMEOUT_HI:
420         case CSR_SPLIT_TIMEOUT_LO:
421         case CSR_CYCLE_TIME:
422         case CSR_BUS_TIME:
423         case CSR_BUS_MANAGER_ID:
424         case CSR_BANDWIDTH_AVAILABLE:
425         case CSR_CHANNELS_AVAILABLE_HI:
426         case CSR_CHANNELS_AVAILABLE_LO:
427                 return RCODE_TYPE_ERROR;
428
429         case CSR_BUSY_TIMEOUT:
430                 /* not yet implemented - fall through */
431         default:
432                 return RCODE_ADDRESS_ERROR;
433         }
434 }
435
436 static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
437                      quadlet_t *data, u64 addr, unsigned int length, u16 flags)
438 {
439         int csraddr = addr - CSR_REGISTER_BASE;
440
441         if (length > 512)
442                 return RCODE_TYPE_ERROR;
443
444         switch (csraddr) {
445         case CSR_FCP_COMMAND:
446                 highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length);
447                 break;
448         case CSR_FCP_RESPONSE:
449                 highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length);
450                 break;
451         default:
452                 return RCODE_TYPE_ERROR;
453         }
454
455         return RCODE_COMPLETE;
456 }
457
458
459 static struct hpsb_highlevel_ops csr_ops = {
460         .add_host =     add_host,
461         .host_reset =   host_reset,
462 };
463
464
465 static struct hpsb_address_ops map_ops = {
466         .read = read_maps,
467 };
468
469 static struct hpsb_address_ops fcp_ops = {
470         .write = write_fcp,
471 };
472
473 static struct hpsb_address_ops reg_ops = {
474         .read = read_regs,
475         .write = write_regs,
476         .lock = lock_regs,
477 };
478
479 static struct hpsb_highlevel *hl;
480
481 void init_csr(void)
482 {
483         hl = hpsb_register_highlevel("standard registers", &csr_ops);
484         if (hl == NULL) {
485                 HPSB_ERR("out of memory during ieee1394 initialization");
486                 return;
487         }
488
489         hpsb_register_addrspace(hl, &reg_ops, CSR_REGISTER_BASE,
490                                 CSR_REGISTER_BASE + CSR_CONFIG_ROM);
491         hpsb_register_addrspace(hl, &map_ops, 
492                                 CSR_REGISTER_BASE + CSR_CONFIG_ROM,
493                                 CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
494         if (fcp) {
495                 hpsb_register_addrspace(hl, &fcp_ops,
496                                 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
497                                 CSR_REGISTER_BASE + CSR_FCP_END);
498         }
499         hpsb_register_addrspace(hl, &map_ops,
500                                 CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
501                                 CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
502         hpsb_register_addrspace(hl, &map_ops,
503                                 CSR_REGISTER_BASE + CSR_SPEED_MAP,
504                                 CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
505 }
506
507 void cleanup_csr(void)
508 {
509         hpsb_unregister_highlevel(hl);
510 }