- Kai Germaschewski: ymfpci cleanups and resource leak fixes
[davej-history.git] / drivers / ieee1394 / csr.c
blob486ad1ad456b1e3c038fcfb0568ad40a7944478e
1 /*
2 * IEEE 1394 for Linux
4 * CSR implementation, iso/bus manager implementation.
6 * Copyright (C) 1999 Andreas E. Bombe
8 * This code is licensed under the GPL. See the file COPYING in the root
9 * directory of the kernel sources for details.
12 #include <linux/string.h>
14 #include "ieee1394_types.h"
15 #include "hosts.h"
16 #include "ieee1394.h"
17 #include "highlevel.h"
20 /* FIXME: this one won't work on little endian with big endian data */
21 static u16 csr_crc16(unsigned *data, int length)
23 int check=0, i;
24 int shift, sum, next=0;
26 for (i = length; i; i--) {
27 for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
28 sum = ((next >> 12) ^ (*data >> shift)) & 0xf;
29 next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
31 check = next & 0xffff;
32 data++;
35 return check;
38 static void host_reset(struct hpsb_host *host)
40 host->csr.state &= 0x300;
42 host->csr.bus_manager_id = 0x3f;
43 host->csr.bandwidth_available = 4915;
44 host->csr.channels_available_hi = ~0;
45 host->csr.channels_available_lo = ~0;
47 host->csr.node_ids = host->node_id << 16;
49 if (!host->is_root) {
50 /* clear cmstr bit */
51 host->csr.state &= ~0x100;
54 host->csr.topology_map[1] =
55 cpu_to_be32(be32_to_cpu(host->csr.topology_map[1]) + 1);
56 host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16
57 | host->selfid_count);
58 host->csr.topology_map[0] =
59 cpu_to_be32((host->selfid_count + 2) << 16
60 | csr_crc16(host->csr.topology_map + 1,
61 host->selfid_count + 2));
63 host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16
64 | csr_crc16(host->csr.speed_map+1,
65 0x3f1));
69 static void add_host(struct hpsb_host *host)
71 host->csr.lock = SPIN_LOCK_UNLOCKED;
73 host->csr.rom_size = host->template->get_rom(host, &host->csr.rom);
75 host->csr.state = 0;
76 host->csr.node_ids = 0;
77 host->csr.split_timeout_hi = 0;
78 host->csr.split_timeout_lo = 800 << 19;
79 host->csr.cycle_time = 0;
80 host->csr.bus_time = 0;
81 host->csr.bus_manager_id = 0x3f;
82 host->csr.bandwidth_available = 4915;
83 host->csr.channels_available_hi = ~0;
84 host->csr.channels_available_lo = ~0;
88 /* Read topology / speed maps and configuration ROM */
89 static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
90 u64 addr, unsigned int length)
92 int csraddr = addr - CSR_REGISTER_BASE;
93 const char *src;
95 if (csraddr < CSR_TOPOLOGY_MAP) {
96 if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
97 return RCODE_ADDRESS_ERROR;
99 src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;
100 } else if (csraddr < CSR_SPEED_MAP) {
101 src = ((char *)host->csr.topology_map) + csraddr
102 - CSR_TOPOLOGY_MAP;
103 } else {
104 src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;
107 memcpy(buffer, src, length);
108 return RCODE_COMPLETE;
112 #define out if (--length == 0) break
114 static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
115 u64 addr, unsigned int length)
117 int csraddr = addr - CSR_REGISTER_BASE;
118 int oldcycle;
120 if ((csraddr | length) & 0x3) {
121 return RCODE_TYPE_ERROR;
124 length /= 4;
126 switch (csraddr) {
127 case CSR_STATE_CLEAR:
128 *(buf++) = cpu_to_be32(host->csr.state);
129 out;
130 case CSR_STATE_SET:
131 *(buf++) = cpu_to_be32(host->csr.state);
132 out;
133 case CSR_NODE_IDS:
134 *(buf++) = cpu_to_be32(host->csr.node_ids);
135 out;
137 case CSR_RESET_START:
138 return RCODE_TYPE_ERROR;
140 /* address gap - handled by default below */
142 case CSR_SPLIT_TIMEOUT_HI:
143 *(buf++) = cpu_to_be32(host->csr.split_timeout_hi);
144 out;
145 case CSR_SPLIT_TIMEOUT_LO:
146 *(buf++) = cpu_to_be32(host->csr.split_timeout_lo);
147 out;
149 /* address gap */
150 return RCODE_ADDRESS_ERROR;
152 case CSR_CYCLE_TIME:
153 oldcycle = host->csr.cycle_time;
154 host->csr.cycle_time =
155 host->template->devctl(host, GET_CYCLE_COUNTER, 0);
157 if (oldcycle > host->csr.cycle_time) {
158 /* cycle time wrapped around */
159 host->csr.bus_time += 1 << 7;
161 *(buf++) = cpu_to_be32(host->csr.cycle_time);
162 out;
163 case CSR_BUS_TIME:
164 oldcycle = host->csr.cycle_time;
165 host->csr.cycle_time =
166 host->template->devctl(host, GET_CYCLE_COUNTER, 0);
168 if (oldcycle > host->csr.cycle_time) {
169 /* cycle time wrapped around */
170 host->csr.bus_time += (1 << 7);
172 *(buf++) = cpu_to_be32(host->csr.bus_time
173 | (host->csr.cycle_time >> 25));
174 out;
176 /* address gap */
177 return RCODE_ADDRESS_ERROR;
179 case CSR_BUSY_TIMEOUT:
180 /* not yet implemented */
181 return RCODE_ADDRESS_ERROR;
183 case CSR_BUS_MANAGER_ID:
184 *(buf++) = cpu_to_be32(host->csr.bus_manager_id);
185 out;
186 case CSR_BANDWIDTH_AVAILABLE:
187 *(buf++) = cpu_to_be32(host->csr.bandwidth_available);
188 out;
189 case CSR_CHANNELS_AVAILABLE_HI:
190 *(buf++) = cpu_to_be32(host->csr.channels_available_hi);
191 out;
192 case CSR_CHANNELS_AVAILABLE_LO:
193 *(buf++) = cpu_to_be32(host->csr.channels_available_lo);
194 out;
196 /* address gap to end - fall through to default */
197 default:
198 return RCODE_ADDRESS_ERROR;
201 return RCODE_COMPLETE;
204 static int write_regs(struct hpsb_host *host, int nodeid, quadlet_t *data,
205 u64 addr, unsigned int length)
207 int csraddr = addr - CSR_REGISTER_BASE;
209 if ((csraddr | length) & 0x3) {
210 return RCODE_TYPE_ERROR;
213 length /= 4;
215 switch (csraddr) {
216 case CSR_STATE_CLEAR:
217 /* FIXME FIXME FIXME */
218 printk("doh, someone wants to mess with state clear\n");
219 out;
220 case CSR_STATE_SET:
221 printk("doh, someone wants to mess with state set\n");
222 out;
224 case CSR_NODE_IDS:
225 host->csr.node_ids &= NODE_MASK << 16;
226 host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);
227 host->node_id = host->csr.node_ids >> 16;
228 host->template->devctl(host, SET_BUS_ID, host->node_id >> 6);
229 out;
231 case CSR_RESET_START:
232 /* FIXME - perform command reset */
233 out;
235 /* address gap */
236 return RCODE_ADDRESS_ERROR;
238 case CSR_SPLIT_TIMEOUT_HI:
239 host->csr.split_timeout_hi =
240 be32_to_cpu(*(data++)) & 0x00000007;
241 out;
242 case CSR_SPLIT_TIMEOUT_LO:
243 host->csr.split_timeout_lo =
244 be32_to_cpu(*(data++)) & 0xfff80000;
245 out;
247 /* address gap */
248 return RCODE_ADDRESS_ERROR;
250 case CSR_CYCLE_TIME:
251 /* should only be set by cycle start packet, automatically */
252 host->csr.cycle_time = be32_to_cpu(*data);
253 host->template->devctl(host, SET_CYCLE_COUNTER,
254 be32_to_cpu(*(data++)));
255 out;
256 case CSR_BUS_TIME:
257 host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80;
258 out;
260 /* address gap */
261 return RCODE_ADDRESS_ERROR;
263 case CSR_BUSY_TIMEOUT:
264 /* not yet implemented */
265 return RCODE_ADDRESS_ERROR;
267 case CSR_BUS_MANAGER_ID:
268 case CSR_BANDWIDTH_AVAILABLE:
269 case CSR_CHANNELS_AVAILABLE_HI:
270 case CSR_CHANNELS_AVAILABLE_LO:
271 /* these are not writable, only lockable */
272 return RCODE_TYPE_ERROR;
274 /* address gap to end - fall through */
275 default:
276 return RCODE_ADDRESS_ERROR;
279 return RCODE_COMPLETE;
282 #undef out
285 /* helper function for lock_regs */
286 inline static void compare_swap(quadlet_t *old, quadlet_t data, quadlet_t arg)
288 if (*old == be32_to_cpu(arg)) {
289 *old = be32_to_cpu(data);
293 static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
294 u64 addr, quadlet_t data, quadlet_t arg, int extcode)
296 int csraddr = addr - CSR_REGISTER_BASE;
297 unsigned long flags;
299 if (csraddr & 0x3) {
300 return RCODE_TYPE_ERROR;
303 if ((csraddr >= CSR_BUS_MANAGER_ID)
304 && (csraddr <= CSR_CHANNELS_AVAILABLE_LO)) {
305 if (extcode == EXTCODE_COMPARE_SWAP) {
306 spin_lock_irqsave(&host->csr.lock, flags);
308 switch (csraddr) {
309 case CSR_BUS_MANAGER_ID:
310 *store = cpu_to_be32(host->csr.bus_manager_id);
311 compare_swap(&host->csr.bus_manager_id,
312 data, arg);
313 break;
315 case CSR_BANDWIDTH_AVAILABLE:
316 *store = cpu_to_be32(host->
317 csr.bandwidth_available);
318 compare_swap(&host->csr.bandwidth_available,
319 data, arg);
320 break;
322 case CSR_CHANNELS_AVAILABLE_HI:
323 *store = cpu_to_be32(host->
324 csr.channels_available_hi);
325 compare_swap(&host->csr.channels_available_hi,
326 data, arg);
327 break;
329 case CSR_CHANNELS_AVAILABLE_LO:
330 *store = cpu_to_be32(host->
331 csr.channels_available_lo);
332 compare_swap(&host->csr.channels_available_lo,
333 data, arg);
334 break;
337 spin_unlock_irqrestore(&host->csr.lock, flags);
338 return RCODE_COMPLETE;
339 } else {
340 return RCODE_TYPE_ERROR;
344 /* no locking for anything else yet */
345 switch (csraddr) {
346 case CSR_STATE_CLEAR:
347 case CSR_STATE_SET:
348 case CSR_RESET_START:
349 case CSR_NODE_IDS:
350 case CSR_SPLIT_TIMEOUT_HI:
351 case CSR_SPLIT_TIMEOUT_LO:
352 case CSR_CYCLE_TIME:
353 case CSR_BUS_TIME:
354 return RCODE_TYPE_ERROR;
356 case CSR_BUSY_TIMEOUT:
357 /* not yet implemented - fall through */
358 default:
359 return RCODE_ADDRESS_ERROR;
363 static int write_fcp(struct hpsb_host *host, int nodeid, quadlet_t *data,
364 u64 addr, unsigned int length)
366 int csraddr = addr - CSR_REGISTER_BASE;
368 if (length > 512) {
369 return RCODE_TYPE_ERROR;
372 switch (csraddr) {
373 case CSR_FCP_COMMAND:
374 highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length);
375 break;
376 case CSR_FCP_RESPONSE:
377 highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length);
378 break;
379 default:
380 return RCODE_TYPE_ERROR;
383 return RCODE_COMPLETE;
387 struct hpsb_highlevel_ops csr_ops = {
388 add_host: add_host,
389 host_reset: host_reset,
393 struct hpsb_address_ops map_ops = {
394 read: read_maps,
397 struct hpsb_address_ops fcp_ops = {
398 write: write_fcp,
401 struct hpsb_address_ops reg_ops = {
402 read: read_regs,
403 write: write_regs,
404 lock: lock_regs,
408 void init_csr(void)
410 struct hpsb_highlevel *hl;
412 hl = hpsb_register_highlevel("standard registers", &csr_ops);
413 if (hl == NULL) {
414 HPSB_ERR("out of memory during ieee1394 initialization");
415 return;
418 hpsb_register_addrspace(hl, &reg_ops, CSR_REGISTER_BASE,
419 CSR_REGISTER_BASE + CSR_CONFIG_ROM);
420 hpsb_register_addrspace(hl, &map_ops,
421 CSR_REGISTER_BASE + CSR_CONFIG_ROM,
422 CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
423 hpsb_register_addrspace(hl, &fcp_ops,
424 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
425 CSR_REGISTER_BASE + CSR_FCP_END);
426 hpsb_register_addrspace(hl, &map_ops,
427 CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
428 CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
429 hpsb_register_addrspace(hl, &map_ops,
430 CSR_REGISTER_BASE + CSR_SPEED_MAP,
431 CSR_REGISTER_BASE + CSR_SPEED_MAP_END);