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