blob: 571ea68c0cf2fe446d0508768a6460d7ca5036b6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * IEEE 1394 for Linux
3 *
4 * Raw interface to the bus
5 *
6 * Copyright (C) 1999, 2000 Andreas E. Bombe
7 * 2001, 2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
8 * 2002 Christian Toegel <christian.toegel@gmx.at>
9 *
10 * This code is licensed under the GPL. See the file COPYING in the root
11 * directory of the kernel sources for details.
12 *
13 *
14 * Contributions:
15 *
16 * Manfred Weihs <weihs@ict.tuwien.ac.at>
17 * configuration ROM manipulation
18 * address range mapping
19 * adaptation for new (transparent) loopback mechanism
20 * sending of arbitrary async packets
21 * Christian Toegel <christian.toegel@gmx.at>
22 * address range mapping
23 * lock64 request
24 * transmit physical packet
25 * busreset notification control (switch on/off)
26 * busreset with selection of type (short/long)
27 * request_reply
28 */
29
30#include <linux/kernel.h>
31#include <linux/list.h>
32#include <linux/string.h>
33#include <linux/slab.h>
34#include <linux/fs.h>
35#include <linux/poll.h>
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/smp_lock.h>
39#include <linux/interrupt.h>
40#include <linux/vmalloc.h>
41#include <linux/cdev.h>
42#include <asm/uaccess.h>
43#include <asm/atomic.h>
Andi Kleen4bc32c42006-03-25 16:30:07 +010044#include <linux/compat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include "csr1212.h"
47#include "ieee1394.h"
48#include "ieee1394_types.h"
49#include "ieee1394_core.h"
50#include "nodemgr.h"
51#include "hosts.h"
52#include "highlevel.h"
53#include "iso.h"
54#include "ieee1394_transactions.h"
55#include "raw1394.h"
56#include "raw1394-private.h"
57
58#define int2ptr(x) ((void __user *)(unsigned long)x)
59#define ptr2int(x) ((u64)(unsigned long)(void __user *)x)
60
61#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
62#define RAW1394_DEBUG
63#endif
64
65#ifdef RAW1394_DEBUG
66#define DBGMSG(fmt, args...) \
67printk(KERN_INFO "raw1394:" fmt "\n" , ## args)
68#else
69#define DBGMSG(fmt, args...)
70#endif
71
72static LIST_HEAD(host_info_list);
73static int host_count;
74static DEFINE_SPINLOCK(host_info_lock);
75static atomic_t internal_generation = ATOMIC_INIT(0);
76
77static atomic_t iso_buffer_size;
78static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */
79
80static struct hpsb_highlevel raw1394_highlevel;
81
82static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
83 u64 addr, size_t length, u16 flags);
84static int arm_write(struct hpsb_host *host, int nodeid, int destid,
85 quadlet_t * data, u64 addr, size_t length, u16 flags);
86static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
87 u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
88 u16 flags);
89static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
90 u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
91 u16 flags);
92static struct hpsb_address_ops arm_ops = {
93 .read = arm_read,
94 .write = arm_write,
95 .lock = arm_lock,
96 .lock64 = arm_lock64,
97};
98
99static void queue_complete_cb(struct pending_request *req);
100
Al Virodd0fc662005-10-07 07:46:04 +0100101static struct pending_request *__alloc_pending_request(gfp_t flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102{
103 struct pending_request *req;
104
Stefan Richter85511582005-11-07 06:31:45 -0500105 req = kzalloc(sizeof(*req), flags);
106 if (req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 INIT_LIST_HEAD(&req->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109 return req;
110}
111
112static inline struct pending_request *alloc_pending_request(void)
113{
114 return __alloc_pending_request(SLAB_KERNEL);
115}
116
117static void free_pending_request(struct pending_request *req)
118{
119 if (req->ibs) {
120 if (atomic_dec_and_test(&req->ibs->refcount)) {
121 atomic_sub(req->ibs->data_size, &iso_buffer_size);
122 kfree(req->ibs);
123 }
124 } else if (req->free_data) {
125 kfree(req->data);
126 }
127 hpsb_free_packet(req->packet);
128 kfree(req);
129}
130
131/* fi->reqlists_lock must be taken */
132static void __queue_complete_req(struct pending_request *req)
133{
134 struct file_info *fi = req->file_info;
Akinobu Mita179e0912006-06-26 00:24:41 -0700135 list_move_tail(&req->list, &fi->req_complete);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137 up(&fi->complete_sem);
138 wake_up_interruptible(&fi->poll_wait_complete);
139}
140
141static void queue_complete_req(struct pending_request *req)
142{
143 unsigned long flags;
144 struct file_info *fi = req->file_info;
145
146 spin_lock_irqsave(&fi->reqlists_lock, flags);
147 __queue_complete_req(req);
148 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
149}
150
151static void queue_complete_cb(struct pending_request *req)
152{
153 struct hpsb_packet *packet = req->packet;
154 int rcode = (packet->header[1] >> 12) & 0xf;
155
156 switch (packet->ack_code) {
157 case ACKX_NONE:
158 case ACKX_SEND_ERROR:
159 req->req.error = RAW1394_ERROR_SEND_ERROR;
160 break;
161 case ACKX_ABORTED:
162 req->req.error = RAW1394_ERROR_ABORTED;
163 break;
164 case ACKX_TIMEOUT:
165 req->req.error = RAW1394_ERROR_TIMEOUT;
166 break;
167 default:
168 req->req.error = (packet->ack_code << 16) | rcode;
169 break;
170 }
171
172 if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
173 req->req.length = 0;
174 }
175
176 if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
177 (req->req.type == RAW1394_REQ_ASYNC_WRITE) ||
178 (req->req.type == RAW1394_REQ_ASYNC_STREAM) ||
179 (req->req.type == RAW1394_REQ_LOCK) ||
180 (req->req.type == RAW1394_REQ_LOCK64))
181 hpsb_free_tlabel(packet);
182
183 queue_complete_req(req);
184}
185
186static void add_host(struct hpsb_host *host)
187{
188 struct host_info *hi;
189 unsigned long flags;
190
Stefan Richter85511582005-11-07 06:31:45 -0500191 hi = kmalloc(sizeof(*hi), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
Stefan Richter85511582005-11-07 06:31:45 -0500193 if (hi) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 INIT_LIST_HEAD(&hi->list);
195 hi->host = host;
196 INIT_LIST_HEAD(&hi->file_info_list);
197
198 spin_lock_irqsave(&host_info_lock, flags);
199 list_add_tail(&hi->list, &host_info_list);
200 host_count++;
201 spin_unlock_irqrestore(&host_info_lock, flags);
202 }
203
204 atomic_inc(&internal_generation);
205}
206
207static struct host_info *find_host_info(struct hpsb_host *host)
208{
209 struct host_info *hi;
210
211 list_for_each_entry(hi, &host_info_list, list)
212 if (hi->host == host)
213 return hi;
214
215 return NULL;
216}
217
218static void remove_host(struct hpsb_host *host)
219{
220 struct host_info *hi;
221 unsigned long flags;
222
223 spin_lock_irqsave(&host_info_lock, flags);
224 hi = find_host_info(host);
225
226 if (hi != NULL) {
227 list_del(&hi->list);
228 host_count--;
229 /*
230 FIXME: address ranges should be removed
231 and fileinfo states should be initialized
232 (including setting generation to
233 internal-generation ...)
234 */
235 }
236 spin_unlock_irqrestore(&host_info_lock, flags);
237
238 if (hi == NULL) {
239 printk(KERN_ERR "raw1394: attempt to remove unknown host "
240 "0x%p\n", host);
241 return;
242 }
243
244 kfree(hi);
245
246 atomic_inc(&internal_generation);
247}
248
249static void host_reset(struct hpsb_host *host)
250{
251 unsigned long flags;
252 struct host_info *hi;
253 struct file_info *fi;
254 struct pending_request *req;
255
256 spin_lock_irqsave(&host_info_lock, flags);
257 hi = find_host_info(host);
258
259 if (hi != NULL) {
260 list_for_each_entry(fi, &hi->file_info_list, list) {
261 if (fi->notification == RAW1394_NOTIFY_ON) {
262 req = __alloc_pending_request(SLAB_ATOMIC);
263
264 if (req != NULL) {
265 req->file_info = fi;
266 req->req.type = RAW1394_REQ_BUS_RESET;
267 req->req.generation =
268 get_hpsb_generation(host);
269 req->req.misc = (host->node_id << 16)
270 | host->node_count;
271 if (fi->protocol_version > 3) {
272 req->req.misc |=
273 (NODEID_TO_NODE
274 (host->irm_id)
275 << 8);
276 }
277
278 queue_complete_req(req);
279 }
280 }
281 }
282 }
283 spin_unlock_irqrestore(&host_info_lock, flags);
284}
285
286static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
287 size_t length)
288{
289 unsigned long flags;
290 struct host_info *hi;
291 struct file_info *fi;
292 struct pending_request *req, *req_next;
293 struct iso_block_store *ibs = NULL;
294 LIST_HEAD(reqs);
295
296 if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
297 HPSB_INFO("dropped iso packet");
298 return;
299 }
300
301 spin_lock_irqsave(&host_info_lock, flags);
302 hi = find_host_info(host);
303
304 if (hi != NULL) {
305 list_for_each_entry(fi, &hi->file_info_list, list) {
306 if (!(fi->listen_channels & (1ULL << channel)))
307 continue;
308
309 req = __alloc_pending_request(SLAB_ATOMIC);
310 if (!req)
311 break;
312
313 if (!ibs) {
Stefan Richter85511582005-11-07 06:31:45 -0500314 ibs = kmalloc(sizeof(*ibs) + length,
315 SLAB_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 if (!ibs) {
317 kfree(req);
318 break;
319 }
320
321 atomic_add(length, &iso_buffer_size);
322 atomic_set(&ibs->refcount, 0);
323 ibs->data_size = length;
324 memcpy(ibs->data, data, length);
325 }
326
327 atomic_inc(&ibs->refcount);
328
329 req->file_info = fi;
330 req->ibs = ibs;
331 req->data = ibs->data;
332 req->req.type = RAW1394_REQ_ISO_RECEIVE;
333 req->req.generation = get_hpsb_generation(host);
334 req->req.misc = 0;
335 req->req.recvb = ptr2int(fi->iso_buffer);
336 req->req.length = min(length, fi->iso_buffer_length);
337
338 list_add_tail(&req->list, &reqs);
339 }
340 }
341 spin_unlock_irqrestore(&host_info_lock, flags);
342
343 list_for_each_entry_safe(req, req_next, &reqs, list)
344 queue_complete_req(req);
345}
346
347static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
348 int cts, u8 * data, size_t length)
349{
350 unsigned long flags;
351 struct host_info *hi;
352 struct file_info *fi;
353 struct pending_request *req, *req_next;
354 struct iso_block_store *ibs = NULL;
355 LIST_HEAD(reqs);
356
357 if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
358 HPSB_INFO("dropped fcp request");
359 return;
360 }
361
362 spin_lock_irqsave(&host_info_lock, flags);
363 hi = find_host_info(host);
364
365 if (hi != NULL) {
366 list_for_each_entry(fi, &hi->file_info_list, list) {
367 if (!fi->fcp_buffer)
368 continue;
369
370 req = __alloc_pending_request(SLAB_ATOMIC);
371 if (!req)
372 break;
373
374 if (!ibs) {
Stefan Richter85511582005-11-07 06:31:45 -0500375 ibs = kmalloc(sizeof(*ibs) + length,
376 SLAB_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 if (!ibs) {
378 kfree(req);
379 break;
380 }
381
382 atomic_add(length, &iso_buffer_size);
383 atomic_set(&ibs->refcount, 0);
384 ibs->data_size = length;
385 memcpy(ibs->data, data, length);
386 }
387
388 atomic_inc(&ibs->refcount);
389
390 req->file_info = fi;
391 req->ibs = ibs;
392 req->data = ibs->data;
393 req->req.type = RAW1394_REQ_FCP_REQUEST;
394 req->req.generation = get_hpsb_generation(host);
395 req->req.misc = nodeid | (direction << 16);
396 req->req.recvb = ptr2int(fi->fcp_buffer);
397 req->req.length = length;
398
399 list_add_tail(&req->list, &reqs);
400 }
401 }
402 spin_unlock_irqrestore(&host_info_lock, flags);
403
404 list_for_each_entry_safe(req, req_next, &reqs, list)
405 queue_complete_req(req);
406}
407
Andi Kleen4bc32c42006-03-25 16:30:07 +0100408#ifdef CONFIG_COMPAT
409struct compat_raw1394_req {
Ben Collins75970282006-06-12 18:12:10 -0400410 __u32 type;
411 __s32 error;
412 __u32 misc;
Andi Kleen4bc32c42006-03-25 16:30:07 +0100413
Ben Collins75970282006-06-12 18:12:10 -0400414 __u32 generation;
415 __u32 length;
Andi Kleen4bc32c42006-03-25 16:30:07 +0100416
Ben Collins75970282006-06-12 18:12:10 -0400417 __u64 address;
Andi Kleen4bc32c42006-03-25 16:30:07 +0100418
Ben Collins75970282006-06-12 18:12:10 -0400419 __u64 tag;
Andi Kleen4bc32c42006-03-25 16:30:07 +0100420
Ben Collins75970282006-06-12 18:12:10 -0400421 __u64 sendb;
422 __u64 recvb;
423} __attribute__((packed));
Andi Kleen4bc32c42006-03-25 16:30:07 +0100424
425static const char __user *raw1394_compat_write(const char __user *buf)
426{
Ben Collins75970282006-06-12 18:12:10 -0400427 struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
Andi Kleen4bc32c42006-03-25 16:30:07 +0100428 struct raw1394_request __user *r;
429 r = compat_alloc_user_space(sizeof(struct raw1394_request));
430
431#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))
432
433 if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||
Ben Collins75970282006-06-12 18:12:10 -0400434 C(address) ||
435 C(tag) ||
436 C(sendb) ||
437 C(recvb))
Andi Kleen4bc32c42006-03-25 16:30:07 +0100438 return ERR_PTR(-EFAULT);
439 return (const char __user *)r;
440}
441#undef C
442
443#define P(x) __put_user(r->x, &cr->x)
444
Ben Collins75970282006-06-12 18:12:10 -0400445static int
Andi Kleen4bc32c42006-03-25 16:30:07 +0100446raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
447{
Ben Collins75970282006-06-12 18:12:10 -0400448 struct compat_raw1394_req __user *cr = (typeof(cr)) r;
449 if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
Andi Kleen4bc32c42006-03-25 16:30:07 +0100450 P(type) ||
451 P(error) ||
452 P(misc) ||
453 P(generation) ||
454 P(length) ||
455 P(address) ||
456 P(tag) ||
457 P(sendb) ||
458 P(recvb))
459 return -EFAULT;
460 return sizeof(struct compat_raw1394_req);
461}
462#undef P
463
464#endif
465
466
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467static ssize_t raw1394_read(struct file *file, char __user * buffer,
468 size_t count, loff_t * offset_is_ignored)
469{
Andy Wingo4a9949d2005-10-19 21:23:46 -0700470 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 struct file_info *fi = (struct file_info *)file->private_data;
472 struct list_head *lh;
473 struct pending_request *req;
474 ssize_t ret;
475
Andi Kleen4bc32c42006-03-25 16:30:07 +0100476#ifdef CONFIG_COMPAT
477 if (count == sizeof(struct compat_raw1394_req)) {
478 /* ok */
479 } else
480#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if (count != sizeof(struct raw1394_request)) {
482 return -EINVAL;
483 }
484
485 if (!access_ok(VERIFY_WRITE, buffer, count)) {
486 return -EFAULT;
487 }
488
489 if (file->f_flags & O_NONBLOCK) {
490 if (down_trylock(&fi->complete_sem)) {
491 return -EAGAIN;
492 }
493 } else {
494 if (down_interruptible(&fi->complete_sem)) {
495 return -ERESTARTSYS;
496 }
497 }
498
Andy Wingo4a9949d2005-10-19 21:23:46 -0700499 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 lh = fi->req_complete.next;
501 list_del(lh);
Andy Wingo4a9949d2005-10-19 21:23:46 -0700502 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504 req = list_entry(lh, struct pending_request, list);
505
506 if (req->req.length) {
507 if (copy_to_user(int2ptr(req->req.recvb), req->data,
508 req->req.length)) {
509 req->req.error = RAW1394_ERROR_MEMFAULT;
510 }
511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Andi Kleen4bc32c42006-03-25 16:30:07 +0100513#ifdef CONFIG_COMPAT
Ben Collins75970282006-06-12 18:12:10 -0400514 if (count == sizeof(struct compat_raw1394_req) &&
515 sizeof(struct compat_raw1394_req) !=
516 sizeof(struct raw1394_request)) {
Andi Kleen4bc32c42006-03-25 16:30:07 +0100517 ret = raw1394_compat_read(buffer, &req->req);
Ben Collins75970282006-06-12 18:12:10 -0400518 } else
Andi Kleen4bc32c42006-03-25 16:30:07 +0100519#endif
520 {
521 if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
522 ret = -EFAULT;
523 goto out;
Ben Collins75970282006-06-12 18:12:10 -0400524 }
Andi Kleen4bc32c42006-03-25 16:30:07 +0100525 ret = (ssize_t) sizeof(struct raw1394_request);
526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 out:
528 free_pending_request(req);
529 return ret;
530}
531
532static int state_opened(struct file_info *fi, struct pending_request *req)
533{
534 if (req->req.type == RAW1394_REQ_INITIALIZE) {
535 switch (req->req.misc) {
536 case RAW1394_KERNELAPI_VERSION:
537 case 3:
538 fi->state = initialized;
539 fi->protocol_version = req->req.misc;
540 req->req.error = RAW1394_ERROR_NONE;
541 req->req.generation = atomic_read(&internal_generation);
542 break;
543
544 default:
545 req->req.error = RAW1394_ERROR_COMPAT;
546 req->req.misc = RAW1394_KERNELAPI_VERSION;
547 }
548 } else {
549 req->req.error = RAW1394_ERROR_STATE_ORDER;
550 }
551
552 req->req.length = 0;
553 queue_complete_req(req);
554 return sizeof(struct raw1394_request);
555}
556
557static int state_initialized(struct file_info *fi, struct pending_request *req)
558{
Andy Wingo4a9949d2005-10-19 21:23:46 -0700559 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 struct host_info *hi;
561 struct raw1394_khost_list *khl;
562
563 if (req->req.generation != atomic_read(&internal_generation)) {
564 req->req.error = RAW1394_ERROR_GENERATION;
565 req->req.generation = atomic_read(&internal_generation);
566 req->req.length = 0;
567 queue_complete_req(req);
568 return sizeof(struct raw1394_request);
569 }
570
571 switch (req->req.type) {
572 case RAW1394_REQ_LIST_CARDS:
Andy Wingo4a9949d2005-10-19 21:23:46 -0700573 spin_lock_irqsave(&host_info_lock, flags);
Stefan Richter85511582005-11-07 06:31:45 -0500574 khl = kmalloc(sizeof(*khl) * host_count, SLAB_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Stefan Richter85511582005-11-07 06:31:45 -0500576 if (khl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 req->req.misc = host_count;
578 req->data = (quadlet_t *) khl;
579
580 list_for_each_entry(hi, &host_info_list, list) {
581 khl->nodes = hi->host->node_count;
582 strcpy(khl->name, hi->host->driver->name);
583 khl++;
584 }
585 }
Andy Wingo4a9949d2005-10-19 21:23:46 -0700586 spin_unlock_irqrestore(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Stefan Richter85511582005-11-07 06:31:45 -0500588 if (khl) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 req->req.error = RAW1394_ERROR_NONE;
590 req->req.length = min(req->req.length,
591 (u32) (sizeof
592 (struct raw1394_khost_list)
593 * req->req.misc));
594 req->free_data = 1;
595 } else {
596 return -ENOMEM;
597 }
598 break;
599
600 case RAW1394_REQ_SET_CARD:
Andy Wingo4a9949d2005-10-19 21:23:46 -0700601 spin_lock_irqsave(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 if (req->req.misc < host_count) {
603 list_for_each_entry(hi, &host_info_list, list) {
604 if (!req->req.misc--)
605 break;
606 }
607 get_device(&hi->host->device); // XXX Need to handle failure case
608 list_add_tail(&fi->list, &hi->file_info_list);
609 fi->host = hi->host;
610 fi->state = connected;
611
612 req->req.error = RAW1394_ERROR_NONE;
613 req->req.generation = get_hpsb_generation(fi->host);
614 req->req.misc = (fi->host->node_id << 16)
615 | fi->host->node_count;
616 if (fi->protocol_version > 3) {
617 req->req.misc |=
618 NODEID_TO_NODE(fi->host->irm_id) << 8;
619 }
620 } else {
621 req->req.error = RAW1394_ERROR_INVALID_ARG;
622 }
Andy Wingo4a9949d2005-10-19 21:23:46 -0700623 spin_unlock_irqrestore(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
625 req->req.length = 0;
626 break;
627
628 default:
629 req->req.error = RAW1394_ERROR_STATE_ORDER;
630 req->req.length = 0;
631 break;
632 }
633
634 queue_complete_req(req);
635 return sizeof(struct raw1394_request);
636}
637
638static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
639{
640 int channel = req->req.misc;
641
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 if ((channel > 63) || (channel < -64)) {
643 req->req.error = RAW1394_ERROR_INVALID_ARG;
644 } else if (channel >= 0) {
645 /* allocate channel req.misc */
646 if (fi->listen_channels & (1ULL << channel)) {
647 req->req.error = RAW1394_ERROR_ALREADY;
648 } else {
649 if (hpsb_listen_channel
650 (&raw1394_highlevel, fi->host, channel)) {
651 req->req.error = RAW1394_ERROR_ALREADY;
652 } else {
653 fi->listen_channels |= 1ULL << channel;
654 fi->iso_buffer = int2ptr(req->req.recvb);
655 fi->iso_buffer_length = req->req.length;
656 }
657 }
658 } else {
659 /* deallocate channel (one's complement neg) req.misc */
660 channel = ~channel;
661
662 if (fi->listen_channels & (1ULL << channel)) {
663 hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
664 channel);
665 fi->listen_channels &= ~(1ULL << channel);
666 } else {
667 req->req.error = RAW1394_ERROR_INVALID_ARG;
668 }
669 }
670
671 req->req.length = 0;
672 queue_complete_req(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673}
674
675static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
676{
677 if (req->req.misc) {
678 if (fi->fcp_buffer) {
679 req->req.error = RAW1394_ERROR_ALREADY;
680 } else {
681 fi->fcp_buffer = int2ptr(req->req.recvb);
682 }
683 } else {
684 if (!fi->fcp_buffer) {
685 req->req.error = RAW1394_ERROR_ALREADY;
686 } else {
687 fi->fcp_buffer = NULL;
688 }
689 }
690
691 req->req.length = 0;
692 queue_complete_req(req);
693}
694
695static int handle_async_request(struct file_info *fi,
696 struct pending_request *req, int node)
697{
Andy Wingo4a9949d2005-10-19 21:23:46 -0700698 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 struct hpsb_packet *packet = NULL;
700 u64 addr = req->req.address & 0xffffffffffffULL;
701
702 switch (req->req.type) {
703 case RAW1394_REQ_ASYNC_READ:
704 DBGMSG("read_request called");
705 packet =
706 hpsb_make_readpacket(fi->host, node, addr, req->req.length);
707
708 if (!packet)
709 return -ENOMEM;
710
711 if (req->req.length == 4)
712 req->data = &packet->header[3];
713 else
714 req->data = packet->data;
715
716 break;
717
718 case RAW1394_REQ_ASYNC_WRITE:
719 DBGMSG("write_request called");
720
721 packet = hpsb_make_writepacket(fi->host, node, addr, NULL,
722 req->req.length);
723 if (!packet)
724 return -ENOMEM;
725
726 if (req->req.length == 4) {
727 if (copy_from_user
728 (&packet->header[3], int2ptr(req->req.sendb),
729 req->req.length))
730 req->req.error = RAW1394_ERROR_MEMFAULT;
731 } else {
732 if (copy_from_user
733 (packet->data, int2ptr(req->req.sendb),
734 req->req.length))
735 req->req.error = RAW1394_ERROR_MEMFAULT;
736 }
737
738 req->req.length = 0;
739 break;
740
741 case RAW1394_REQ_ASYNC_STREAM:
742 DBGMSG("stream_request called");
743
744 packet =
745 hpsb_make_streampacket(fi->host, NULL, req->req.length,
746 node & 0x3f /*channel */ ,
747 (req->req.misc >> 16) & 0x3,
748 req->req.misc & 0xf);
749 if (!packet)
750 return -ENOMEM;
751
752 if (copy_from_user(packet->data, int2ptr(req->req.sendb),
753 req->req.length))
754 req->req.error = RAW1394_ERROR_MEMFAULT;
755
756 req->req.length = 0;
757 break;
758
759 case RAW1394_REQ_LOCK:
760 DBGMSG("lock_request called");
761 if ((req->req.misc == EXTCODE_FETCH_ADD)
762 || (req->req.misc == EXTCODE_LITTLE_ADD)) {
763 if (req->req.length != 4) {
764 req->req.error = RAW1394_ERROR_INVALID_ARG;
765 break;
766 }
767 } else {
768 if (req->req.length != 8) {
769 req->req.error = RAW1394_ERROR_INVALID_ARG;
770 break;
771 }
772 }
773
774 packet = hpsb_make_lockpacket(fi->host, node, addr,
775 req->req.misc, NULL, 0);
776 if (!packet)
777 return -ENOMEM;
778
779 if (copy_from_user(packet->data, int2ptr(req->req.sendb),
780 req->req.length)) {
781 req->req.error = RAW1394_ERROR_MEMFAULT;
782 break;
783 }
784
785 req->data = packet->data;
786 req->req.length = 4;
787 break;
788
789 case RAW1394_REQ_LOCK64:
790 DBGMSG("lock64_request called");
791 if ((req->req.misc == EXTCODE_FETCH_ADD)
792 || (req->req.misc == EXTCODE_LITTLE_ADD)) {
793 if (req->req.length != 8) {
794 req->req.error = RAW1394_ERROR_INVALID_ARG;
795 break;
796 }
797 } else {
798 if (req->req.length != 16) {
799 req->req.error = RAW1394_ERROR_INVALID_ARG;
800 break;
801 }
802 }
803 packet = hpsb_make_lock64packet(fi->host, node, addr,
804 req->req.misc, NULL, 0);
805 if (!packet)
806 return -ENOMEM;
807
808 if (copy_from_user(packet->data, int2ptr(req->req.sendb),
809 req->req.length)) {
810 req->req.error = RAW1394_ERROR_MEMFAULT;
811 break;
812 }
813
814 req->data = packet->data;
815 req->req.length = 8;
816 break;
817
818 default:
819 req->req.error = RAW1394_ERROR_STATE_ORDER;
820 }
821
822 req->packet = packet;
823
824 if (req->req.error) {
825 req->req.length = 0;
826 queue_complete_req(req);
827 return sizeof(struct raw1394_request);
828 }
829
830 hpsb_set_packet_complete_task(packet,
831 (void (*)(void *))queue_complete_cb, req);
832
Andy Wingo4a9949d2005-10-19 21:23:46 -0700833 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 list_add_tail(&req->list, &fi->req_pending);
Andy Wingo4a9949d2005-10-19 21:23:46 -0700835 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
837 packet->generation = req->req.generation;
838
839 if (hpsb_send_packet(packet) < 0) {
840 req->req.error = RAW1394_ERROR_SEND_ERROR;
841 req->req.length = 0;
842 hpsb_free_tlabel(packet);
843 queue_complete_req(req);
844 }
845 return sizeof(struct raw1394_request);
846}
847
848static int handle_iso_send(struct file_info *fi, struct pending_request *req,
849 int channel)
850{
Andy Wingo4a9949d2005-10-19 21:23:46 -0700851 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 struct hpsb_packet *packet;
853
854 packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
855 (req->req.misc >> 16) & 0x3,
856 req->req.misc & 0xf);
857 if (!packet)
858 return -ENOMEM;
859
860 packet->speed_code = req->req.address & 0x3;
861
862 req->packet = packet;
863
864 if (copy_from_user(packet->data, int2ptr(req->req.sendb),
865 req->req.length)) {
866 req->req.error = RAW1394_ERROR_MEMFAULT;
867 req->req.length = 0;
868 queue_complete_req(req);
869 return sizeof(struct raw1394_request);
870 }
871
872 req->req.length = 0;
873 hpsb_set_packet_complete_task(packet,
874 (void (*)(void *))queue_complete_req,
875 req);
876
Andy Wingo4a9949d2005-10-19 21:23:46 -0700877 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 list_add_tail(&req->list, &fi->req_pending);
Andy Wingo4a9949d2005-10-19 21:23:46 -0700879 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 /* Update the generation of the packet just before sending. */
882 packet->generation = req->req.generation;
883
884 if (hpsb_send_packet(packet) < 0) {
885 req->req.error = RAW1394_ERROR_SEND_ERROR;
886 queue_complete_req(req);
887 }
888
889 return sizeof(struct raw1394_request);
890}
891
892static int handle_async_send(struct file_info *fi, struct pending_request *req)
893{
Andy Wingo4a9949d2005-10-19 21:23:46 -0700894 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 struct hpsb_packet *packet;
896 int header_length = req->req.misc & 0xffff;
897 int expect_response = req->req.misc >> 16;
898
899 if ((header_length > req->req.length) || (header_length < 12)) {
900 req->req.error = RAW1394_ERROR_INVALID_ARG;
901 req->req.length = 0;
902 queue_complete_req(req);
903 return sizeof(struct raw1394_request);
904 }
905
906 packet = hpsb_alloc_packet(req->req.length - header_length);
907 req->packet = packet;
908 if (!packet)
909 return -ENOMEM;
910
911 if (copy_from_user(packet->header, int2ptr(req->req.sendb),
912 header_length)) {
913 req->req.error = RAW1394_ERROR_MEMFAULT;
914 req->req.length = 0;
915 queue_complete_req(req);
916 return sizeof(struct raw1394_request);
917 }
918
919 if (copy_from_user
920 (packet->data, int2ptr(req->req.sendb) + header_length,
921 packet->data_size)) {
922 req->req.error = RAW1394_ERROR_MEMFAULT;
923 req->req.length = 0;
924 queue_complete_req(req);
925 return sizeof(struct raw1394_request);
926 }
927
928 packet->type = hpsb_async;
929 packet->node_id = packet->header[0] >> 16;
930 packet->tcode = (packet->header[0] >> 4) & 0xf;
931 packet->tlabel = (packet->header[0] >> 10) & 0x3f;
932 packet->host = fi->host;
933 packet->expect_response = expect_response;
934 packet->header_size = header_length;
935 packet->data_size = req->req.length - header_length;
936
937 req->req.length = 0;
938 hpsb_set_packet_complete_task(packet,
939 (void (*)(void *))queue_complete_cb, req);
940
Andy Wingo4a9949d2005-10-19 21:23:46 -0700941 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 list_add_tail(&req->list, &fi->req_pending);
Andy Wingo4a9949d2005-10-19 21:23:46 -0700943 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
945 /* Update the generation of the packet just before sending. */
946 packet->generation = req->req.generation;
947
948 if (hpsb_send_packet(packet) < 0) {
949 req->req.error = RAW1394_ERROR_SEND_ERROR;
950 queue_complete_req(req);
951 }
952
953 return sizeof(struct raw1394_request);
954}
955
956static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
957 u64 addr, size_t length, u16 flags)
958{
Andy Wingo4a9949d2005-10-19 21:23:46 -0700959 unsigned long irqflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 struct pending_request *req;
961 struct host_info *hi;
962 struct file_info *fi = NULL;
963 struct list_head *entry;
964 struct arm_addr *arm_addr = NULL;
965 struct arm_request *arm_req = NULL;
966 struct arm_response *arm_resp = NULL;
967 int found = 0, size = 0, rcode = -1;
968 struct arm_request_response *arm_req_resp = NULL;
969
970 DBGMSG("arm_read called by node: %X"
971 "addr: %4.4x %8.8x length: %Zu", nodeid,
972 (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
973 length);
Andy Wingo4a9949d2005-10-19 21:23:46 -0700974 spin_lock_irqsave(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 hi = find_host_info(host); /* search address-entry */
976 if (hi != NULL) {
977 list_for_each_entry(fi, &hi->file_info_list, list) {
978 entry = fi->addr_list.next;
979 while (entry != &(fi->addr_list)) {
980 arm_addr =
981 list_entry(entry, struct arm_addr,
982 addr_list);
983 if (((arm_addr->start) <= (addr))
984 && ((arm_addr->end) >= (addr + length))) {
985 found = 1;
986 break;
987 }
988 entry = entry->next;
989 }
990 if (found) {
991 break;
992 }
993 }
994 }
995 rcode = -1;
996 if (!found) {
997 printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
998 " -> rcode_address_error\n");
Andy Wingo4a9949d2005-10-19 21:23:46 -0700999 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 return (RCODE_ADDRESS_ERROR);
1001 } else {
1002 DBGMSG("arm_read addr_entry FOUND");
1003 }
1004 if (arm_addr->rec_length < length) {
1005 DBGMSG("arm_read blocklength too big -> rcode_data_error");
1006 rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
1007 }
1008 if (rcode == -1) {
1009 if (arm_addr->access_rights & ARM_READ) {
1010 if (!(arm_addr->client_transactions & ARM_READ)) {
1011 memcpy(buffer,
1012 (arm_addr->addr_space_buffer) + (addr -
1013 (arm_addr->
1014 start)),
1015 length);
1016 DBGMSG("arm_read -> (rcode_complete)");
1017 rcode = RCODE_COMPLETE;
1018 }
1019 } else {
1020 rcode = RCODE_TYPE_ERROR; /* function not allowed */
1021 DBGMSG("arm_read -> rcode_type_error (access denied)");
1022 }
1023 }
1024 if (arm_addr->notification_options & ARM_READ) {
1025 DBGMSG("arm_read -> entering notification-section");
1026 req = __alloc_pending_request(SLAB_ATOMIC);
1027 if (!req) {
1028 DBGMSG("arm_read -> rcode_conflict_error");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001029 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1031 The request may be retried */
1032 }
1033 if (rcode == RCODE_COMPLETE) {
1034 size =
1035 sizeof(struct arm_request) +
1036 sizeof(struct arm_response) +
1037 length * sizeof(byte_t) +
1038 sizeof(struct arm_request_response);
1039 } else {
1040 size =
1041 sizeof(struct arm_request) +
1042 sizeof(struct arm_response) +
1043 sizeof(struct arm_request_response);
1044 }
1045 req->data = kmalloc(size, SLAB_ATOMIC);
1046 if (!(req->data)) {
1047 free_pending_request(req);
1048 DBGMSG("arm_read -> rcode_conflict_error");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001049 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1051 The request may be retried */
1052 }
1053 req->free_data = 1;
1054 req->file_info = fi;
1055 req->req.type = RAW1394_REQ_ARM;
1056 req->req.generation = get_hpsb_generation(host);
1057 req->req.misc =
1058 (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
1059 req->req.tag = arm_addr->arm_tag;
1060 req->req.recvb = arm_addr->recvb;
1061 req->req.length = size;
1062 arm_req_resp = (struct arm_request_response *)(req->data);
1063 arm_req = (struct arm_request *)((byte_t *) (req->data) +
1064 (sizeof
1065 (struct
1066 arm_request_response)));
1067 arm_resp =
1068 (struct arm_response *)((byte_t *) (arm_req) +
1069 (sizeof(struct arm_request)));
1070 arm_req->buffer = NULL;
1071 arm_resp->buffer = NULL;
1072 if (rcode == RCODE_COMPLETE) {
1073 byte_t *buf =
1074 (byte_t *) arm_resp + sizeof(struct arm_response);
1075 memcpy(buf,
1076 (arm_addr->addr_space_buffer) + (addr -
1077 (arm_addr->
1078 start)),
1079 length);
1080 arm_resp->buffer =
1081 int2ptr((arm_addr->recvb) +
1082 sizeof(struct arm_request_response) +
1083 sizeof(struct arm_request) +
1084 sizeof(struct arm_response));
1085 }
1086 arm_resp->buffer_length =
1087 (rcode == RCODE_COMPLETE) ? length : 0;
1088 arm_resp->response_code = rcode;
1089 arm_req->buffer_length = 0;
1090 arm_req->generation = req->req.generation;
1091 arm_req->extended_transaction_code = 0;
1092 arm_req->destination_offset = addr;
1093 arm_req->source_nodeid = nodeid;
1094 arm_req->destination_nodeid = host->node_id;
1095 arm_req->tlabel = (flags >> 10) & 0x3f;
1096 arm_req->tcode = (flags >> 4) & 0x0f;
1097 arm_req_resp->request = int2ptr((arm_addr->recvb) +
1098 sizeof(struct
1099 arm_request_response));
1100 arm_req_resp->response =
1101 int2ptr((arm_addr->recvb) +
1102 sizeof(struct arm_request_response) +
1103 sizeof(struct arm_request));
1104 queue_complete_req(req);
1105 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07001106 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 return (rcode);
1108}
1109
1110static int arm_write(struct hpsb_host *host, int nodeid, int destid,
1111 quadlet_t * data, u64 addr, size_t length, u16 flags)
1112{
Andy Wingo4a9949d2005-10-19 21:23:46 -07001113 unsigned long irqflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 struct pending_request *req;
1115 struct host_info *hi;
1116 struct file_info *fi = NULL;
1117 struct list_head *entry;
1118 struct arm_addr *arm_addr = NULL;
1119 struct arm_request *arm_req = NULL;
1120 struct arm_response *arm_resp = NULL;
1121 int found = 0, size = 0, rcode = -1, length_conflict = 0;
1122 struct arm_request_response *arm_req_resp = NULL;
1123
1124 DBGMSG("arm_write called by node: %X"
1125 "addr: %4.4x %8.8x length: %Zu", nodeid,
1126 (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
1127 length);
Andy Wingo4a9949d2005-10-19 21:23:46 -07001128 spin_lock_irqsave(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 hi = find_host_info(host); /* search address-entry */
1130 if (hi != NULL) {
1131 list_for_each_entry(fi, &hi->file_info_list, list) {
1132 entry = fi->addr_list.next;
1133 while (entry != &(fi->addr_list)) {
1134 arm_addr =
1135 list_entry(entry, struct arm_addr,
1136 addr_list);
1137 if (((arm_addr->start) <= (addr))
1138 && ((arm_addr->end) >= (addr + length))) {
1139 found = 1;
1140 break;
1141 }
1142 entry = entry->next;
1143 }
1144 if (found) {
1145 break;
1146 }
1147 }
1148 }
1149 rcode = -1;
1150 if (!found) {
1151 printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
1152 " -> rcode_address_error\n");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001153 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 return (RCODE_ADDRESS_ERROR);
1155 } else {
1156 DBGMSG("arm_write addr_entry FOUND");
1157 }
1158 if (arm_addr->rec_length < length) {
1159 DBGMSG("arm_write blocklength too big -> rcode_data_error");
1160 length_conflict = 1;
1161 rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
1162 }
1163 if (rcode == -1) {
1164 if (arm_addr->access_rights & ARM_WRITE) {
1165 if (!(arm_addr->client_transactions & ARM_WRITE)) {
1166 memcpy((arm_addr->addr_space_buffer) +
1167 (addr - (arm_addr->start)), data,
1168 length);
1169 DBGMSG("arm_write -> (rcode_complete)");
1170 rcode = RCODE_COMPLETE;
1171 }
1172 } else {
1173 rcode = RCODE_TYPE_ERROR; /* function not allowed */
1174 DBGMSG("arm_write -> rcode_type_error (access denied)");
1175 }
1176 }
1177 if (arm_addr->notification_options & ARM_WRITE) {
1178 DBGMSG("arm_write -> entering notification-section");
1179 req = __alloc_pending_request(SLAB_ATOMIC);
1180 if (!req) {
1181 DBGMSG("arm_write -> rcode_conflict_error");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001182 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1184 The request my be retried */
1185 }
1186 size =
1187 sizeof(struct arm_request) + sizeof(struct arm_response) +
1188 (length) * sizeof(byte_t) +
1189 sizeof(struct arm_request_response);
1190 req->data = kmalloc(size, SLAB_ATOMIC);
1191 if (!(req->data)) {
1192 free_pending_request(req);
1193 DBGMSG("arm_write -> rcode_conflict_error");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001194 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1196 The request may be retried */
1197 }
1198 req->free_data = 1;
1199 req->file_info = fi;
1200 req->req.type = RAW1394_REQ_ARM;
1201 req->req.generation = get_hpsb_generation(host);
1202 req->req.misc =
1203 (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
1204 req->req.tag = arm_addr->arm_tag;
1205 req->req.recvb = arm_addr->recvb;
1206 req->req.length = size;
1207 arm_req_resp = (struct arm_request_response *)(req->data);
1208 arm_req = (struct arm_request *)((byte_t *) (req->data) +
1209 (sizeof
1210 (struct
1211 arm_request_response)));
1212 arm_resp =
1213 (struct arm_response *)((byte_t *) (arm_req) +
1214 (sizeof(struct arm_request)));
1215 arm_resp->buffer = NULL;
1216 memcpy((byte_t *) arm_resp + sizeof(struct arm_response),
1217 data, length);
1218 arm_req->buffer = int2ptr((arm_addr->recvb) +
1219 sizeof(struct arm_request_response) +
1220 sizeof(struct arm_request) +
1221 sizeof(struct arm_response));
1222 arm_req->buffer_length = length;
1223 arm_req->generation = req->req.generation;
1224 arm_req->extended_transaction_code = 0;
1225 arm_req->destination_offset = addr;
1226 arm_req->source_nodeid = nodeid;
1227 arm_req->destination_nodeid = destid;
1228 arm_req->tlabel = (flags >> 10) & 0x3f;
1229 arm_req->tcode = (flags >> 4) & 0x0f;
1230 arm_resp->buffer_length = 0;
1231 arm_resp->response_code = rcode;
1232 arm_req_resp->request = int2ptr((arm_addr->recvb) +
1233 sizeof(struct
1234 arm_request_response));
1235 arm_req_resp->response =
1236 int2ptr((arm_addr->recvb) +
1237 sizeof(struct arm_request_response) +
1238 sizeof(struct arm_request));
1239 queue_complete_req(req);
1240 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07001241 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 return (rcode);
1243}
1244
1245static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
1246 u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
1247 u16 flags)
1248{
Andy Wingo4a9949d2005-10-19 21:23:46 -07001249 unsigned long irqflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 struct pending_request *req;
1251 struct host_info *hi;
1252 struct file_info *fi = NULL;
1253 struct list_head *entry;
1254 struct arm_addr *arm_addr = NULL;
1255 struct arm_request *arm_req = NULL;
1256 struct arm_response *arm_resp = NULL;
1257 int found = 0, size = 0, rcode = -1;
1258 quadlet_t old, new;
1259 struct arm_request_response *arm_req_resp = NULL;
1260
1261 if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
1262 ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
1263 DBGMSG("arm_lock called by node: %X "
1264 "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
1265 nodeid, (u16) ((addr >> 32) & 0xFFFF),
1266 (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
1267 be32_to_cpu(data));
1268 } else {
1269 DBGMSG("arm_lock called by node: %X "
1270 "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
1271 nodeid, (u16) ((addr >> 32) & 0xFFFF),
1272 (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
1273 be32_to_cpu(data), be32_to_cpu(arg));
1274 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07001275 spin_lock_irqsave(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 hi = find_host_info(host); /* search address-entry */
1277 if (hi != NULL) {
1278 list_for_each_entry(fi, &hi->file_info_list, list) {
1279 entry = fi->addr_list.next;
1280 while (entry != &(fi->addr_list)) {
1281 arm_addr =
1282 list_entry(entry, struct arm_addr,
1283 addr_list);
1284 if (((arm_addr->start) <= (addr))
1285 && ((arm_addr->end) >=
1286 (addr + sizeof(*store)))) {
1287 found = 1;
1288 break;
1289 }
1290 entry = entry->next;
1291 }
1292 if (found) {
1293 break;
1294 }
1295 }
1296 }
1297 rcode = -1;
1298 if (!found) {
1299 printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
1300 " -> rcode_address_error\n");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001301 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return (RCODE_ADDRESS_ERROR);
1303 } else {
1304 DBGMSG("arm_lock addr_entry FOUND");
1305 }
1306 if (rcode == -1) {
1307 if (arm_addr->access_rights & ARM_LOCK) {
1308 if (!(arm_addr->client_transactions & ARM_LOCK)) {
1309 memcpy(&old,
1310 (arm_addr->addr_space_buffer) + (addr -
1311 (arm_addr->
1312 start)),
1313 sizeof(old));
1314 switch (ext_tcode) {
1315 case (EXTCODE_MASK_SWAP):
1316 new = data | (old & ~arg);
1317 break;
1318 case (EXTCODE_COMPARE_SWAP):
1319 if (old == arg) {
1320 new = data;
1321 } else {
1322 new = old;
1323 }
1324 break;
1325 case (EXTCODE_FETCH_ADD):
1326 new =
1327 cpu_to_be32(be32_to_cpu(data) +
1328 be32_to_cpu(old));
1329 break;
1330 case (EXTCODE_LITTLE_ADD):
1331 new =
1332 cpu_to_le32(le32_to_cpu(data) +
1333 le32_to_cpu(old));
1334 break;
1335 case (EXTCODE_BOUNDED_ADD):
1336 if (old != arg) {
1337 new =
1338 cpu_to_be32(be32_to_cpu
1339 (data) +
1340 be32_to_cpu
1341 (old));
1342 } else {
1343 new = old;
1344 }
1345 break;
1346 case (EXTCODE_WRAP_ADD):
1347 if (old != arg) {
1348 new =
1349 cpu_to_be32(be32_to_cpu
1350 (data) +
1351 be32_to_cpu
1352 (old));
1353 } else {
1354 new = data;
1355 }
1356 break;
1357 default:
1358 rcode = RCODE_TYPE_ERROR; /* function not allowed */
1359 printk(KERN_ERR
1360 "raw1394: arm_lock FAILED "
1361 "ext_tcode not allowed -> rcode_type_error\n");
1362 break;
1363 } /*switch */
1364 if (rcode == -1) {
1365 DBGMSG("arm_lock -> (rcode_complete)");
1366 rcode = RCODE_COMPLETE;
1367 memcpy(store, &old, sizeof(*store));
1368 memcpy((arm_addr->addr_space_buffer) +
1369 (addr - (arm_addr->start)),
1370 &new, sizeof(*store));
1371 }
1372 }
1373 } else {
1374 rcode = RCODE_TYPE_ERROR; /* function not allowed */
1375 DBGMSG("arm_lock -> rcode_type_error (access denied)");
1376 }
1377 }
1378 if (arm_addr->notification_options & ARM_LOCK) {
1379 byte_t *buf1, *buf2;
1380 DBGMSG("arm_lock -> entering notification-section");
1381 req = __alloc_pending_request(SLAB_ATOMIC);
1382 if (!req) {
1383 DBGMSG("arm_lock -> rcode_conflict_error");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001384 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1386 The request may be retried */
1387 }
1388 size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */
1389 req->data = kmalloc(size, SLAB_ATOMIC);
1390 if (!(req->data)) {
1391 free_pending_request(req);
1392 DBGMSG("arm_lock -> rcode_conflict_error");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001393 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1395 The request may be retried */
1396 }
1397 req->free_data = 1;
1398 arm_req_resp = (struct arm_request_response *)(req->data);
1399 arm_req = (struct arm_request *)((byte_t *) (req->data) +
1400 (sizeof
1401 (struct
1402 arm_request_response)));
1403 arm_resp =
1404 (struct arm_response *)((byte_t *) (arm_req) +
1405 (sizeof(struct arm_request)));
1406 buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
1407 buf2 = buf1 + 2 * sizeof(*store);
1408 if ((ext_tcode == EXTCODE_FETCH_ADD) ||
1409 (ext_tcode == EXTCODE_LITTLE_ADD)) {
1410 arm_req->buffer_length = sizeof(*store);
1411 memcpy(buf1, &data, sizeof(*store));
1412
1413 } else {
1414 arm_req->buffer_length = 2 * sizeof(*store);
1415 memcpy(buf1, &arg, sizeof(*store));
1416 memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
1417 }
1418 if (rcode == RCODE_COMPLETE) {
1419 arm_resp->buffer_length = sizeof(*store);
1420 memcpy(buf2, &old, sizeof(*store));
1421 } else {
1422 arm_resp->buffer_length = 0;
1423 }
1424 req->file_info = fi;
1425 req->req.type = RAW1394_REQ_ARM;
1426 req->req.generation = get_hpsb_generation(host);
1427 req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
1428 (ARM_LOCK & 0xFF));
1429 req->req.tag = arm_addr->arm_tag;
1430 req->req.recvb = arm_addr->recvb;
1431 req->req.length = size;
1432 arm_req->generation = req->req.generation;
1433 arm_req->extended_transaction_code = ext_tcode;
1434 arm_req->destination_offset = addr;
1435 arm_req->source_nodeid = nodeid;
1436 arm_req->destination_nodeid = host->node_id;
1437 arm_req->tlabel = (flags >> 10) & 0x3f;
1438 arm_req->tcode = (flags >> 4) & 0x0f;
1439 arm_resp->response_code = rcode;
1440 arm_req_resp->request = int2ptr((arm_addr->recvb) +
1441 sizeof(struct
1442 arm_request_response));
1443 arm_req_resp->response =
1444 int2ptr((arm_addr->recvb) +
1445 sizeof(struct arm_request_response) +
1446 sizeof(struct arm_request));
1447 arm_req->buffer =
1448 int2ptr((arm_addr->recvb) +
1449 sizeof(struct arm_request_response) +
1450 sizeof(struct arm_request) +
1451 sizeof(struct arm_response));
1452 arm_resp->buffer =
1453 int2ptr((arm_addr->recvb) +
1454 sizeof(struct arm_request_response) +
1455 sizeof(struct arm_request) +
1456 sizeof(struct arm_response) + 2 * sizeof(*store));
1457 queue_complete_req(req);
1458 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07001459 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 return (rcode);
1461}
1462
1463static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
1464 u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
1465 u16 flags)
1466{
Andy Wingo4a9949d2005-10-19 21:23:46 -07001467 unsigned long irqflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 struct pending_request *req;
1469 struct host_info *hi;
1470 struct file_info *fi = NULL;
1471 struct list_head *entry;
1472 struct arm_addr *arm_addr = NULL;
1473 struct arm_request *arm_req = NULL;
1474 struct arm_response *arm_resp = NULL;
1475 int found = 0, size = 0, rcode = -1;
1476 octlet_t old, new;
1477 struct arm_request_response *arm_req_resp = NULL;
1478
1479 if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
1480 ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
1481 DBGMSG("arm_lock64 called by node: %X "
1482 "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
1483 nodeid, (u16) ((addr >> 32) & 0xFFFF),
1484 (u32) (addr & 0xFFFFFFFF),
1485 ext_tcode & 0xFF,
1486 (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
1487 (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
1488 } else {
1489 DBGMSG("arm_lock64 called by node: %X "
1490 "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
1491 "%8.8X %8.8X ",
1492 nodeid, (u16) ((addr >> 32) & 0xFFFF),
1493 (u32) (addr & 0xFFFFFFFF),
1494 ext_tcode & 0xFF,
1495 (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
1496 (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
1497 (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
1498 (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
1499 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07001500 spin_lock_irqsave(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 hi = find_host_info(host); /* search addressentry in file_info's for host */
1502 if (hi != NULL) {
1503 list_for_each_entry(fi, &hi->file_info_list, list) {
1504 entry = fi->addr_list.next;
1505 while (entry != &(fi->addr_list)) {
1506 arm_addr =
1507 list_entry(entry, struct arm_addr,
1508 addr_list);
1509 if (((arm_addr->start) <= (addr))
1510 && ((arm_addr->end) >=
1511 (addr + sizeof(*store)))) {
1512 found = 1;
1513 break;
1514 }
1515 entry = entry->next;
1516 }
1517 if (found) {
1518 break;
1519 }
1520 }
1521 }
1522 rcode = -1;
1523 if (!found) {
1524 printk(KERN_ERR
1525 "raw1394: arm_lock64 FAILED addr_entry not found"
1526 " -> rcode_address_error\n");
Andy Wingo4a9949d2005-10-19 21:23:46 -07001527 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 return (RCODE_ADDRESS_ERROR);
1529 } else {
1530 DBGMSG("arm_lock64 addr_entry FOUND");
1531 }
1532 if (rcode == -1) {
1533 if (arm_addr->access_rights & ARM_LOCK) {
1534 if (!(arm_addr->client_transactions & ARM_LOCK)) {
1535 memcpy(&old,
1536 (arm_addr->addr_space_buffer) + (addr -
1537 (arm_addr->
1538 start)),
1539 sizeof(old));
1540 switch (ext_tcode) {
1541 case (EXTCODE_MASK_SWAP):
1542 new = data | (old & ~arg);
1543 break;
1544 case (EXTCODE_COMPARE_SWAP):
1545 if (old == arg) {
1546 new = data;
1547 } else {
1548 new = old;
1549 }
1550 break;
1551 case (EXTCODE_FETCH_ADD):
1552 new =
1553 cpu_to_be64(be64_to_cpu(data) +
1554 be64_to_cpu(old));
1555 break;
1556 case (EXTCODE_LITTLE_ADD):
1557 new =
1558 cpu_to_le64(le64_to_cpu(data) +
1559 le64_to_cpu(old));
1560 break;
1561 case (EXTCODE_BOUNDED_ADD):
1562 if (old != arg) {
1563 new =
1564 cpu_to_be64(be64_to_cpu
1565 (data) +
1566 be64_to_cpu
1567 (old));
1568 } else {
1569 new = old;
1570 }
1571 break;
1572 case (EXTCODE_WRAP_ADD):
1573 if (old != arg) {
1574 new =
1575 cpu_to_be64(be64_to_cpu
1576 (data) +
1577 be64_to_cpu
1578 (old));
1579 } else {
1580 new = data;
1581 }
1582 break;
1583 default:
1584 printk(KERN_ERR
1585 "raw1394: arm_lock64 FAILED "
1586 "ext_tcode not allowed -> rcode_type_error\n");
1587 rcode = RCODE_TYPE_ERROR; /* function not allowed */
1588 break;
1589 } /*switch */
1590 if (rcode == -1) {
1591 DBGMSG
1592 ("arm_lock64 -> (rcode_complete)");
1593 rcode = RCODE_COMPLETE;
1594 memcpy(store, &old, sizeof(*store));
1595 memcpy((arm_addr->addr_space_buffer) +
1596 (addr - (arm_addr->start)),
1597 &new, sizeof(*store));
1598 }
1599 }
1600 } else {
1601 rcode = RCODE_TYPE_ERROR; /* function not allowed */
1602 DBGMSG
1603 ("arm_lock64 -> rcode_type_error (access denied)");
1604 }
1605 }
1606 if (arm_addr->notification_options & ARM_LOCK) {
1607 byte_t *buf1, *buf2;
1608 DBGMSG("arm_lock64 -> entering notification-section");
1609 req = __alloc_pending_request(SLAB_ATOMIC);
1610 if (!req) {
Andy Wingo4a9949d2005-10-19 21:23:46 -07001611 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 DBGMSG("arm_lock64 -> rcode_conflict_error");
1613 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1614 The request may be retried */
1615 }
1616 size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */
1617 req->data = kmalloc(size, SLAB_ATOMIC);
1618 if (!(req->data)) {
1619 free_pending_request(req);
Andy Wingo4a9949d2005-10-19 21:23:46 -07001620 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 DBGMSG("arm_lock64 -> rcode_conflict_error");
1622 return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
1623 The request may be retried */
1624 }
1625 req->free_data = 1;
1626 arm_req_resp = (struct arm_request_response *)(req->data);
1627 arm_req = (struct arm_request *)((byte_t *) (req->data) +
1628 (sizeof
1629 (struct
1630 arm_request_response)));
1631 arm_resp =
1632 (struct arm_response *)((byte_t *) (arm_req) +
1633 (sizeof(struct arm_request)));
1634 buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
1635 buf2 = buf1 + 2 * sizeof(*store);
1636 if ((ext_tcode == EXTCODE_FETCH_ADD) ||
1637 (ext_tcode == EXTCODE_LITTLE_ADD)) {
1638 arm_req->buffer_length = sizeof(*store);
1639 memcpy(buf1, &data, sizeof(*store));
1640
1641 } else {
1642 arm_req->buffer_length = 2 * sizeof(*store);
1643 memcpy(buf1, &arg, sizeof(*store));
1644 memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
1645 }
1646 if (rcode == RCODE_COMPLETE) {
1647 arm_resp->buffer_length = sizeof(*store);
1648 memcpy(buf2, &old, sizeof(*store));
1649 } else {
1650 arm_resp->buffer_length = 0;
1651 }
1652 req->file_info = fi;
1653 req->req.type = RAW1394_REQ_ARM;
1654 req->req.generation = get_hpsb_generation(host);
1655 req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
1656 (ARM_LOCK & 0xFF));
1657 req->req.tag = arm_addr->arm_tag;
1658 req->req.recvb = arm_addr->recvb;
1659 req->req.length = size;
1660 arm_req->generation = req->req.generation;
1661 arm_req->extended_transaction_code = ext_tcode;
1662 arm_req->destination_offset = addr;
1663 arm_req->source_nodeid = nodeid;
1664 arm_req->destination_nodeid = host->node_id;
1665 arm_req->tlabel = (flags >> 10) & 0x3f;
1666 arm_req->tcode = (flags >> 4) & 0x0f;
1667 arm_resp->response_code = rcode;
1668 arm_req_resp->request = int2ptr((arm_addr->recvb) +
1669 sizeof(struct
1670 arm_request_response));
1671 arm_req_resp->response =
1672 int2ptr((arm_addr->recvb) +
1673 sizeof(struct arm_request_response) +
1674 sizeof(struct arm_request));
1675 arm_req->buffer =
1676 int2ptr((arm_addr->recvb) +
1677 sizeof(struct arm_request_response) +
1678 sizeof(struct arm_request) +
1679 sizeof(struct arm_response));
1680 arm_resp->buffer =
1681 int2ptr((arm_addr->recvb) +
1682 sizeof(struct arm_request_response) +
1683 sizeof(struct arm_request) +
1684 sizeof(struct arm_response) + 2 * sizeof(*store));
1685 queue_complete_req(req);
1686 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07001687 spin_unlock_irqrestore(&host_info_lock, irqflags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 return (rcode);
1689}
1690
1691static int arm_register(struct file_info *fi, struct pending_request *req)
1692{
1693 int retval;
1694 struct arm_addr *addr;
1695 struct host_info *hi;
1696 struct file_info *fi_hlp = NULL;
1697 struct list_head *entry;
1698 struct arm_addr *arm_addr = NULL;
1699 int same_host, another_host;
1700 unsigned long flags;
1701
1702 DBGMSG("arm_register called "
1703 "addr(Offset): %8.8x %8.8x length: %u "
1704 "rights: %2.2X notify: %2.2X "
1705 "max_blk_len: %4.4X",
1706 (u32) ((req->req.address >> 32) & 0xFFFF),
1707 (u32) (req->req.address & 0xFFFFFFFF),
1708 req->req.length, ((req->req.misc >> 8) & 0xFF),
1709 (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF));
1710 /* check addressrange */
1711 if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
1712 (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) !=
1713 0)) {
1714 req->req.length = 0;
1715 return (-EINVAL);
1716 }
1717 /* addr-list-entry for fileinfo */
Stefan Richter85511582005-11-07 06:31:45 -05001718 addr = kmalloc(sizeof(*addr), SLAB_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 if (!addr) {
1720 req->req.length = 0;
1721 return (-ENOMEM);
1722 }
1723 /* allocation of addr_space_buffer */
Stefan Richter85511582005-11-07 06:31:45 -05001724 addr->addr_space_buffer = vmalloc(req->req.length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 if (!(addr->addr_space_buffer)) {
1726 kfree(addr);
1727 req->req.length = 0;
1728 return (-ENOMEM);
1729 }
1730 /* initialization of addr_space_buffer */
1731 if ((req->req.sendb) == (unsigned long)NULL) {
1732 /* init: set 0 */
1733 memset(addr->addr_space_buffer, 0, req->req.length);
1734 } else {
1735 /* init: user -> kernel */
1736 if (copy_from_user
1737 (addr->addr_space_buffer, int2ptr(req->req.sendb),
1738 req->req.length)) {
1739 vfree(addr->addr_space_buffer);
1740 kfree(addr);
1741 return (-EFAULT);
1742 }
1743 }
1744 INIT_LIST_HEAD(&addr->addr_list);
1745 addr->arm_tag = req->req.tag;
1746 addr->start = req->req.address;
1747 addr->end = req->req.address + req->req.length;
1748 addr->access_rights = (u8) (req->req.misc & 0x0F);
1749 addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
1750 addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
1751 addr->access_rights |= addr->client_transactions;
1752 addr->notification_options |= addr->client_transactions;
1753 addr->recvb = req->req.recvb;
1754 addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
1755 spin_lock_irqsave(&host_info_lock, flags);
1756 hi = find_host_info(fi->host);
1757 same_host = 0;
1758 another_host = 0;
1759 /* same host with address-entry containing same addressrange ? */
1760 list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
1761 entry = fi_hlp->addr_list.next;
1762 while (entry != &(fi_hlp->addr_list)) {
1763 arm_addr =
1764 list_entry(entry, struct arm_addr, addr_list);
1765 if ((arm_addr->start == addr->start)
1766 && (arm_addr->end == addr->end)) {
1767 DBGMSG("same host ownes same "
1768 "addressrange -> EALREADY");
1769 same_host = 1;
1770 break;
1771 }
1772 entry = entry->next;
1773 }
1774 if (same_host) {
1775 break;
1776 }
1777 }
1778 if (same_host) {
1779 /* addressrange occupied by same host */
1780 vfree(addr->addr_space_buffer);
1781 kfree(addr);
1782 spin_unlock_irqrestore(&host_info_lock, flags);
1783 return (-EALREADY);
1784 }
1785 /* another host with valid address-entry containing same addressrange */
1786 list_for_each_entry(hi, &host_info_list, list) {
1787 if (hi->host != fi->host) {
1788 list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
1789 entry = fi_hlp->addr_list.next;
1790 while (entry != &(fi_hlp->addr_list)) {
1791 arm_addr =
1792 list_entry(entry, struct arm_addr,
1793 addr_list);
1794 if ((arm_addr->start == addr->start)
1795 && (arm_addr->end == addr->end)) {
1796 DBGMSG
1797 ("another host ownes same "
1798 "addressrange");
1799 another_host = 1;
1800 break;
1801 }
1802 entry = entry->next;
1803 }
1804 if (another_host) {
1805 break;
1806 }
1807 }
1808 }
1809 }
1810 if (another_host) {
1811 DBGMSG("another hosts entry is valid -> SUCCESS");
1812 if (copy_to_user(int2ptr(req->req.recvb),
1813 &addr->start, sizeof(u64))) {
1814 printk(KERN_ERR "raw1394: arm_register failed "
1815 " address-range-entry is invalid -> EFAULT !!!\n");
1816 vfree(addr->addr_space_buffer);
1817 kfree(addr);
1818 spin_unlock_irqrestore(&host_info_lock, flags);
1819 return (-EFAULT);
1820 }
1821 free_pending_request(req); /* immediate success or fail */
1822 /* INSERT ENTRY */
1823 list_add_tail(&addr->addr_list, &fi->addr_list);
1824 spin_unlock_irqrestore(&host_info_lock, flags);
1825 return sizeof(struct raw1394_request);
1826 }
1827 retval =
1828 hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
1829 req->req.address,
1830 req->req.address + req->req.length);
1831 if (retval) {
1832 /* INSERT ENTRY */
1833 list_add_tail(&addr->addr_list, &fi->addr_list);
1834 } else {
1835 DBGMSG("arm_register failed errno: %d \n", retval);
1836 vfree(addr->addr_space_buffer);
1837 kfree(addr);
1838 spin_unlock_irqrestore(&host_info_lock, flags);
1839 return (-EALREADY);
1840 }
1841 spin_unlock_irqrestore(&host_info_lock, flags);
1842 free_pending_request(req); /* immediate success or fail */
1843 return sizeof(struct raw1394_request);
1844}
1845
1846static int arm_unregister(struct file_info *fi, struct pending_request *req)
1847{
1848 int found = 0;
1849 int retval = 0;
1850 struct list_head *entry;
1851 struct arm_addr *addr = NULL;
1852 struct host_info *hi;
1853 struct file_info *fi_hlp = NULL;
1854 struct arm_addr *arm_addr = NULL;
1855 int another_host;
1856 unsigned long flags;
1857
1858 DBGMSG("arm_Unregister called addr(Offset): "
1859 "%8.8x %8.8x",
1860 (u32) ((req->req.address >> 32) & 0xFFFF),
1861 (u32) (req->req.address & 0xFFFFFFFF));
1862 spin_lock_irqsave(&host_info_lock, flags);
1863 /* get addr */
1864 entry = fi->addr_list.next;
1865 while (entry != &(fi->addr_list)) {
1866 addr = list_entry(entry, struct arm_addr, addr_list);
1867 if (addr->start == req->req.address) {
1868 found = 1;
1869 break;
1870 }
1871 entry = entry->next;
1872 }
1873 if (!found) {
1874 DBGMSG("arm_Unregister addr not found");
1875 spin_unlock_irqrestore(&host_info_lock, flags);
1876 return (-EINVAL);
1877 }
1878 DBGMSG("arm_Unregister addr found");
1879 another_host = 0;
1880 /* another host with valid address-entry containing
1881 same addressrange */
1882 list_for_each_entry(hi, &host_info_list, list) {
1883 if (hi->host != fi->host) {
1884 list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
1885 entry = fi_hlp->addr_list.next;
1886 while (entry != &(fi_hlp->addr_list)) {
1887 arm_addr = list_entry(entry,
1888 struct arm_addr,
1889 addr_list);
1890 if (arm_addr->start == addr->start) {
1891 DBGMSG("another host ownes "
1892 "same addressrange");
1893 another_host = 1;
1894 break;
1895 }
1896 entry = entry->next;
1897 }
1898 if (another_host) {
1899 break;
1900 }
1901 }
1902 }
1903 }
1904 if (another_host) {
1905 DBGMSG("delete entry from list -> success");
1906 list_del(&addr->addr_list);
1907 vfree(addr->addr_space_buffer);
1908 kfree(addr);
1909 free_pending_request(req); /* immediate success or fail */
1910 spin_unlock_irqrestore(&host_info_lock, flags);
1911 return sizeof(struct raw1394_request);
1912 }
1913 retval =
1914 hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
1915 addr->start);
1916 if (!retval) {
1917 printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
1918 spin_unlock_irqrestore(&host_info_lock, flags);
1919 return (-EINVAL);
1920 }
1921 DBGMSG("delete entry from list -> success");
1922 list_del(&addr->addr_list);
1923 spin_unlock_irqrestore(&host_info_lock, flags);
1924 vfree(addr->addr_space_buffer);
1925 kfree(addr);
1926 free_pending_request(req); /* immediate success or fail */
1927 return sizeof(struct raw1394_request);
1928}
1929
1930/* Copy data from ARM buffer(s) to user buffer. */
1931static int arm_get_buf(struct file_info *fi, struct pending_request *req)
1932{
1933 struct arm_addr *arm_addr = NULL;
1934 unsigned long flags;
1935 unsigned long offset;
1936
1937 struct list_head *entry;
1938
1939 DBGMSG("arm_get_buf "
1940 "addr(Offset): %04X %08X length: %u",
1941 (u32) ((req->req.address >> 32) & 0xFFFF),
1942 (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
1943
1944 spin_lock_irqsave(&host_info_lock, flags);
1945 entry = fi->addr_list.next;
1946 while (entry != &(fi->addr_list)) {
1947 arm_addr = list_entry(entry, struct arm_addr, addr_list);
1948 if ((arm_addr->start <= req->req.address) &&
1949 (arm_addr->end > req->req.address)) {
1950 if (req->req.address + req->req.length <= arm_addr->end) {
1951 offset = req->req.address - arm_addr->start;
1952
1953 DBGMSG
1954 ("arm_get_buf copy_to_user( %08X, %p, %u )",
1955 (u32) req->req.recvb,
1956 arm_addr->addr_space_buffer + offset,
1957 (u32) req->req.length);
1958
1959 if (copy_to_user
1960 (int2ptr(req->req.recvb),
1961 arm_addr->addr_space_buffer + offset,
1962 req->req.length)) {
1963 spin_unlock_irqrestore(&host_info_lock,
1964 flags);
1965 return (-EFAULT);
1966 }
1967
1968 spin_unlock_irqrestore(&host_info_lock, flags);
1969 /* We have to free the request, because we
1970 * queue no response, and therefore nobody
1971 * will free it. */
1972 free_pending_request(req);
1973 return sizeof(struct raw1394_request);
1974 } else {
1975 DBGMSG("arm_get_buf request exceeded mapping");
1976 spin_unlock_irqrestore(&host_info_lock, flags);
1977 return (-EINVAL);
1978 }
1979 }
1980 entry = entry->next;
1981 }
1982 spin_unlock_irqrestore(&host_info_lock, flags);
1983 return (-EINVAL);
1984}
1985
1986/* Copy data from user buffer to ARM buffer(s). */
1987static int arm_set_buf(struct file_info *fi, struct pending_request *req)
1988{
1989 struct arm_addr *arm_addr = NULL;
1990 unsigned long flags;
1991 unsigned long offset;
1992
1993 struct list_head *entry;
1994
1995 DBGMSG("arm_set_buf "
1996 "addr(Offset): %04X %08X length: %u",
1997 (u32) ((req->req.address >> 32) & 0xFFFF),
1998 (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
1999
2000 spin_lock_irqsave(&host_info_lock, flags);
2001 entry = fi->addr_list.next;
2002 while (entry != &(fi->addr_list)) {
2003 arm_addr = list_entry(entry, struct arm_addr, addr_list);
2004 if ((arm_addr->start <= req->req.address) &&
2005 (arm_addr->end > req->req.address)) {
2006 if (req->req.address + req->req.length <= arm_addr->end) {
2007 offset = req->req.address - arm_addr->start;
2008
2009 DBGMSG
2010 ("arm_set_buf copy_from_user( %p, %08X, %u )",
2011 arm_addr->addr_space_buffer + offset,
2012 (u32) req->req.sendb,
2013 (u32) req->req.length);
2014
2015 if (copy_from_user
2016 (arm_addr->addr_space_buffer + offset,
2017 int2ptr(req->req.sendb),
2018 req->req.length)) {
2019 spin_unlock_irqrestore(&host_info_lock,
2020 flags);
2021 return (-EFAULT);
2022 }
2023
2024 spin_unlock_irqrestore(&host_info_lock, flags);
2025 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
2026 return sizeof(struct raw1394_request);
2027 } else {
2028 DBGMSG("arm_set_buf request exceeded mapping");
2029 spin_unlock_irqrestore(&host_info_lock, flags);
2030 return (-EINVAL);
2031 }
2032 }
2033 entry = entry->next;
2034 }
2035 spin_unlock_irqrestore(&host_info_lock, flags);
2036 return (-EINVAL);
2037}
2038
2039static int reset_notification(struct file_info *fi, struct pending_request *req)
2040{
2041 DBGMSG("reset_notification called - switch %s ",
2042 (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON");
2043 if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
2044 (req->req.misc == RAW1394_NOTIFY_ON)) {
2045 fi->notification = (u8) req->req.misc;
2046 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
2047 return sizeof(struct raw1394_request);
2048 }
2049 /* error EINVAL (22) invalid argument */
2050 return (-EINVAL);
2051}
2052
2053static int write_phypacket(struct file_info *fi, struct pending_request *req)
2054{
2055 struct hpsb_packet *packet = NULL;
2056 int retval = 0;
2057 quadlet_t data;
Andy Wingo4a9949d2005-10-19 21:23:46 -07002058 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
2060 data = be32_to_cpu((u32) req->req.sendb);
2061 DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data);
2062 packet = hpsb_make_phypacket(fi->host, data);
2063 if (!packet)
2064 return -ENOMEM;
2065 req->req.length = 0;
2066 req->packet = packet;
2067 hpsb_set_packet_complete_task(packet,
2068 (void (*)(void *))queue_complete_cb, req);
Andy Wingo4a9949d2005-10-19 21:23:46 -07002069 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 list_add_tail(&req->list, &fi->req_pending);
Andy Wingo4a9949d2005-10-19 21:23:46 -07002071 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 packet->generation = req->req.generation;
2073 retval = hpsb_send_packet(packet);
2074 DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
2075 if (retval < 0) {
2076 req->req.error = RAW1394_ERROR_SEND_ERROR;
2077 req->req.length = 0;
2078 queue_complete_req(req);
2079 }
2080 return sizeof(struct raw1394_request);
2081}
2082
2083static int get_config_rom(struct file_info *fi, struct pending_request *req)
2084{
2085 int ret = sizeof(struct raw1394_request);
2086 quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
2087 int status;
2088
2089 if (!data)
2090 return -ENOMEM;
2091
2092 status =
2093 csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
2094 data, req->req.length);
2095 if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length))
2096 ret = -EFAULT;
2097 if (copy_to_user
2098 (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
2099 sizeof(fi->host->csr.rom->cache_head->len)))
2100 ret = -EFAULT;
2101 if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation,
2102 sizeof(fi->host->csr.generation)))
2103 ret = -EFAULT;
2104 if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status)))
2105 ret = -EFAULT;
2106 kfree(data);
2107 if (ret >= 0) {
2108 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
2109 }
2110 return ret;
2111}
2112
2113static int update_config_rom(struct file_info *fi, struct pending_request *req)
2114{
2115 int ret = sizeof(struct raw1394_request);
2116 quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
2117 if (!data)
2118 return -ENOMEM;
2119 if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) {
2120 ret = -EFAULT;
2121 } else {
2122 int status = hpsb_update_config_rom(fi->host,
2123 data, req->req.length,
2124 (unsigned char)req->req.
2125 misc);
2126 if (copy_to_user
2127 (int2ptr(req->req.recvb), &status, sizeof(status)))
2128 ret = -ENOMEM;
2129 }
2130 kfree(data);
2131 if (ret >= 0) {
2132 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
2133 fi->cfgrom_upd = 1;
2134 }
2135 return ret;
2136}
2137
2138static int modify_config_rom(struct file_info *fi, struct pending_request *req)
2139{
2140 struct csr1212_keyval *kv;
2141 struct csr1212_csr_rom_cache *cache;
2142 struct csr1212_dentry *dentry;
2143 u32 dr;
2144 int ret = 0;
2145
2146 if (req->req.misc == ~0) {
2147 if (req->req.length == 0)
2148 return -EINVAL;
2149
2150 /* Find an unused slot */
2151 for (dr = 0;
2152 dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr];
2153 dr++) ;
2154
2155 if (dr == RAW1394_MAX_USER_CSR_DIRS)
2156 return -ENOMEM;
2157
2158 fi->csr1212_dirs[dr] =
2159 csr1212_new_directory(CSR1212_KV_ID_VENDOR);
2160 if (!fi->csr1212_dirs[dr])
2161 return -ENOMEM;
2162 } else {
2163 dr = req->req.misc;
2164 if (!fi->csr1212_dirs[dr])
2165 return -EINVAL;
2166
2167 /* Delete old stuff */
2168 for (dentry =
2169 fi->csr1212_dirs[dr]->value.directory.dentries_head;
2170 dentry; dentry = dentry->next) {
2171 csr1212_detach_keyval_from_directory(fi->host->csr.rom->
2172 root_kv,
2173 dentry->kv);
2174 }
2175
2176 if (req->req.length == 0) {
2177 csr1212_release_keyval(fi->csr1212_dirs[dr]);
2178 fi->csr1212_dirs[dr] = NULL;
2179
2180 hpsb_update_config_rom_image(fi->host);
2181 free_pending_request(req);
2182 return sizeof(struct raw1394_request);
2183 }
2184 }
2185
2186 cache = csr1212_rom_cache_malloc(0, req->req.length);
2187 if (!cache) {
2188 csr1212_release_keyval(fi->csr1212_dirs[dr]);
2189 fi->csr1212_dirs[dr] = NULL;
2190 return -ENOMEM;
2191 }
2192
Stefan Richter85511582005-11-07 06:31:45 -05002193 cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 if (!cache->filled_head) {
2195 csr1212_release_keyval(fi->csr1212_dirs[dr]);
2196 fi->csr1212_dirs[dr] = NULL;
2197 CSR1212_FREE(cache);
2198 return -ENOMEM;
2199 }
2200 cache->filled_tail = cache->filled_head;
2201
2202 if (copy_from_user(cache->data, int2ptr(req->req.sendb),
2203 req->req.length)) {
2204 csr1212_release_keyval(fi->csr1212_dirs[dr]);
2205 fi->csr1212_dirs[dr] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 ret = -EFAULT;
2207 } else {
2208 cache->len = req->req.length;
2209 cache->filled_head->offset_start = 0;
2210 cache->filled_head->offset_end = cache->size - 1;
2211
2212 cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr];
2213
2214 ret = CSR1212_SUCCESS;
2215 /* parse all the items */
2216 for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv;
2217 kv = kv->next) {
2218 ret = csr1212_parse_keyval(kv, cache);
2219 }
2220
2221 /* attach top level items to the root directory */
2222 for (dentry =
2223 fi->csr1212_dirs[dr]->value.directory.dentries_head;
2224 ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) {
2225 ret =
2226 csr1212_attach_keyval_to_directory(fi->host->csr.
2227 rom->root_kv,
2228 dentry->kv);
2229 }
2230
2231 if (ret == CSR1212_SUCCESS) {
2232 ret = hpsb_update_config_rom_image(fi->host);
2233
2234 if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb),
2235 &dr, sizeof(dr))) {
2236 ret = -ENOMEM;
2237 }
2238 }
2239 }
2240 kfree(cache->filled_head);
Stefan Richterb12479d2005-11-21 17:32:18 -05002241 CSR1212_FREE(cache);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242
2243 if (ret >= 0) {
2244 /* we have to free the request, because we queue no response,
2245 * and therefore nobody will free it */
2246 free_pending_request(req);
2247 return sizeof(struct raw1394_request);
2248 } else {
2249 for (dentry =
2250 fi->csr1212_dirs[dr]->value.directory.dentries_head;
2251 dentry; dentry = dentry->next) {
2252 csr1212_detach_keyval_from_directory(fi->host->csr.rom->
2253 root_kv,
2254 dentry->kv);
2255 }
2256 csr1212_release_keyval(fi->csr1212_dirs[dr]);
2257 fi->csr1212_dirs[dr] = NULL;
2258 return ret;
2259 }
2260}
2261
2262static int state_connected(struct file_info *fi, struct pending_request *req)
2263{
2264 int node = req->req.address >> 48;
2265
2266 req->req.error = RAW1394_ERROR_NONE;
2267
2268 switch (req->req.type) {
2269
2270 case RAW1394_REQ_ECHO:
2271 queue_complete_req(req);
2272 return sizeof(struct raw1394_request);
2273
2274 case RAW1394_REQ_ISO_SEND:
2275 return handle_iso_send(fi, req, node);
2276
2277 case RAW1394_REQ_ARM_REGISTER:
2278 return arm_register(fi, req);
2279
2280 case RAW1394_REQ_ARM_UNREGISTER:
2281 return arm_unregister(fi, req);
2282
2283 case RAW1394_REQ_ARM_SET_BUF:
2284 return arm_set_buf(fi, req);
2285
2286 case RAW1394_REQ_ARM_GET_BUF:
2287 return arm_get_buf(fi, req);
2288
2289 case RAW1394_REQ_RESET_NOTIFY:
2290 return reset_notification(fi, req);
2291
2292 case RAW1394_REQ_ISO_LISTEN:
2293 handle_iso_listen(fi, req);
2294 return sizeof(struct raw1394_request);
2295
2296 case RAW1394_REQ_FCP_LISTEN:
2297 handle_fcp_listen(fi, req);
2298 return sizeof(struct raw1394_request);
2299
2300 case RAW1394_REQ_RESET_BUS:
2301 if (req->req.misc == RAW1394_LONG_RESET) {
2302 DBGMSG("busreset called (type: LONG)");
2303 hpsb_reset_bus(fi->host, LONG_RESET);
2304 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
2305 return sizeof(struct raw1394_request);
2306 }
2307 if (req->req.misc == RAW1394_SHORT_RESET) {
2308 DBGMSG("busreset called (type: SHORT)");
2309 hpsb_reset_bus(fi->host, SHORT_RESET);
2310 free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
2311 return sizeof(struct raw1394_request);
2312 }
2313 /* error EINVAL (22) invalid argument */
2314 return (-EINVAL);
2315 case RAW1394_REQ_GET_ROM:
2316 return get_config_rom(fi, req);
2317
2318 case RAW1394_REQ_UPDATE_ROM:
2319 return update_config_rom(fi, req);
2320
2321 case RAW1394_REQ_MODIFY_ROM:
2322 return modify_config_rom(fi, req);
2323 }
2324
2325 if (req->req.generation != get_hpsb_generation(fi->host)) {
2326 req->req.error = RAW1394_ERROR_GENERATION;
2327 req->req.generation = get_hpsb_generation(fi->host);
2328 req->req.length = 0;
2329 queue_complete_req(req);
2330 return sizeof(struct raw1394_request);
2331 }
2332
2333 switch (req->req.type) {
2334 case RAW1394_REQ_PHYPACKET:
2335 return write_phypacket(fi, req);
2336 case RAW1394_REQ_ASYNC_SEND:
2337 return handle_async_send(fi, req);
2338 }
2339
2340 if (req->req.length == 0) {
2341 req->req.error = RAW1394_ERROR_INVALID_ARG;
2342 queue_complete_req(req);
2343 return sizeof(struct raw1394_request);
2344 }
2345
2346 return handle_async_request(fi, req, node);
2347}
2348
2349static ssize_t raw1394_write(struct file *file, const char __user * buffer,
2350 size_t count, loff_t * offset_is_ignored)
2351{
2352 struct file_info *fi = (struct file_info *)file->private_data;
2353 struct pending_request *req;
2354 ssize_t retval = 0;
2355
Andi Kleen4bc32c42006-03-25 16:30:07 +01002356#ifdef CONFIG_COMPAT
Ben Collins75970282006-06-12 18:12:10 -04002357 if (count == sizeof(struct compat_raw1394_req) &&
2358 sizeof(struct compat_raw1394_req) !=
2359 sizeof(struct raw1394_request)) {
Andi Kleen4bc32c42006-03-25 16:30:07 +01002360 buffer = raw1394_compat_write(buffer);
2361 if (IS_ERR(buffer))
2362 return PTR_ERR(buffer);
2363 } else
2364#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 if (count != sizeof(struct raw1394_request)) {
2366 return -EINVAL;
2367 }
2368
2369 req = alloc_pending_request();
2370 if (req == NULL) {
2371 return -ENOMEM;
2372 }
2373 req->file_info = fi;
2374
2375 if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
2376 free_pending_request(req);
2377 return -EFAULT;
2378 }
2379
2380 switch (fi->state) {
2381 case opened:
2382 retval = state_opened(fi, req);
2383 break;
2384
2385 case initialized:
2386 retval = state_initialized(fi, req);
2387 break;
2388
2389 case connected:
2390 retval = state_connected(fi, req);
2391 break;
2392 }
2393
2394 if (retval < 0) {
2395 free_pending_request(req);
2396 }
2397
2398 return retval;
2399}
2400
2401/* rawiso operations */
2402
2403/* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the
2404 * completion queue (reqlists_lock must be taken) */
2405static inline int __rawiso_event_in_queue(struct file_info *fi)
2406{
2407 struct pending_request *req;
2408
2409 list_for_each_entry(req, &fi->req_complete, list)
2410 if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
2411 return 1;
2412
2413 return 0;
2414}
2415
2416/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */
2417static void queue_rawiso_event(struct file_info *fi)
2418{
2419 unsigned long flags;
2420
2421 spin_lock_irqsave(&fi->reqlists_lock, flags);
2422
2423 /* only one ISO activity event may be in the queue */
2424 if (!__rawiso_event_in_queue(fi)) {
2425 struct pending_request *req =
2426 __alloc_pending_request(SLAB_ATOMIC);
2427
2428 if (req) {
2429 req->file_info = fi;
2430 req->req.type = RAW1394_REQ_RAWISO_ACTIVITY;
2431 req->req.generation = get_hpsb_generation(fi->host);
2432 __queue_complete_req(req);
2433 } else {
2434 /* on allocation failure, signal an overflow */
2435 if (fi->iso_handle) {
2436 atomic_inc(&fi->iso_handle->overflows);
2437 }
2438 }
2439 }
2440 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
2441}
2442
2443static void rawiso_activity_cb(struct hpsb_iso *iso)
2444{
2445 unsigned long flags;
2446 struct host_info *hi;
2447 struct file_info *fi;
2448
2449 spin_lock_irqsave(&host_info_lock, flags);
2450 hi = find_host_info(iso->host);
2451
2452 if (hi != NULL) {
2453 list_for_each_entry(fi, &hi->file_info_list, list) {
2454 if (fi->iso_handle == iso)
2455 queue_rawiso_event(fi);
2456 }
2457 }
2458
2459 spin_unlock_irqrestore(&host_info_lock, flags);
2460}
2461
2462/* helper function - gather all the kernel iso status bits for returning to user-space */
2463static void raw1394_iso_fill_status(struct hpsb_iso *iso,
2464 struct raw1394_iso_status *stat)
2465{
2466 stat->config.data_buf_size = iso->buf_size;
2467 stat->config.buf_packets = iso->buf_packets;
2468 stat->config.channel = iso->channel;
2469 stat->config.speed = iso->speed;
2470 stat->config.irq_interval = iso->irq_interval;
2471 stat->n_packets = hpsb_iso_n_ready(iso);
2472 stat->overflows = atomic_read(&iso->overflows);
2473 stat->xmit_cycle = iso->xmit_cycle;
2474}
2475
2476static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr)
2477{
2478 struct raw1394_iso_status stat;
2479
2480 if (!fi->host)
2481 return -EINVAL;
2482
2483 if (copy_from_user(&stat, uaddr, sizeof(stat)))
2484 return -EFAULT;
2485
2486 fi->iso_handle = hpsb_iso_xmit_init(fi->host,
2487 stat.config.data_buf_size,
2488 stat.config.buf_packets,
2489 stat.config.channel,
2490 stat.config.speed,
2491 stat.config.irq_interval,
2492 rawiso_activity_cb);
2493 if (!fi->iso_handle)
2494 return -ENOMEM;
2495
2496 fi->iso_state = RAW1394_ISO_XMIT;
2497
2498 raw1394_iso_fill_status(fi->iso_handle, &stat);
2499 if (copy_to_user(uaddr, &stat, sizeof(stat)))
2500 return -EFAULT;
2501
2502 /* queue an event to get things started */
2503 rawiso_activity_cb(fi->iso_handle);
2504
2505 return 0;
2506}
2507
2508static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr)
2509{
2510 struct raw1394_iso_status stat;
2511
2512 if (!fi->host)
2513 return -EINVAL;
2514
2515 if (copy_from_user(&stat, uaddr, sizeof(stat)))
2516 return -EFAULT;
2517
2518 fi->iso_handle = hpsb_iso_recv_init(fi->host,
2519 stat.config.data_buf_size,
2520 stat.config.buf_packets,
2521 stat.config.channel,
2522 stat.config.dma_mode,
2523 stat.config.irq_interval,
2524 rawiso_activity_cb);
2525 if (!fi->iso_handle)
2526 return -ENOMEM;
2527
2528 fi->iso_state = RAW1394_ISO_RECV;
2529
2530 raw1394_iso_fill_status(fi->iso_handle, &stat);
2531 if (copy_to_user(uaddr, &stat, sizeof(stat)))
2532 return -EFAULT;
2533 return 0;
2534}
2535
2536static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
2537{
2538 struct raw1394_iso_status stat;
2539 struct hpsb_iso *iso = fi->iso_handle;
2540
2541 raw1394_iso_fill_status(fi->iso_handle, &stat);
2542 if (copy_to_user(uaddr, &stat, sizeof(stat)))
2543 return -EFAULT;
2544
2545 /* reset overflow counter */
2546 atomic_set(&iso->overflows, 0);
2547
2548 return 0;
2549}
2550
2551/* copy N packet_infos out of the ringbuffer into user-supplied array */
2552static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
2553{
2554 struct raw1394_iso_packets upackets;
2555 unsigned int packet = fi->iso_handle->first_packet;
2556 int i;
2557
2558 if (copy_from_user(&upackets, uaddr, sizeof(upackets)))
2559 return -EFAULT;
2560
2561 if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))
2562 return -EINVAL;
2563
2564 /* ensure user-supplied buffer is accessible and big enough */
2565 if (!access_ok(VERIFY_WRITE, upackets.infos,
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05002566 upackets.n_packets *
2567 sizeof(struct raw1394_iso_packet_info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568 return -EFAULT;
2569
2570 /* copy the packet_infos out */
2571 for (i = 0; i < upackets.n_packets; i++) {
2572 if (__copy_to_user(&upackets.infos[i],
2573 &fi->iso_handle->infos[packet],
2574 sizeof(struct raw1394_iso_packet_info)))
2575 return -EFAULT;
2576
2577 packet = (packet + 1) % fi->iso_handle->buf_packets;
2578 }
2579
2580 return 0;
2581}
2582
2583/* copy N packet_infos from user to ringbuffer, and queue them for transmission */
2584static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
2585{
2586 struct raw1394_iso_packets upackets;
2587 int i, rv;
2588
2589 if (copy_from_user(&upackets, uaddr, sizeof(upackets)))
2590 return -EFAULT;
2591
Ben Collins1934b8b2005-07-09 20:01:23 -04002592 if (upackets.n_packets >= fi->iso_handle->buf_packets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 return -EINVAL;
2594
Ben Collins1934b8b2005-07-09 20:01:23 -04002595 if (upackets.n_packets >= hpsb_iso_n_ready(fi->iso_handle))
2596 return -EAGAIN;
2597
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 /* ensure user-supplied buffer is accessible and big enough */
2599 if (!access_ok(VERIFY_READ, upackets.infos,
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05002600 upackets.n_packets *
2601 sizeof(struct raw1394_iso_packet_info)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 return -EFAULT;
2603
2604 /* copy the infos structs in and queue the packets */
2605 for (i = 0; i < upackets.n_packets; i++) {
2606 struct raw1394_iso_packet_info info;
2607
2608 if (__copy_from_user(&info, &upackets.infos[i],
2609 sizeof(struct raw1394_iso_packet_info)))
2610 return -EFAULT;
2611
2612 rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,
2613 info.len, info.tag, info.sy);
2614 if (rv)
2615 return rv;
2616 }
2617
2618 return 0;
2619}
2620
2621static void raw1394_iso_shutdown(struct file_info *fi)
2622{
2623 if (fi->iso_handle)
2624 hpsb_iso_shutdown(fi->iso_handle);
2625
2626 fi->iso_handle = NULL;
2627 fi->iso_state = RAW1394_ISO_INACTIVE;
2628}
2629
2630/* mmap the rawiso xmit/recv buffer */
2631static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
2632{
2633 struct file_info *fi = file->private_data;
2634
2635 if (fi->iso_state == RAW1394_ISO_INACTIVE)
2636 return -EINVAL;
2637
2638 return dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
2639}
2640
2641/* ioctl is only used for rawiso operations */
2642static int raw1394_ioctl(struct inode *inode, struct file *file,
2643 unsigned int cmd, unsigned long arg)
2644{
2645 struct file_info *fi = file->private_data;
2646 void __user *argp = (void __user *)arg;
2647
2648 switch (fi->iso_state) {
2649 case RAW1394_ISO_INACTIVE:
2650 switch (cmd) {
2651 case RAW1394_IOC_ISO_XMIT_INIT:
2652 return raw1394_iso_xmit_init(fi, argp);
2653 case RAW1394_IOC_ISO_RECV_INIT:
2654 return raw1394_iso_recv_init(fi, argp);
2655 default:
2656 break;
2657 }
2658 break;
2659 case RAW1394_ISO_RECV:
2660 switch (cmd) {
2661 case RAW1394_IOC_ISO_RECV_START:{
2662 /* copy args from user-space */
2663 int args[3];
2664 if (copy_from_user
2665 (&args[0], argp, sizeof(args)))
2666 return -EFAULT;
2667 return hpsb_iso_recv_start(fi->iso_handle,
2668 args[0], args[1],
2669 args[2]);
2670 }
2671 case RAW1394_IOC_ISO_XMIT_RECV_STOP:
2672 hpsb_iso_stop(fi->iso_handle);
2673 return 0;
2674 case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
2675 return hpsb_iso_recv_listen_channel(fi->iso_handle,
2676 arg);
2677 case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
2678 return hpsb_iso_recv_unlisten_channel(fi->iso_handle,
2679 arg);
2680 case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
2681 /* copy the u64 from user-space */
2682 u64 mask;
2683 if (copy_from_user(&mask, argp, sizeof(mask)))
2684 return -EFAULT;
2685 return hpsb_iso_recv_set_channel_mask(fi->
2686 iso_handle,
2687 mask);
2688 }
2689 case RAW1394_IOC_ISO_GET_STATUS:
2690 return raw1394_iso_get_status(fi, argp);
2691 case RAW1394_IOC_ISO_RECV_PACKETS:
2692 return raw1394_iso_recv_packets(fi, argp);
2693 case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
2694 return hpsb_iso_recv_release_packets(fi->iso_handle,
2695 arg);
2696 case RAW1394_IOC_ISO_RECV_FLUSH:
2697 return hpsb_iso_recv_flush(fi->iso_handle);
2698 case RAW1394_IOC_ISO_SHUTDOWN:
2699 raw1394_iso_shutdown(fi);
2700 return 0;
2701 case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
2702 queue_rawiso_event(fi);
2703 return 0;
2704 }
2705 break;
2706 case RAW1394_ISO_XMIT:
2707 switch (cmd) {
2708 case RAW1394_IOC_ISO_XMIT_START:{
2709 /* copy two ints from user-space */
2710 int args[2];
2711 if (copy_from_user
2712 (&args[0], argp, sizeof(args)))
2713 return -EFAULT;
2714 return hpsb_iso_xmit_start(fi->iso_handle,
2715 args[0], args[1]);
2716 }
2717 case RAW1394_IOC_ISO_XMIT_SYNC:
2718 return hpsb_iso_xmit_sync(fi->iso_handle);
2719 case RAW1394_IOC_ISO_XMIT_RECV_STOP:
2720 hpsb_iso_stop(fi->iso_handle);
2721 return 0;
2722 case RAW1394_IOC_ISO_GET_STATUS:
2723 return raw1394_iso_get_status(fi, argp);
2724 case RAW1394_IOC_ISO_XMIT_PACKETS:
2725 return raw1394_iso_send_packets(fi, argp);
2726 case RAW1394_IOC_ISO_SHUTDOWN:
2727 raw1394_iso_shutdown(fi);
2728 return 0;
2729 case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
2730 queue_rawiso_event(fi);
2731 return 0;
2732 }
2733 break;
2734 default:
2735 break;
2736 }
2737
2738 return -EINVAL;
2739}
2740
2741static unsigned int raw1394_poll(struct file *file, poll_table * pt)
2742{
2743 struct file_info *fi = file->private_data;
2744 unsigned int mask = POLLOUT | POLLWRNORM;
Andy Wingo4a9949d2005-10-19 21:23:46 -07002745 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746
2747 poll_wait(file, &fi->poll_wait_complete, pt);
2748
Andy Wingo4a9949d2005-10-19 21:23:46 -07002749 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 if (!list_empty(&fi->req_complete)) {
2751 mask |= POLLIN | POLLRDNORM;
2752 }
Andy Wingo4a9949d2005-10-19 21:23:46 -07002753 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
2755 return mask;
2756}
2757
2758static int raw1394_open(struct inode *inode, struct file *file)
2759{
2760 struct file_info *fi;
2761
Stefan Richter85511582005-11-07 06:31:45 -05002762 fi = kzalloc(sizeof(*fi), SLAB_KERNEL);
2763 if (!fi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 return -ENOMEM;
2765
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
2767
2768 INIT_LIST_HEAD(&fi->list);
2769 fi->state = opened;
2770 INIT_LIST_HEAD(&fi->req_pending);
2771 INIT_LIST_HEAD(&fi->req_complete);
2772 sema_init(&fi->complete_sem, 0);
2773 spin_lock_init(&fi->reqlists_lock);
2774 init_waitqueue_head(&fi->poll_wait_complete);
2775 INIT_LIST_HEAD(&fi->addr_list);
2776
2777 file->private_data = fi;
2778
2779 return 0;
2780}
2781
2782static int raw1394_release(struct inode *inode, struct file *file)
2783{
2784 struct file_info *fi = file->private_data;
2785 struct list_head *lh;
2786 struct pending_request *req;
2787 int done = 0, i, fail = 0;
2788 int retval = 0;
2789 struct list_head *entry;
2790 struct arm_addr *addr = NULL;
2791 struct host_info *hi;
2792 struct file_info *fi_hlp = NULL;
2793 struct arm_addr *arm_addr = NULL;
2794 int another_host;
2795 int csr_mod = 0;
Andy Wingo4a9949d2005-10-19 21:23:46 -07002796 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798 if (fi->iso_state != RAW1394_ISO_INACTIVE)
2799 raw1394_iso_shutdown(fi);
2800
2801 for (i = 0; i < 64; i++) {
2802 if (fi->listen_channels & (1ULL << i)) {
2803 hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
2804 }
2805 }
2806
Andy Wingo4a9949d2005-10-19 21:23:46 -07002807 spin_lock_irqsave(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 fi->listen_channels = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
2810 fail = 0;
2811 /* set address-entries invalid */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
2813 while (!list_empty(&fi->addr_list)) {
2814 another_host = 0;
2815 lh = fi->addr_list.next;
2816 addr = list_entry(lh, struct arm_addr, addr_list);
2817 /* another host with valid address-entry containing
2818 same addressrange? */
2819 list_for_each_entry(hi, &host_info_list, list) {
2820 if (hi->host != fi->host) {
2821 list_for_each_entry(fi_hlp, &hi->file_info_list,
2822 list) {
2823 entry = fi_hlp->addr_list.next;
2824 while (entry != &(fi_hlp->addr_list)) {
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05002825 arm_addr = list_entry(entry, struct
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 arm_addr,
2827 addr_list);
2828 if (arm_addr->start ==
2829 addr->start) {
2830 DBGMSG
2831 ("raw1394_release: "
2832 "another host ownes "
2833 "same addressrange");
2834 another_host = 1;
2835 break;
2836 }
2837 entry = entry->next;
2838 }
2839 if (another_host) {
2840 break;
2841 }
2842 }
2843 }
2844 }
2845 if (!another_host) {
2846 DBGMSG("raw1394_release: call hpsb_arm_unregister");
2847 retval =
2848 hpsb_unregister_addrspace(&raw1394_highlevel,
2849 fi->host, addr->start);
2850 if (!retval) {
2851 ++fail;
2852 printk(KERN_ERR
2853 "raw1394_release arm_Unregister failed\n");
2854 }
2855 }
2856 DBGMSG("raw1394_release: delete addr_entry from list");
2857 list_del(&addr->addr_list);
2858 vfree(addr->addr_space_buffer);
2859 kfree(addr);
2860 } /* while */
Andy Wingo4a9949d2005-10-19 21:23:46 -07002861 spin_unlock_irqrestore(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 if (fail > 0) {
2863 printk(KERN_ERR "raw1394: during addr_list-release "
2864 "error(s) occurred \n");
2865 }
2866
2867 while (!done) {
Andy Wingo4a9949d2005-10-19 21:23:46 -07002868 spin_lock_irqsave(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869
2870 while (!list_empty(&fi->req_complete)) {
2871 lh = fi->req_complete.next;
2872 list_del(lh);
2873
2874 req = list_entry(lh, struct pending_request, list);
2875
2876 free_pending_request(req);
2877 }
2878
2879 if (list_empty(&fi->req_pending))
2880 done = 1;
2881
Andy Wingo4a9949d2005-10-19 21:23:46 -07002882 spin_unlock_irqrestore(&fi->reqlists_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
2884 if (!done)
2885 down_interruptible(&fi->complete_sem);
2886 }
2887
2888 /* Remove any sub-trees left by user space programs */
2889 for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) {
2890 struct csr1212_dentry *dentry;
2891 if (!fi->csr1212_dirs[i])
2892 continue;
2893 for (dentry =
2894 fi->csr1212_dirs[i]->value.directory.dentries_head; dentry;
2895 dentry = dentry->next) {
2896 csr1212_detach_keyval_from_directory(fi->host->csr.rom->
2897 root_kv,
2898 dentry->kv);
2899 }
2900 csr1212_release_keyval(fi->csr1212_dirs[i]);
2901 fi->csr1212_dirs[i] = NULL;
2902 csr_mod = 1;
2903 }
2904
2905 if ((csr_mod || fi->cfgrom_upd)
2906 && hpsb_update_config_rom_image(fi->host) < 0)
2907 HPSB_ERR
2908 ("Failed to generate Configuration ROM image for host %d",
2909 fi->host->id);
2910
2911 if (fi->state == connected) {
Andy Wingo4a9949d2005-10-19 21:23:46 -07002912 spin_lock_irqsave(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913 list_del(&fi->list);
Andy Wingo4a9949d2005-10-19 21:23:46 -07002914 spin_unlock_irqrestore(&host_info_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
2916 put_device(&fi->host->device);
2917 }
2918
2919 kfree(fi);
2920
2921 return 0;
2922}
2923
2924/*** HOTPLUG STUFF **********************************************************/
2925/*
2926 * Export information about protocols/devices supported by this driver.
2927 */
2928static struct ieee1394_device_id raw1394_id_table[] = {
2929 {
2930 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
2931 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
2932 .version = AVC_SW_VERSION_ENTRY & 0xffffff},
2933 {
2934 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
2935 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
2936 .version = CAMERA_SW_VERSION_ENTRY & 0xffffff},
2937 {
2938 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
2939 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
2940 .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff},
2941 {
2942 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
2943 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
2944 .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff},
2945 {}
2946};
2947
2948MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
2949
2950static struct hpsb_protocol_driver raw1394_driver = {
2951 .name = "raw1394 Driver",
2952 .id_table = raw1394_id_table,
2953 .driver = {
2954 .name = "raw1394",
2955 .bus = &ieee1394_bus_type,
2956 },
2957};
2958
2959/******************************************************************************/
2960
2961static struct hpsb_highlevel raw1394_highlevel = {
2962 .name = RAW1394_DEVICE_NAME,
2963 .add_host = add_host,
2964 .remove_host = remove_host,
2965 .host_reset = host_reset,
2966 .iso_receive = iso_receive,
2967 .fcp_request = fcp_request,
2968};
2969
2970static struct cdev raw1394_cdev;
2971static struct file_operations raw1394_fops = {
2972 .owner = THIS_MODULE,
2973 .read = raw1394_read,
2974 .write = raw1394_write,
2975 .mmap = raw1394_mmap,
2976 .ioctl = raw1394_ioctl,
Andi Kleen4bc32c42006-03-25 16:30:07 +01002977 // .compat_ioctl = ... someone needs to do this
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 .poll = raw1394_poll,
2979 .open = raw1394_open,
2980 .release = raw1394_release,
2981};
2982
2983static int __init init_raw1394(void)
2984{
2985 int ret = 0;
2986
2987 hpsb_register_highlevel(&raw1394_highlevel);
2988
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05002989 if (IS_ERR
2990 (class_device_create
2991 (hpsb_protocol_class, NULL,
2992 MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
2993 RAW1394_DEVICE_NAME))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 ret = -EFAULT;
2995 goto out_unreg;
2996 }
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05002997
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 cdev_init(&raw1394_cdev, &raw1394_fops);
2999 raw1394_cdev.owner = THIS_MODULE;
3000 kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
3001 ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
3002 if (ret) {
3003 HPSB_ERR("raw1394 failed to register minor device block");
3004 goto out_dev;
3005 }
3006
3007 HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
3008
3009 ret = hpsb_register_protocol(&raw1394_driver);
3010 if (ret) {
3011 HPSB_ERR("raw1394: failed to register protocol");
3012 cdev_del(&raw1394_cdev);
3013 goto out_dev;
3014 }
3015
3016 goto out;
3017
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05003018 out_dev:
gregkh@suse.de7e25ab92005-03-23 09:53:36 -08003019 class_device_destroy(hpsb_protocol_class,
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05003020 MKDEV(IEEE1394_MAJOR,
3021 IEEE1394_MINOR_BLOCK_RAW1394 * 16));
3022 out_unreg:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 hpsb_unregister_highlevel(&raw1394_highlevel);
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05003024 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 return ret;
3026}
3027
3028static void __exit cleanup_raw1394(void)
3029{
gregkh@suse.de7e25ab92005-03-23 09:53:36 -08003030 class_device_destroy(hpsb_protocol_class,
Jens-Michael Hoffmannc64d4722005-11-22 12:37:10 -05003031 MKDEV(IEEE1394_MAJOR,
3032 IEEE1394_MINOR_BLOCK_RAW1394 * 16));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 cdev_del(&raw1394_cdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 hpsb_unregister_highlevel(&raw1394_highlevel);
3035 hpsb_unregister_protocol(&raw1394_driver);
3036}
3037
3038module_init(init_raw1394);
3039module_exit(cleanup_raw1394);
3040MODULE_LICENSE("GPL");