staging: r8712u: Most return-values changed from -1 to proper errno macros.
[deliverable/linux.git] / drivers / staging / vme / vme.c
CommitLineData
a17a75e2
MW
1/*
2 * VME Bridge Framework
3 *
66bd8db5
MW
4 * Author: Martyn Welch <martyn.welch@ge.com>
5 * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
a17a75e2
MW
6 *
7 * Based on work by Tom Armistead and Ajit Prem
8 * Copyright 2004 Motorola Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
a17a75e2
MW
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/mm.h>
19#include <linux/types.h>
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/pci.h>
23#include <linux/poll.h>
24#include <linux/highmem.h>
25#include <linux/interrupt.h>
26#include <linux/pagemap.h>
27#include <linux/device.h>
28#include <linux/dma-mapping.h>
29#include <linux/syscalls.h>
400822fe 30#include <linux/mutex.h>
a17a75e2 31#include <linux/spinlock.h>
5a0e3ad6 32#include <linux/slab.h>
a17a75e2
MW
33
34#include "vme.h"
35#include "vme_bridge.h"
36
733e3ef0 37/* Bitmask and list of registered buses both protected by common mutex */
a17a75e2 38static unsigned int vme_bus_numbers;
733e3ef0
MV
39static LIST_HEAD(vme_bus_list);
40static DEFINE_MUTEX(vme_buses_lock);
a17a75e2 41
ead1f3e3
MW
42static void __exit vme_exit(void);
43static int __init vme_init(void);
a17a75e2
MW
44
45
46/*
47 * Find the bridge resource associated with a specific device resource
48 */
49static struct vme_bridge *dev_to_bridge(struct device *dev)
50{
51 return dev->platform_data;
52}
53
54/*
55 * Find the bridge that the resource is associated with.
56 */
57static struct vme_bridge *find_bridge(struct vme_resource *resource)
58{
59 /* Get list to search */
60 switch (resource->type) {
61 case VME_MASTER:
62 return list_entry(resource->entry, struct vme_master_resource,
63 list)->parent;
64 break;
65 case VME_SLAVE:
66 return list_entry(resource->entry, struct vme_slave_resource,
67 list)->parent;
68 break;
69 case VME_DMA:
70 return list_entry(resource->entry, struct vme_dma_resource,
71 list)->parent;
72 break;
42fb5031
MW
73 case VME_LM:
74 return list_entry(resource->entry, struct vme_lm_resource,
75 list)->parent;
76 break;
a17a75e2
MW
77 default:
78 printk(KERN_ERR "Unknown resource type\n");
79 return NULL;
80 break;
81 }
82}
83
84/*
85 * Allocate a contiguous block of memory for use by the driver. This is used to
86 * create the buffers for the slave windows.
a17a75e2 87 */
ead1f3e3 88void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
a17a75e2
MW
89 dma_addr_t *dma)
90{
91 struct vme_bridge *bridge;
a17a75e2 92
ead1f3e3
MW
93 if (resource == NULL) {
94 printk(KERN_ERR "No resource\n");
a17a75e2
MW
95 return NULL;
96 }
97
98 bridge = find_bridge(resource);
ead1f3e3
MW
99 if (bridge == NULL) {
100 printk(KERN_ERR "Can't find bridge\n");
a17a75e2
MW
101 return NULL;
102 }
103
a17a75e2 104 if (bridge->parent == NULL) {
7f58f025
MV
105 printk(KERN_ERR "Dev entry NULL for"
106 " bridge %s\n", bridge->name);
107 return NULL;
108 }
109
110 if (bridge->alloc_consistent == NULL) {
111 printk(KERN_ERR "alloc_consistent not supported by"
112 " bridge %s\n", bridge->name);
a17a75e2
MW
113 return NULL;
114 }
a17a75e2 115
7f58f025 116 return bridge->alloc_consistent(bridge->parent, size, dma);
a17a75e2
MW
117}
118EXPORT_SYMBOL(vme_alloc_consistent);
119
120/*
121 * Free previously allocated contiguous block of memory.
a17a75e2
MW
122 */
123void vme_free_consistent(struct vme_resource *resource, size_t size,
124 void *vaddr, dma_addr_t dma)
125{
126 struct vme_bridge *bridge;
a17a75e2 127
ead1f3e3
MW
128 if (resource == NULL) {
129 printk(KERN_ERR "No resource\n");
a17a75e2
MW
130 return;
131 }
132
133 bridge = find_bridge(resource);
ead1f3e3
MW
134 if (bridge == NULL) {
135 printk(KERN_ERR "Can't find bridge\n");
a17a75e2
MW
136 return;
137 }
138
7f58f025
MV
139 if (bridge->parent == NULL) {
140 printk(KERN_ERR "Dev entry NULL for"
141 " bridge %s\n", bridge->name);
142 return;
143 }
144
145 if (bridge->free_consistent == NULL) {
146 printk(KERN_ERR "free_consistent not supported by"
147 " bridge %s\n", bridge->name);
148 return;
149 }
a17a75e2 150
7f58f025 151 bridge->free_consistent(bridge->parent, size, vaddr, dma);
a17a75e2
MW
152}
153EXPORT_SYMBOL(vme_free_consistent);
154
155size_t vme_get_size(struct vme_resource *resource)
156{
157 int enabled, retval;
158 unsigned long long base, size;
159 dma_addr_t buf_base;
160 vme_address_t aspace;
161 vme_cycle_t cycle;
162 vme_width_t dwidth;
163
164 switch (resource->type) {
165 case VME_MASTER:
166 retval = vme_master_get(resource, &enabled, &base, &size,
167 &aspace, &cycle, &dwidth);
168
169 return size;
170 break;
171 case VME_SLAVE:
172 retval = vme_slave_get(resource, &enabled, &base, &size,
173 &buf_base, &aspace, &cycle);
174
175 return size;
176 break;
177 case VME_DMA:
178 return 0;
179 break;
180 default:
181 printk(KERN_ERR "Unknown resource type\n");
182 return 0;
183 break;
184 }
185}
186EXPORT_SYMBOL(vme_get_size);
187
188static int vme_check_window(vme_address_t aspace, unsigned long long vme_base,
189 unsigned long long size)
190{
191 int retval = 0;
192
193 switch (aspace) {
194 case VME_A16:
195 if (((vme_base + size) > VME_A16_MAX) ||
196 (vme_base > VME_A16_MAX))
197 retval = -EFAULT;
198 break;
199 case VME_A24:
200 if (((vme_base + size) > VME_A24_MAX) ||
201 (vme_base > VME_A24_MAX))
202 retval = -EFAULT;
203 break;
204 case VME_A32:
205 if (((vme_base + size) > VME_A32_MAX) ||
206 (vme_base > VME_A32_MAX))
207 retval = -EFAULT;
208 break;
209 case VME_A64:
210 /*
211 * Any value held in an unsigned long long can be used as the
212 * base
213 */
214 break;
215 case VME_CRCSR:
216 if (((vme_base + size) > VME_CRCSR_MAX) ||
217 (vme_base > VME_CRCSR_MAX))
218 retval = -EFAULT;
219 break;
220 case VME_USER1:
221 case VME_USER2:
222 case VME_USER3:
223 case VME_USER4:
224 /* User Defined */
225 break;
226 default:
ead1f3e3 227 printk(KERN_ERR "Invalid address space\n");
a17a75e2
MW
228 retval = -EINVAL;
229 break;
230 }
231
232 return retval;
233}
234
235/*
236 * Request a slave image with specific attributes, return some unique
237 * identifier.
238 */
ead1f3e3 239struct vme_resource *vme_slave_request(struct device *dev,
a17a75e2
MW
240 vme_address_t address, vme_cycle_t cycle)
241{
242 struct vme_bridge *bridge;
243 struct list_head *slave_pos = NULL;
244 struct vme_slave_resource *allocated_image = NULL;
245 struct vme_slave_resource *slave_image = NULL;
246 struct vme_resource *resource = NULL;
247
248 bridge = dev_to_bridge(dev);
249 if (bridge == NULL) {
250 printk(KERN_ERR "Can't find VME bus\n");
251 goto err_bus;
252 }
253
254 /* Loop through slave resources */
886953e9 255 list_for_each(slave_pos, &bridge->slave_resources) {
a17a75e2
MW
256 slave_image = list_entry(slave_pos,
257 struct vme_slave_resource, list);
258
259 if (slave_image == NULL) {
ead1f3e3 260 printk(KERN_ERR "Registered NULL Slave resource\n");
a17a75e2
MW
261 continue;
262 }
263
264 /* Find an unlocked and compatible image */
886953e9 265 mutex_lock(&slave_image->mtx);
ead1f3e3 266 if (((slave_image->address_attr & address) == address) &&
a17a75e2
MW
267 ((slave_image->cycle_attr & cycle) == cycle) &&
268 (slave_image->locked == 0)) {
269
270 slave_image->locked = 1;
886953e9 271 mutex_unlock(&slave_image->mtx);
a17a75e2
MW
272 allocated_image = slave_image;
273 break;
274 }
886953e9 275 mutex_unlock(&slave_image->mtx);
a17a75e2
MW
276 }
277
278 /* No free image */
279 if (allocated_image == NULL)
280 goto err_image;
281
282 resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL);
283 if (resource == NULL) {
284 printk(KERN_WARNING "Unable to allocate resource structure\n");
285 goto err_alloc;
286 }
287 resource->type = VME_SLAVE;
886953e9 288 resource->entry = &allocated_image->list;
a17a75e2
MW
289
290 return resource;
291
292err_alloc:
293 /* Unlock image */
886953e9 294 mutex_lock(&slave_image->mtx);
a17a75e2 295 slave_image->locked = 0;
886953e9 296 mutex_unlock(&slave_image->mtx);
a17a75e2
MW
297err_image:
298err_bus:
299 return NULL;
300}
301EXPORT_SYMBOL(vme_slave_request);
302
ead1f3e3 303int vme_slave_set(struct vme_resource *resource, int enabled,
a17a75e2
MW
304 unsigned long long vme_base, unsigned long long size,
305 dma_addr_t buf_base, vme_address_t aspace, vme_cycle_t cycle)
306{
307 struct vme_bridge *bridge = find_bridge(resource);
308 struct vme_slave_resource *image;
309 int retval;
310
311 if (resource->type != VME_SLAVE) {
ead1f3e3 312 printk(KERN_ERR "Not a slave resource\n");
a17a75e2
MW
313 return -EINVAL;
314 }
315
316 image = list_entry(resource->entry, struct vme_slave_resource, list);
317
318 if (bridge->slave_set == NULL) {
ead1f3e3 319 printk(KERN_ERR "Function not supported\n");
a17a75e2
MW
320 return -ENOSYS;
321 }
322
ead1f3e3 323 if (!(((image->address_attr & aspace) == aspace) &&
a17a75e2 324 ((image->cycle_attr & cycle) == cycle))) {
ead1f3e3 325 printk(KERN_ERR "Invalid attributes\n");
a17a75e2
MW
326 return -EINVAL;
327 }
328
329 retval = vme_check_window(aspace, vme_base, size);
ead1f3e3 330 if (retval)
a17a75e2
MW
331 return retval;
332
333 return bridge->slave_set(image, enabled, vme_base, size, buf_base,
334 aspace, cycle);
335}
336EXPORT_SYMBOL(vme_slave_set);
337
ead1f3e3 338int vme_slave_get(struct vme_resource *resource, int *enabled,
a17a75e2
MW
339 unsigned long long *vme_base, unsigned long long *size,
340 dma_addr_t *buf_base, vme_address_t *aspace, vme_cycle_t *cycle)
341{
342 struct vme_bridge *bridge = find_bridge(resource);
343 struct vme_slave_resource *image;
344
345 if (resource->type != VME_SLAVE) {
ead1f3e3 346 printk(KERN_ERR "Not a slave resource\n");
a17a75e2
MW
347 return -EINVAL;
348 }
349
350 image = list_entry(resource->entry, struct vme_slave_resource, list);
351
51a569f7 352 if (bridge->slave_get == NULL) {
ead1f3e3 353 printk(KERN_ERR "vme_slave_get not supported\n");
a17a75e2
MW
354 return -EINVAL;
355 }
356
357 return bridge->slave_get(image, enabled, vme_base, size, buf_base,
358 aspace, cycle);
359}
360EXPORT_SYMBOL(vme_slave_get);
361
362void vme_slave_free(struct vme_resource *resource)
363{
364 struct vme_slave_resource *slave_image;
365
366 if (resource->type != VME_SLAVE) {
ead1f3e3 367 printk(KERN_ERR "Not a slave resource\n");
a17a75e2
MW
368 return;
369 }
370
371 slave_image = list_entry(resource->entry, struct vme_slave_resource,
372 list);
373 if (slave_image == NULL) {
ead1f3e3 374 printk(KERN_ERR "Can't find slave resource\n");
a17a75e2
MW
375 return;
376 }
377
378 /* Unlock image */
886953e9 379 mutex_lock(&slave_image->mtx);
a17a75e2
MW
380 if (slave_image->locked == 0)
381 printk(KERN_ERR "Image is already free\n");
382
383 slave_image->locked = 0;
886953e9 384 mutex_unlock(&slave_image->mtx);
a17a75e2
MW
385
386 /* Free up resource memory */
387 kfree(resource);
388}
389EXPORT_SYMBOL(vme_slave_free);
390
391/*
392 * Request a master image with specific attributes, return some unique
393 * identifier.
394 */
ead1f3e3 395struct vme_resource *vme_master_request(struct device *dev,
a17a75e2
MW
396 vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth)
397{
398 struct vme_bridge *bridge;
399 struct list_head *master_pos = NULL;
400 struct vme_master_resource *allocated_image = NULL;
401 struct vme_master_resource *master_image = NULL;
402 struct vme_resource *resource = NULL;
403
404 bridge = dev_to_bridge(dev);
405 if (bridge == NULL) {
406 printk(KERN_ERR "Can't find VME bus\n");
407 goto err_bus;
408 }
409
410 /* Loop through master resources */
886953e9 411 list_for_each(master_pos, &bridge->master_resources) {
a17a75e2
MW
412 master_image = list_entry(master_pos,
413 struct vme_master_resource, list);
414
415 if (master_image == NULL) {
416 printk(KERN_WARNING "Registered NULL master resource\n");
417 continue;
418 }
419
420 /* Find an unlocked and compatible image */
886953e9 421 spin_lock(&master_image->lock);
ead1f3e3 422 if (((master_image->address_attr & address) == address) &&
a17a75e2
MW
423 ((master_image->cycle_attr & cycle) == cycle) &&
424 ((master_image->width_attr & dwidth) == dwidth) &&
425 (master_image->locked == 0)) {
426
427 master_image->locked = 1;
886953e9 428 spin_unlock(&master_image->lock);
a17a75e2
MW
429 allocated_image = master_image;
430 break;
431 }
886953e9 432 spin_unlock(&master_image->lock);
a17a75e2
MW
433 }
434
435 /* Check to see if we found a resource */
436 if (allocated_image == NULL) {
437 printk(KERN_ERR "Can't find a suitable resource\n");
438 goto err_image;
439 }
440
441 resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL);
442 if (resource == NULL) {
443 printk(KERN_ERR "Unable to allocate resource structure\n");
444 goto err_alloc;
445 }
446 resource->type = VME_MASTER;
886953e9 447 resource->entry = &allocated_image->list;
a17a75e2
MW
448
449 return resource;
450
a17a75e2
MW
451err_alloc:
452 /* Unlock image */
886953e9 453 spin_lock(&master_image->lock);
a17a75e2 454 master_image->locked = 0;
886953e9 455 spin_unlock(&master_image->lock);
a17a75e2
MW
456err_image:
457err_bus:
458 return NULL;
459}
460EXPORT_SYMBOL(vme_master_request);
461
ead1f3e3 462int vme_master_set(struct vme_resource *resource, int enabled,
a17a75e2
MW
463 unsigned long long vme_base, unsigned long long size,
464 vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
465{
466 struct vme_bridge *bridge = find_bridge(resource);
467 struct vme_master_resource *image;
468 int retval;
469
470 if (resource->type != VME_MASTER) {
ead1f3e3 471 printk(KERN_ERR "Not a master resource\n");
a17a75e2
MW
472 return -EINVAL;
473 }
474
475 image = list_entry(resource->entry, struct vme_master_resource, list);
476
477 if (bridge->master_set == NULL) {
ead1f3e3 478 printk(KERN_WARNING "vme_master_set not supported\n");
a17a75e2
MW
479 return -EINVAL;
480 }
481
ead1f3e3 482 if (!(((image->address_attr & aspace) == aspace) &&
a17a75e2
MW
483 ((image->cycle_attr & cycle) == cycle) &&
484 ((image->width_attr & dwidth) == dwidth))) {
ead1f3e3 485 printk(KERN_WARNING "Invalid attributes\n");
a17a75e2
MW
486 return -EINVAL;
487 }
488
489 retval = vme_check_window(aspace, vme_base, size);
ead1f3e3 490 if (retval)
a17a75e2
MW
491 return retval;
492
493 return bridge->master_set(image, enabled, vme_base, size, aspace,
494 cycle, dwidth);
495}
496EXPORT_SYMBOL(vme_master_set);
497
ead1f3e3 498int vme_master_get(struct vme_resource *resource, int *enabled,
a17a75e2
MW
499 unsigned long long *vme_base, unsigned long long *size,
500 vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
501{
502 struct vme_bridge *bridge = find_bridge(resource);
503 struct vme_master_resource *image;
504
505 if (resource->type != VME_MASTER) {
ead1f3e3 506 printk(KERN_ERR "Not a master resource\n");
a17a75e2
MW
507 return -EINVAL;
508 }
509
510 image = list_entry(resource->entry, struct vme_master_resource, list);
511
51a569f7 512 if (bridge->master_get == NULL) {
ead1f3e3 513 printk(KERN_WARNING "vme_master_set not supported\n");
a17a75e2
MW
514 return -EINVAL;
515 }
516
517 return bridge->master_get(image, enabled, vme_base, size, aspace,
518 cycle, dwidth);
519}
520EXPORT_SYMBOL(vme_master_get);
521
522/*
523 * Read data out of VME space into a buffer.
524 */
ead1f3e3 525ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count,
a17a75e2
MW
526 loff_t offset)
527{
528 struct vme_bridge *bridge = find_bridge(resource);
529 struct vme_master_resource *image;
530 size_t length;
531
532 if (bridge->master_read == NULL) {
ead1f3e3 533 printk(KERN_WARNING "Reading from resource not supported\n");
a17a75e2
MW
534 return -EINVAL;
535 }
536
537 if (resource->type != VME_MASTER) {
ead1f3e3 538 printk(KERN_ERR "Not a master resource\n");
a17a75e2
MW
539 return -EINVAL;
540 }
541
542 image = list_entry(resource->entry, struct vme_master_resource, list);
543
544 length = vme_get_size(resource);
545
546 if (offset > length) {
ead1f3e3 547 printk(KERN_WARNING "Invalid Offset\n");
a17a75e2
MW
548 return -EFAULT;
549 }
550
551 if ((offset + count) > length)
552 count = length - offset;
553
554 return bridge->master_read(image, buf, count, offset);
555
556}
557EXPORT_SYMBOL(vme_master_read);
558
559/*
560 * Write data out to VME space from a buffer.
561 */
ead1f3e3 562ssize_t vme_master_write(struct vme_resource *resource, void *buf,
a17a75e2
MW
563 size_t count, loff_t offset)
564{
565 struct vme_bridge *bridge = find_bridge(resource);
566 struct vme_master_resource *image;
567 size_t length;
568
569 if (bridge->master_write == NULL) {
ead1f3e3 570 printk(KERN_WARNING "Writing to resource not supported\n");
a17a75e2
MW
571 return -EINVAL;
572 }
573
574 if (resource->type != VME_MASTER) {
ead1f3e3 575 printk(KERN_ERR "Not a master resource\n");
a17a75e2
MW
576 return -EINVAL;
577 }
578
579 image = list_entry(resource->entry, struct vme_master_resource, list);
580
581 length = vme_get_size(resource);
582
583 if (offset > length) {
ead1f3e3 584 printk(KERN_WARNING "Invalid Offset\n");
a17a75e2
MW
585 return -EFAULT;
586 }
587
588 if ((offset + count) > length)
589 count = length - offset;
590
591 return bridge->master_write(image, buf, count, offset);
592}
593EXPORT_SYMBOL(vme_master_write);
594
595/*
596 * Perform RMW cycle to provided location.
597 */
ead1f3e3 598unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask,
a17a75e2
MW
599 unsigned int compare, unsigned int swap, loff_t offset)
600{
601 struct vme_bridge *bridge = find_bridge(resource);
602 struct vme_master_resource *image;
603
604 if (bridge->master_rmw == NULL) {
ead1f3e3 605 printk(KERN_WARNING "Writing to resource not supported\n");
a17a75e2
MW
606 return -EINVAL;
607 }
608
609 if (resource->type != VME_MASTER) {
ead1f3e3 610 printk(KERN_ERR "Not a master resource\n");
a17a75e2
MW
611 return -EINVAL;
612 }
613
614 image = list_entry(resource->entry, struct vme_master_resource, list);
615
616 return bridge->master_rmw(image, mask, compare, swap, offset);
617}
618EXPORT_SYMBOL(vme_master_rmw);
619
620void vme_master_free(struct vme_resource *resource)
621{
622 struct vme_master_resource *master_image;
623
624 if (resource->type != VME_MASTER) {
ead1f3e3 625 printk(KERN_ERR "Not a master resource\n");
a17a75e2
MW
626 return;
627 }
628
629 master_image = list_entry(resource->entry, struct vme_master_resource,
630 list);
631 if (master_image == NULL) {
ead1f3e3 632 printk(KERN_ERR "Can't find master resource\n");
a17a75e2
MW
633 return;
634 }
635
636 /* Unlock image */
886953e9 637 spin_lock(&master_image->lock);
a17a75e2
MW
638 if (master_image->locked == 0)
639 printk(KERN_ERR "Image is already free\n");
640
641 master_image->locked = 0;
886953e9 642 spin_unlock(&master_image->lock);
a17a75e2
MW
643
644 /* Free up resource memory */
645 kfree(resource);
646}
647EXPORT_SYMBOL(vme_master_free);
648
649/*
650 * Request a DMA controller with specific attributes, return some unique
651 * identifier.
652 */
4f723df4 653struct vme_resource *vme_dma_request(struct device *dev, vme_dma_route_t route)
a17a75e2
MW
654{
655 struct vme_bridge *bridge;
656 struct list_head *dma_pos = NULL;
657 struct vme_dma_resource *allocated_ctrlr = NULL;
658 struct vme_dma_resource *dma_ctrlr = NULL;
659 struct vme_resource *resource = NULL;
660
661 /* XXX Not checking resource attributes */
662 printk(KERN_ERR "No VME resource Attribute tests done\n");
663
664 bridge = dev_to_bridge(dev);
665 if (bridge == NULL) {
666 printk(KERN_ERR "Can't find VME bus\n");
667 goto err_bus;
668 }
669
670 /* Loop through DMA resources */
886953e9 671 list_for_each(dma_pos, &bridge->dma_resources) {
a17a75e2
MW
672 dma_ctrlr = list_entry(dma_pos,
673 struct vme_dma_resource, list);
674
675 if (dma_ctrlr == NULL) {
ead1f3e3 676 printk(KERN_ERR "Registered NULL DMA resource\n");
a17a75e2
MW
677 continue;
678 }
679
4f723df4 680 /* Find an unlocked and compatible controller */
886953e9 681 mutex_lock(&dma_ctrlr->mtx);
4f723df4
MW
682 if (((dma_ctrlr->route_attr & route) == route) &&
683 (dma_ctrlr->locked == 0)) {
684
a17a75e2 685 dma_ctrlr->locked = 1;
886953e9 686 mutex_unlock(&dma_ctrlr->mtx);
a17a75e2
MW
687 allocated_ctrlr = dma_ctrlr;
688 break;
689 }
886953e9 690 mutex_unlock(&dma_ctrlr->mtx);
a17a75e2
MW
691 }
692
693 /* Check to see if we found a resource */
694 if (allocated_ctrlr == NULL)
695 goto err_ctrlr;
696
697 resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL);
698 if (resource == NULL) {
699 printk(KERN_WARNING "Unable to allocate resource structure\n");
700 goto err_alloc;
701 }
702 resource->type = VME_DMA;
886953e9 703 resource->entry = &allocated_ctrlr->list;
a17a75e2
MW
704
705 return resource;
706
707err_alloc:
708 /* Unlock image */
886953e9 709 mutex_lock(&dma_ctrlr->mtx);
a17a75e2 710 dma_ctrlr->locked = 0;
886953e9 711 mutex_unlock(&dma_ctrlr->mtx);
a17a75e2
MW
712err_ctrlr:
713err_bus:
714 return NULL;
715}
58e50798 716EXPORT_SYMBOL(vme_dma_request);
a17a75e2
MW
717
718/*
719 * Start new list
720 */
721struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource)
722{
723 struct vme_dma_resource *ctrlr;
724 struct vme_dma_list *dma_list;
725
726 if (resource->type != VME_DMA) {
ead1f3e3 727 printk(KERN_ERR "Not a DMA resource\n");
a17a75e2
MW
728 return NULL;
729 }
730
731 ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
732
ead1f3e3
MW
733 dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL);
734 if (dma_list == NULL) {
735 printk(KERN_ERR "Unable to allocate memory for new dma list\n");
a17a75e2
MW
736 return NULL;
737 }
886953e9 738 INIT_LIST_HEAD(&dma_list->entries);
a17a75e2 739 dma_list->parent = ctrlr;
886953e9 740 mutex_init(&dma_list->mtx);
a17a75e2
MW
741
742 return dma_list;
743}
744EXPORT_SYMBOL(vme_new_dma_list);
745
746/*
747 * Create "Pattern" type attributes
748 */
749struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern,
750 vme_pattern_t type)
751{
752 struct vme_dma_attr *attributes;
753 struct vme_dma_pattern *pattern_attr;
754
ead1f3e3
MW
755 attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
756 if (attributes == NULL) {
757 printk(KERN_ERR "Unable to allocate memory for attributes "
758 "structure\n");
a17a75e2
MW
759 goto err_attr;
760 }
761
ead1f3e3
MW
762 pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL);
763 if (pattern_attr == NULL) {
764 printk(KERN_ERR "Unable to allocate memory for pattern "
765 "attributes\n");
a17a75e2
MW
766 goto err_pat;
767 }
768
769 attributes->type = VME_DMA_PATTERN;
770 attributes->private = (void *)pattern_attr;
771
772 pattern_attr->pattern = pattern;
773 pattern_attr->type = type;
774
775 return attributes;
776
a17a75e2
MW
777err_pat:
778 kfree(attributes);
779err_attr:
780 return NULL;
781}
782EXPORT_SYMBOL(vme_dma_pattern_attribute);
783
784/*
785 * Create "PCI" type attributes
786 */
787struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address)
788{
789 struct vme_dma_attr *attributes;
790 struct vme_dma_pci *pci_attr;
791
792 /* XXX Run some sanity checks here */
793
ead1f3e3
MW
794 attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
795 if (attributes == NULL) {
796 printk(KERN_ERR "Unable to allocate memory for attributes "
797 "structure\n");
a17a75e2
MW
798 goto err_attr;
799 }
800
ead1f3e3
MW
801 pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL);
802 if (pci_attr == NULL) {
803 printk(KERN_ERR "Unable to allocate memory for pci "
804 "attributes\n");
a17a75e2
MW
805 goto err_pci;
806 }
807
808
809
810 attributes->type = VME_DMA_PCI;
811 attributes->private = (void *)pci_attr;
812
813 pci_attr->address = address;
814
815 return attributes;
816
a17a75e2
MW
817err_pci:
818 kfree(attributes);
819err_attr:
820 return NULL;
821}
822EXPORT_SYMBOL(vme_dma_pci_attribute);
823
824/*
825 * Create "VME" type attributes
826 */
827struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address,
828 vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
829{
830 struct vme_dma_attr *attributes;
831 struct vme_dma_vme *vme_attr;
832
ead1f3e3 833 attributes = kmalloc(
a17a75e2 834 sizeof(struct vme_dma_attr), GFP_KERNEL);
ead1f3e3
MW
835 if (attributes == NULL) {
836 printk(KERN_ERR "Unable to allocate memory for attributes "
837 "structure\n");
a17a75e2
MW
838 goto err_attr;
839 }
840
ead1f3e3
MW
841 vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL);
842 if (vme_attr == NULL) {
843 printk(KERN_ERR "Unable to allocate memory for vme "
844 "attributes\n");
a17a75e2
MW
845 goto err_vme;
846 }
847
848 attributes->type = VME_DMA_VME;
849 attributes->private = (void *)vme_attr;
850
851 vme_attr->address = address;
852 vme_attr->aspace = aspace;
853 vme_attr->cycle = cycle;
854 vme_attr->dwidth = dwidth;
855
856 return attributes;
857
a17a75e2
MW
858err_vme:
859 kfree(attributes);
860err_attr:
861 return NULL;
862}
863EXPORT_SYMBOL(vme_dma_vme_attribute);
864
865/*
866 * Free attribute
867 */
868void vme_dma_free_attribute(struct vme_dma_attr *attributes)
869{
870 kfree(attributes->private);
871 kfree(attributes);
872}
873EXPORT_SYMBOL(vme_dma_free_attribute);
874
875int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
876 struct vme_dma_attr *dest, size_t count)
877{
878 struct vme_bridge *bridge = list->parent->parent;
879 int retval;
880
881 if (bridge->dma_list_add == NULL) {
ead1f3e3 882 printk(KERN_WARNING "Link List DMA generation not supported\n");
a17a75e2
MW
883 return -EINVAL;
884 }
885
886953e9 886 if (!mutex_trylock(&list->mtx)) {
ead1f3e3 887 printk(KERN_ERR "Link List already submitted\n");
a17a75e2
MW
888 return -EINVAL;
889 }
890
891 retval = bridge->dma_list_add(list, src, dest, count);
892
886953e9 893 mutex_unlock(&list->mtx);
a17a75e2
MW
894
895 return retval;
896}
897EXPORT_SYMBOL(vme_dma_list_add);
898
899int vme_dma_list_exec(struct vme_dma_list *list)
900{
901 struct vme_bridge *bridge = list->parent->parent;
902 int retval;
903
904 if (bridge->dma_list_exec == NULL) {
ead1f3e3 905 printk(KERN_ERR "Link List DMA execution not supported\n");
a17a75e2
MW
906 return -EINVAL;
907 }
908
886953e9 909 mutex_lock(&list->mtx);
a17a75e2
MW
910
911 retval = bridge->dma_list_exec(list);
912
886953e9 913 mutex_unlock(&list->mtx);
a17a75e2
MW
914
915 return retval;
916}
917EXPORT_SYMBOL(vme_dma_list_exec);
918
919int vme_dma_list_free(struct vme_dma_list *list)
920{
921 struct vme_bridge *bridge = list->parent->parent;
922 int retval;
923
924 if (bridge->dma_list_empty == NULL) {
ead1f3e3 925 printk(KERN_WARNING "Emptying of Link Lists not supported\n");
a17a75e2
MW
926 return -EINVAL;
927 }
928
886953e9 929 if (!mutex_trylock(&list->mtx)) {
ead1f3e3 930 printk(KERN_ERR "Link List in use\n");
a17a75e2
MW
931 return -EINVAL;
932 }
933
934 /*
935 * Empty out all of the entries from the dma list. We need to go to the
936 * low level driver as dma entries are driver specific.
937 */
938 retval = bridge->dma_list_empty(list);
939 if (retval) {
ead1f3e3 940 printk(KERN_ERR "Unable to empty link-list entries\n");
886953e9 941 mutex_unlock(&list->mtx);
a17a75e2
MW
942 return retval;
943 }
886953e9 944 mutex_unlock(&list->mtx);
a17a75e2
MW
945 kfree(list);
946
947 return retval;
948}
949EXPORT_SYMBOL(vme_dma_list_free);
950
951int vme_dma_free(struct vme_resource *resource)
952{
953 struct vme_dma_resource *ctrlr;
954
955 if (resource->type != VME_DMA) {
ead1f3e3 956 printk(KERN_ERR "Not a DMA resource\n");
a17a75e2
MW
957 return -EINVAL;
958 }
959
960 ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
961
886953e9 962 if (!mutex_trylock(&ctrlr->mtx)) {
ead1f3e3 963 printk(KERN_ERR "Resource busy, can't free\n");
a17a75e2
MW
964 return -EBUSY;
965 }
966
886953e9 967 if (!(list_empty(&ctrlr->pending) && list_empty(&ctrlr->running))) {
ead1f3e3 968 printk(KERN_WARNING "Resource still processing transfers\n");
886953e9 969 mutex_unlock(&ctrlr->mtx);
a17a75e2
MW
970 return -EBUSY;
971 }
972
973 ctrlr->locked = 0;
974
886953e9 975 mutex_unlock(&ctrlr->mtx);
a17a75e2
MW
976
977 return 0;
978}
979EXPORT_SYMBOL(vme_dma_free);
980
c813f592
MW
981void vme_irq_handler(struct vme_bridge *bridge, int level, int statid)
982{
983 void (*call)(int, int, void *);
984 void *priv_data;
985
986 call = bridge->irq[level - 1].callback[statid].func;
987 priv_data = bridge->irq[level - 1].callback[statid].priv_data;
988
989 if (call != NULL)
990 call(level, statid, priv_data);
991 else
992 printk(KERN_WARNING "Spurilous VME interrupt, level:%x, "
993 "vector:%x\n", level, statid);
994}
995EXPORT_SYMBOL(vme_irq_handler);
996
997int vme_irq_request(struct device *dev, int level, int statid,
29848ac9 998 void (*callback)(int, int, void *),
a17a75e2
MW
999 void *priv_data)
1000{
1001 struct vme_bridge *bridge;
1002
1003 bridge = dev_to_bridge(dev);
1004 if (bridge == NULL) {
1005 printk(KERN_ERR "Can't find VME bus\n");
1006 return -EINVAL;
1007 }
1008
ead1f3e3 1009 if ((level < 1) || (level > 7)) {
c813f592 1010 printk(KERN_ERR "Invalid interrupt level\n");
a17a75e2
MW
1011 return -EINVAL;
1012 }
1013
c813f592
MW
1014 if (bridge->irq_set == NULL) {
1015 printk(KERN_ERR "Configuring interrupts not supported\n");
a17a75e2
MW
1016 return -EINVAL;
1017 }
1018
886953e9 1019 mutex_lock(&bridge->irq_mtx);
c813f592
MW
1020
1021 if (bridge->irq[level - 1].callback[statid].func) {
886953e9 1022 mutex_unlock(&bridge->irq_mtx);
c813f592
MW
1023 printk(KERN_WARNING "VME Interrupt already taken\n");
1024 return -EBUSY;
1025 }
1026
1027 bridge->irq[level - 1].count++;
1028 bridge->irq[level - 1].callback[statid].priv_data = priv_data;
1029 bridge->irq[level - 1].callback[statid].func = callback;
1030
1031 /* Enable IRQ level */
29848ac9 1032 bridge->irq_set(bridge, level, 1, 1);
c813f592 1033
886953e9 1034 mutex_unlock(&bridge->irq_mtx);
c813f592
MW
1035
1036 return 0;
a17a75e2 1037}
c813f592 1038EXPORT_SYMBOL(vme_irq_request);
a17a75e2 1039
c813f592 1040void vme_irq_free(struct device *dev, int level, int statid)
a17a75e2
MW
1041{
1042 struct vme_bridge *bridge;
1043
1044 bridge = dev_to_bridge(dev);
1045 if (bridge == NULL) {
1046 printk(KERN_ERR "Can't find VME bus\n");
1047 return;
1048 }
1049
ead1f3e3 1050 if ((level < 1) || (level > 7)) {
c813f592 1051 printk(KERN_ERR "Invalid interrupt level\n");
a17a75e2
MW
1052 return;
1053 }
1054
c813f592
MW
1055 if (bridge->irq_set == NULL) {
1056 printk(KERN_ERR "Configuring interrupts not supported\n");
a17a75e2
MW
1057 return;
1058 }
1059
886953e9 1060 mutex_lock(&bridge->irq_mtx);
c813f592
MW
1061
1062 bridge->irq[level - 1].count--;
1063
1064 /* Disable IRQ level if no more interrupts attached at this level*/
1065 if (bridge->irq[level - 1].count == 0)
29848ac9 1066 bridge->irq_set(bridge, level, 0, 1);
c813f592
MW
1067
1068 bridge->irq[level - 1].callback[statid].func = NULL;
1069 bridge->irq[level - 1].callback[statid].priv_data = NULL;
1070
886953e9 1071 mutex_unlock(&bridge->irq_mtx);
a17a75e2 1072}
c813f592 1073EXPORT_SYMBOL(vme_irq_free);
a17a75e2 1074
c813f592 1075int vme_irq_generate(struct device *dev, int level, int statid)
a17a75e2
MW
1076{
1077 struct vme_bridge *bridge;
1078
1079 bridge = dev_to_bridge(dev);
1080 if (bridge == NULL) {
1081 printk(KERN_ERR "Can't find VME bus\n");
1082 return -EINVAL;
1083 }
1084
ead1f3e3 1085 if ((level < 1) || (level > 7)) {
a17a75e2
MW
1086 printk(KERN_WARNING "Invalid interrupt level\n");
1087 return -EINVAL;
1088 }
1089
c813f592 1090 if (bridge->irq_generate == NULL) {
ead1f3e3 1091 printk(KERN_WARNING "Interrupt generation not supported\n");
a17a75e2
MW
1092 return -EINVAL;
1093 }
1094
29848ac9 1095 return bridge->irq_generate(bridge, level, statid);
a17a75e2 1096}
c813f592 1097EXPORT_SYMBOL(vme_irq_generate);
a17a75e2 1098
42fb5031
MW
1099/*
1100 * Request the location monitor, return resource or NULL
1101 */
1102struct vme_resource *vme_lm_request(struct device *dev)
a17a75e2
MW
1103{
1104 struct vme_bridge *bridge;
42fb5031
MW
1105 struct list_head *lm_pos = NULL;
1106 struct vme_lm_resource *allocated_lm = NULL;
1107 struct vme_lm_resource *lm = NULL;
1108 struct vme_resource *resource = NULL;
a17a75e2
MW
1109
1110 bridge = dev_to_bridge(dev);
1111 if (bridge == NULL) {
1112 printk(KERN_ERR "Can't find VME bus\n");
42fb5031
MW
1113 goto err_bus;
1114 }
1115
1116 /* Loop through DMA resources */
886953e9 1117 list_for_each(lm_pos, &bridge->lm_resources) {
42fb5031
MW
1118 lm = list_entry(lm_pos,
1119 struct vme_lm_resource, list);
1120
1121 if (lm == NULL) {
1122 printk(KERN_ERR "Registered NULL Location Monitor "
1123 "resource\n");
1124 continue;
1125 }
1126
1127 /* Find an unlocked controller */
886953e9 1128 mutex_lock(&lm->mtx);
42fb5031
MW
1129 if (lm->locked == 0) {
1130 lm->locked = 1;
886953e9 1131 mutex_unlock(&lm->mtx);
42fb5031
MW
1132 allocated_lm = lm;
1133 break;
1134 }
886953e9 1135 mutex_unlock(&lm->mtx);
42fb5031
MW
1136 }
1137
1138 /* Check to see if we found a resource */
1139 if (allocated_lm == NULL)
1140 goto err_lm;
1141
1142 resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL);
1143 if (resource == NULL) {
1144 printk(KERN_ERR "Unable to allocate resource structure\n");
1145 goto err_alloc;
1146 }
1147 resource->type = VME_LM;
886953e9 1148 resource->entry = &allocated_lm->list;
42fb5031
MW
1149
1150 return resource;
1151
1152err_alloc:
1153 /* Unlock image */
886953e9 1154 mutex_lock(&lm->mtx);
42fb5031 1155 lm->locked = 0;
886953e9 1156 mutex_unlock(&lm->mtx);
42fb5031
MW
1157err_lm:
1158err_bus:
1159 return NULL;
1160}
1161EXPORT_SYMBOL(vme_lm_request);
1162
1163int vme_lm_count(struct vme_resource *resource)
1164{
1165 struct vme_lm_resource *lm;
1166
1167 if (resource->type != VME_LM) {
1168 printk(KERN_ERR "Not a Location Monitor resource\n");
1169 return -EINVAL;
1170 }
1171
1172 lm = list_entry(resource->entry, struct vme_lm_resource, list);
1173
1174 return lm->monitors;
1175}
1176EXPORT_SYMBOL(vme_lm_count);
1177
1178int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base,
1179 vme_address_t aspace, vme_cycle_t cycle)
1180{
1181 struct vme_bridge *bridge = find_bridge(resource);
1182 struct vme_lm_resource *lm;
1183
1184 if (resource->type != VME_LM) {
1185 printk(KERN_ERR "Not a Location Monitor resource\n");
a17a75e2
MW
1186 return -EINVAL;
1187 }
1188
42fb5031
MW
1189 lm = list_entry(resource->entry, struct vme_lm_resource, list);
1190
a17a75e2 1191 if (bridge->lm_set == NULL) {
42fb5031 1192 printk(KERN_ERR "vme_lm_set not supported\n");
a17a75e2
MW
1193 return -EINVAL;
1194 }
1195
8be9226c 1196 return bridge->lm_set(lm, lm_base, aspace, cycle);
a17a75e2
MW
1197}
1198EXPORT_SYMBOL(vme_lm_set);
1199
42fb5031
MW
1200int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base,
1201 vme_address_t *aspace, vme_cycle_t *cycle)
a17a75e2 1202{
42fb5031
MW
1203 struct vme_bridge *bridge = find_bridge(resource);
1204 struct vme_lm_resource *lm;
a17a75e2 1205
42fb5031
MW
1206 if (resource->type != VME_LM) {
1207 printk(KERN_ERR "Not a Location Monitor resource\n");
a17a75e2
MW
1208 return -EINVAL;
1209 }
1210
42fb5031
MW
1211 lm = list_entry(resource->entry, struct vme_lm_resource, list);
1212
a17a75e2 1213 if (bridge->lm_get == NULL) {
42fb5031 1214 printk(KERN_ERR "vme_lm_get not supported\n");
a17a75e2
MW
1215 return -EINVAL;
1216 }
1217
42fb5031 1218 return bridge->lm_get(lm, lm_base, aspace, cycle);
a17a75e2
MW
1219}
1220EXPORT_SYMBOL(vme_lm_get);
1221
42fb5031
MW
1222int vme_lm_attach(struct vme_resource *resource, int monitor,
1223 void (*callback)(int))
a17a75e2 1224{
42fb5031
MW
1225 struct vme_bridge *bridge = find_bridge(resource);
1226 struct vme_lm_resource *lm;
a17a75e2 1227
42fb5031
MW
1228 if (resource->type != VME_LM) {
1229 printk(KERN_ERR "Not a Location Monitor resource\n");
a17a75e2
MW
1230 return -EINVAL;
1231 }
1232
42fb5031
MW
1233 lm = list_entry(resource->entry, struct vme_lm_resource, list);
1234
a17a75e2 1235 if (bridge->lm_attach == NULL) {
42fb5031 1236 printk(KERN_ERR "vme_lm_attach not supported\n");
a17a75e2
MW
1237 return -EINVAL;
1238 }
1239
42fb5031 1240 return bridge->lm_attach(lm, monitor, callback);
a17a75e2
MW
1241}
1242EXPORT_SYMBOL(vme_lm_attach);
1243
42fb5031 1244int vme_lm_detach(struct vme_resource *resource, int monitor)
a17a75e2 1245{
42fb5031
MW
1246 struct vme_bridge *bridge = find_bridge(resource);
1247 struct vme_lm_resource *lm;
a17a75e2 1248
42fb5031
MW
1249 if (resource->type != VME_LM) {
1250 printk(KERN_ERR "Not a Location Monitor resource\n");
a17a75e2
MW
1251 return -EINVAL;
1252 }
1253
42fb5031
MW
1254 lm = list_entry(resource->entry, struct vme_lm_resource, list);
1255
a17a75e2 1256 if (bridge->lm_detach == NULL) {
42fb5031 1257 printk(KERN_ERR "vme_lm_detach not supported\n");
a17a75e2
MW
1258 return -EINVAL;
1259 }
1260
42fb5031 1261 return bridge->lm_detach(lm, monitor);
a17a75e2
MW
1262}
1263EXPORT_SYMBOL(vme_lm_detach);
1264
42fb5031
MW
1265void vme_lm_free(struct vme_resource *resource)
1266{
1267 struct vme_lm_resource *lm;
1268
1269 if (resource->type != VME_LM) {
1270 printk(KERN_ERR "Not a Location Monitor resource\n");
1271 return;
1272 }
1273
1274 lm = list_entry(resource->entry, struct vme_lm_resource, list);
1275
886953e9 1276 mutex_lock(&lm->mtx);
42fb5031 1277
8be9226c
MW
1278 /* XXX
1279 * Check to see that there aren't any callbacks still attached, if
1280 * there are we should probably be detaching them!
1281 */
42fb5031
MW
1282
1283 lm->locked = 0;
1284
886953e9 1285 mutex_unlock(&lm->mtx);
8be9226c
MW
1286
1287 kfree(resource);
42fb5031
MW
1288}
1289EXPORT_SYMBOL(vme_lm_free);
1290
a17a75e2
MW
1291int vme_slot_get(struct device *bus)
1292{
1293 struct vme_bridge *bridge;
1294
1295 bridge = dev_to_bridge(bus);
1296 if (bridge == NULL) {
1297 printk(KERN_ERR "Can't find VME bus\n");
1298 return -EINVAL;
1299 }
1300
1301 if (bridge->slot_get == NULL) {
ead1f3e3 1302 printk(KERN_WARNING "vme_slot_get not supported\n");
a17a75e2
MW
1303 return -EINVAL;
1304 }
1305
29848ac9 1306 return bridge->slot_get(bridge);
a17a75e2
MW
1307}
1308EXPORT_SYMBOL(vme_slot_get);
1309
1310
1311/* - Bridge Registration --------------------------------------------------- */
1312
733e3ef0 1313static int vme_add_bus(struct vme_bridge *bridge)
a17a75e2
MW
1314{
1315 int i;
733e3ef0 1316 int ret = -1;
a17a75e2 1317
733e3ef0 1318 mutex_lock(&vme_buses_lock);
a17a75e2 1319 for (i = 0; i < sizeof(vme_bus_numbers) * 8; i++) {
733e3ef0
MV
1320 if ((vme_bus_numbers & (1 << i)) == 0) {
1321 vme_bus_numbers |= (1 << i);
1322 bridge->num = i;
1323 list_add_tail(&bridge->bus_list, &vme_bus_list);
1324 ret = 0;
a17a75e2
MW
1325 break;
1326 }
1327 }
733e3ef0 1328 mutex_unlock(&vme_buses_lock);
a17a75e2 1329
733e3ef0 1330 return ret;
a17a75e2
MW
1331}
1332
733e3ef0 1333static void vme_remove_bus(struct vme_bridge *bridge)
a17a75e2 1334{
733e3ef0
MV
1335 mutex_lock(&vme_buses_lock);
1336 vme_bus_numbers &= ~(1 << bridge->num);
1337 list_del(&bridge->bus_list);
1338 mutex_unlock(&vme_buses_lock);
a17a75e2
MW
1339}
1340
ead1f3e3 1341int vme_register_bridge(struct vme_bridge *bridge)
a17a75e2
MW
1342{
1343 struct device *dev;
1344 int retval;
1345 int i;
1346
733e3ef0
MV
1347 retval = vme_add_bus(bridge);
1348 if (retval)
1349 return retval;
a17a75e2
MW
1350
1351 /* This creates 32 vme "slot" devices. This equates to a slot for each
1352 * ID available in a system conforming to the ANSI/VITA 1-1994
1353 * specification.
1354 */
1355 for (i = 0; i < VME_SLOTS_MAX; i++) {
886953e9 1356 dev = &bridge->dev[i];
a17a75e2
MW
1357 memset(dev, 0, sizeof(struct device));
1358
1359 dev->parent = bridge->parent;
886953e9 1360 dev->bus = &vme_bus_type;
a17a75e2
MW
1361 /*
1362 * We save a pointer to the bridge in platform_data so that we
1363 * can get to it later. We keep driver_data for use by the
1364 * driver that binds against the slot
1365 */
1366 dev->platform_data = bridge;
1367 dev_set_name(dev, "vme-%x.%x", bridge->num, i + 1);
1368
1369 retval = device_register(dev);
ead1f3e3 1370 if (retval)
a17a75e2
MW
1371 goto err_reg;
1372 }
1373
1374 return retval;
1375
a17a75e2 1376err_reg:
da1bbd1d 1377 while (--i >= 0) {
886953e9 1378 dev = &bridge->dev[i];
a17a75e2
MW
1379 device_unregister(dev);
1380 }
733e3ef0 1381 vme_remove_bus(bridge);
a17a75e2
MW
1382 return retval;
1383}
1384EXPORT_SYMBOL(vme_register_bridge);
1385
ead1f3e3 1386void vme_unregister_bridge(struct vme_bridge *bridge)
a17a75e2
MW
1387{
1388 int i;
1389 struct device *dev;
1390
1391
1392 for (i = 0; i < VME_SLOTS_MAX; i++) {
886953e9 1393 dev = &bridge->dev[i];
a17a75e2
MW
1394 device_unregister(dev);
1395 }
733e3ef0 1396 vme_remove_bus(bridge);
a17a75e2
MW
1397}
1398EXPORT_SYMBOL(vme_unregister_bridge);
1399
1400
1401/* - Driver Registration --------------------------------------------------- */
1402
ead1f3e3 1403int vme_register_driver(struct vme_driver *drv)
a17a75e2
MW
1404{
1405 drv->driver.name = drv->name;
1406 drv->driver.bus = &vme_bus_type;
1407
1408 return driver_register(&drv->driver);
1409}
1410EXPORT_SYMBOL(vme_register_driver);
1411
ead1f3e3 1412void vme_unregister_driver(struct vme_driver *drv)
a17a75e2
MW
1413{
1414 driver_unregister(&drv->driver);
1415}
1416EXPORT_SYMBOL(vme_unregister_driver);
1417
1418/* - Bus Registration ------------------------------------------------------ */
1419
b1a5fad4 1420static int vme_calc_slot(struct device *dev)
a17a75e2
MW
1421{
1422 struct vme_bridge *bridge;
1423 int num;
1424
1425 bridge = dev_to_bridge(dev);
1426
1427 /* Determine slot number */
1428 num = 0;
ead1f3e3 1429 while (num < VME_SLOTS_MAX) {
886953e9 1430 if (&bridge->dev[num] == dev)
a17a75e2 1431 break;
ead1f3e3 1432
a17a75e2
MW
1433 num++;
1434 }
1435 if (num == VME_SLOTS_MAX) {
1436 dev_err(dev, "Failed to identify slot\n");
1437 num = 0;
1438 goto err_dev;
1439 }
1440 num++;
1441
1442err_dev:
1443 return num;
1444}
1445
1446static struct vme_driver *dev_to_vme_driver(struct device *dev)
1447{
ead1f3e3
MW
1448 if (dev->driver == NULL)
1449 printk(KERN_ERR "Bugger dev->driver is NULL\n");
a17a75e2
MW
1450
1451 return container_of(dev->driver, struct vme_driver, driver);
1452}
1453
1454static int vme_bus_match(struct device *dev, struct device_driver *drv)
1455{
1456 struct vme_bridge *bridge;
1457 struct vme_driver *driver;
1458 int i, num;
1459
1460 bridge = dev_to_bridge(dev);
1461 driver = container_of(drv, struct vme_driver, driver);
1462
1463 num = vme_calc_slot(dev);
1464 if (!num)
1465 goto err_dev;
1466
1467 if (driver->bind_table == NULL) {
1468 dev_err(dev, "Bind table NULL\n");
1469 goto err_table;
1470 }
1471
1472 i = 0;
ead1f3e3 1473 while ((driver->bind_table[i].bus != 0) ||
a17a75e2
MW
1474 (driver->bind_table[i].slot != 0)) {
1475
a37b0dad
MW
1476 if (bridge->num == driver->bind_table[i].bus) {
1477 if (num == driver->bind_table[i].slot)
1478 return 1;
1479
1480 if (driver->bind_table[i].slot == VME_SLOT_ALL)
1481 return 1;
1482
1483 if ((driver->bind_table[i].slot == VME_SLOT_CURRENT) &&
1484 (num == vme_slot_get(dev)))
1485 return 1;
1486 }
a17a75e2
MW
1487 i++;
1488 }
1489
1490err_dev:
1491err_table:
1492 return 0;
1493}
1494
1495static int vme_bus_probe(struct device *dev)
1496{
1497 struct vme_bridge *bridge;
1498 struct vme_driver *driver;
1499 int retval = -ENODEV;
1500
1501 driver = dev_to_vme_driver(dev);
1502 bridge = dev_to_bridge(dev);
1503
ead1f3e3 1504 if (driver->probe != NULL)
a17a75e2 1505 retval = driver->probe(dev, bridge->num, vme_calc_slot(dev));
a17a75e2
MW
1506
1507 return retval;
1508}
1509
1510static int vme_bus_remove(struct device *dev)
1511{
1512 struct vme_bridge *bridge;
1513 struct vme_driver *driver;
1514 int retval = -ENODEV;
1515
1516 driver = dev_to_vme_driver(dev);
1517 bridge = dev_to_bridge(dev);
1518
ead1f3e3 1519 if (driver->remove != NULL)
a17a75e2 1520 retval = driver->remove(dev, bridge->num, vme_calc_slot(dev));
a17a75e2
MW
1521
1522 return retval;
1523}
1524
1525struct bus_type vme_bus_type = {
1526 .name = "vme",
1527 .match = vme_bus_match,
1528 .probe = vme_bus_probe,
1529 .remove = vme_bus_remove,
1530};
1531EXPORT_SYMBOL(vme_bus_type);
1532
ead1f3e3 1533static int __init vme_init(void)
a17a75e2
MW
1534{
1535 return bus_register(&vme_bus_type);
1536}
1537
ead1f3e3 1538static void __exit vme_exit(void)
a17a75e2
MW
1539{
1540 bus_unregister(&vme_bus_type);
1541}
1542
1543MODULE_DESCRIPTION("VME bridge driver framework");
66bd8db5 1544MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
a17a75e2
MW
1545MODULE_LICENSE("GPL");
1546
1547module_init(vme_init);
1548module_exit(vme_exit);
This page took 0.280658 seconds and 5 git commands to generate.