2 * Fake VME bridge support.
4 * This drive provides a fake VME bridge chip, this enables debugging of the
5 * VME framework in the absence of a VME system.
7 * This driver has to do a number of things in software that would be driven
8 * by hardware if it was available, it will also result in extra overhead at
9 * times when compared with driving actual hardware.
11 * Author: Martyn Welch <martyn@welches.me.uk>
12 * Copyright (c) 2014 Martyn Welch
14 * Based on vme_tsi148.c:
16 * Author: Martyn Welch <martyn.welch@ge.com>
17 * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
19 * Based on work by Tom Armistead and Ajit Prem
20 * Copyright 2004 Motorola Inc.
22 * This program is free software; you can redistribute it and/or modify it
23 * under the terms of the GNU General Public License as published by the
24 * Free Software Foundation; either version 2 of the License, or (at your
25 * option) any later version.
28 #include <linux/device.h>
29 #include <linux/errno.h>
30 #include <linux/interrupt.h>
31 #include <linux/module.h>
32 #include <linux/moduleparam.h>
33 #include <linux/slab.h>
34 #include <linux/spinlock.h>
35 #include <linux/types.h>
36 #include <linux/vme.h>
38 #include "../vme_bridge.h"
41 * Define the number of each that the fake driver supports.
43 #define FAKE_MAX_MASTER 8 /* Max Master Windows */
44 #define FAKE_MAX_SLAVE 8 /* Max Slave Windows */
46 /* Structures to hold information normally held in device registers */
47 struct fake_slave_window
{
49 unsigned long long vme_base
;
50 unsigned long long size
;
56 struct fake_master_window
{
58 unsigned long long vme_base
;
59 unsigned long long size
;
65 /* Structure used to hold driver specific information */
67 struct vme_bridge
*parent
;
68 struct fake_slave_window slaves
[FAKE_MAX_SLAVE
];
69 struct fake_master_window masters
[FAKE_MAX_MASTER
];
71 unsigned long long lm_base
;
74 void (*lm_callback
[4])(void *);
76 struct tasklet_struct int_tasklet
;
81 /* Only one VME interrupt can be generated at a time, provide locking */
85 /* Module parameter */
88 static const char driver_name
[] = "vme_fake";
90 static struct vme_bridge
*exit_pointer
;
92 static struct device
*vme_root
;
95 * Calling VME bus interrupt callback if provided.
97 static void fake_VIRQ_tasklet(unsigned long data
)
99 struct vme_bridge
*fake_bridge
;
100 struct fake_driver
*bridge
;
102 fake_bridge
= (struct vme_bridge
*) data
;
103 bridge
= fake_bridge
->driver_priv
;
105 vme_irq_handler(fake_bridge
, bridge
->int_level
, bridge
->int_statid
);
109 * Configure VME interrupt
111 static void fake_irq_set(struct vme_bridge
*fake_bridge
, int level
,
117 static void *fake_pci_to_ptr(dma_addr_t addr
)
119 return (void *)(uintptr_t)addr
;
122 static dma_addr_t
fake_ptr_to_pci(void *addr
)
124 return (dma_addr_t
)(uintptr_t)addr
;
128 * Generate a VME bus interrupt at the requested level & vector. Wait for
129 * interrupt to be acked.
131 static int fake_irq_generate(struct vme_bridge
*fake_bridge
, int level
,
134 struct fake_driver
*bridge
;
136 bridge
= fake_bridge
->driver_priv
;
138 mutex_lock(&bridge
->vme_int
);
140 bridge
->int_level
= level
;
142 bridge
->int_statid
= statid
;
145 * Schedule tasklet to run VME handler to emulate normal VME interrupt
148 tasklet_schedule(&bridge
->int_tasklet
);
150 mutex_unlock(&bridge
->vme_int
);
156 * Initialize a slave window with the requested attributes.
158 static int fake_slave_set(struct vme_slave_resource
*image
, int enabled
,
159 unsigned long long vme_base
, unsigned long long size
,
160 dma_addr_t buf_base
, u32 aspace
, u32 cycle
)
162 unsigned int i
, granularity
= 0;
163 unsigned long long vme_bound
;
164 struct vme_bridge
*fake_bridge
;
165 struct fake_driver
*bridge
;
167 fake_bridge
= image
->parent
;
168 bridge
= fake_bridge
->driver_priv
;
177 granularity
= 0x1000;
180 granularity
= 0x10000;
183 granularity
= 0x10000;
191 pr_err("Invalid address space\n");
196 * Bound address is a valid address for the window, adjust
199 vme_bound
= vme_base
+ size
- granularity
;
201 if (vme_base
& (granularity
- 1)) {
202 pr_err("Invalid VME base alignment\n");
205 if (vme_bound
& (granularity
- 1)) {
206 pr_err("Invalid VME bound alignment\n");
210 mutex_lock(&image
->mtx
);
212 bridge
->slaves
[i
].enabled
= enabled
;
213 bridge
->slaves
[i
].vme_base
= vme_base
;
214 bridge
->slaves
[i
].size
= size
;
215 bridge
->slaves
[i
].buf_base
= fake_pci_to_ptr(buf_base
);
216 bridge
->slaves
[i
].aspace
= aspace
;
217 bridge
->slaves
[i
].cycle
= cycle
;
219 mutex_unlock(&image
->mtx
);
225 * Get slave window configuration.
227 static int fake_slave_get(struct vme_slave_resource
*image
, int *enabled
,
228 unsigned long long *vme_base
, unsigned long long *size
,
229 dma_addr_t
*buf_base
, u32
*aspace
, u32
*cycle
)
232 struct fake_driver
*bridge
;
234 bridge
= image
->parent
->driver_priv
;
238 mutex_lock(&image
->mtx
);
240 *enabled
= bridge
->slaves
[i
].enabled
;
241 *vme_base
= bridge
->slaves
[i
].vme_base
;
242 *size
= bridge
->slaves
[i
].size
;
243 *buf_base
= fake_ptr_to_pci(bridge
->slaves
[i
].buf_base
);
244 *aspace
= bridge
->slaves
[i
].aspace
;
245 *cycle
= bridge
->slaves
[i
].cycle
;
247 mutex_unlock(&image
->mtx
);
253 * Set the attributes of an outbound window.
255 static int fake_master_set(struct vme_master_resource
*image
, int enabled
,
256 unsigned long long vme_base
, unsigned long long size
,
257 u32 aspace
, u32 cycle
, u32 dwidth
)
261 struct vme_bridge
*fake_bridge
;
262 struct fake_driver
*bridge
;
264 fake_bridge
= image
->parent
;
266 bridge
= fake_bridge
->driver_priv
;
268 /* Verify input data */
269 if (vme_base
& 0xFFFF) {
270 pr_err("Invalid VME Window alignment\n");
276 pr_err("Invalid size alignment\n");
281 if ((size
== 0) && (enabled
!= 0)) {
282 pr_err("Size must be non-zero for enabled windows\n");
287 /* Setup data width */
294 pr_err("Invalid data width\n");
299 /* Setup address space */
312 pr_err("Invalid address space\n");
317 spin_lock(&image
->lock
);
321 bridge
->masters
[i
].enabled
= enabled
;
322 bridge
->masters
[i
].vme_base
= vme_base
;
323 bridge
->masters
[i
].size
= size
;
324 bridge
->masters
[i
].aspace
= aspace
;
325 bridge
->masters
[i
].cycle
= cycle
;
326 bridge
->masters
[i
].dwidth
= dwidth
;
328 spin_unlock(&image
->lock
);
340 * Set the attributes of an outbound window.
342 static int __fake_master_get(struct vme_master_resource
*image
, int *enabled
,
343 unsigned long long *vme_base
, unsigned long long *size
,
344 u32
*aspace
, u32
*cycle
, u32
*dwidth
)
347 struct fake_driver
*bridge
;
349 bridge
= image
->parent
->driver_priv
;
353 *enabled
= bridge
->masters
[i
].enabled
;
354 *vme_base
= bridge
->masters
[i
].vme_base
;
355 *size
= bridge
->masters
[i
].size
;
356 *aspace
= bridge
->masters
[i
].aspace
;
357 *cycle
= bridge
->masters
[i
].cycle
;
358 *dwidth
= bridge
->masters
[i
].dwidth
;
364 static int fake_master_get(struct vme_master_resource
*image
, int *enabled
,
365 unsigned long long *vme_base
, unsigned long long *size
,
366 u32
*aspace
, u32
*cycle
, u32
*dwidth
)
370 spin_lock(&image
->lock
);
372 retval
= __fake_master_get(image
, enabled
, vme_base
, size
, aspace
,
375 spin_unlock(&image
->lock
);
381 static void fake_lm_check(struct fake_driver
*bridge
, unsigned long long addr
,
382 u32 aspace
, u32 cycle
)
384 struct vme_bridge
*fake_bridge
;
385 unsigned long long lm_base
;
386 u32 lm_aspace
, lm_cycle
;
388 struct vme_lm_resource
*lm
;
389 struct list_head
*pos
= NULL
, *n
;
392 fake_bridge
= bridge
->parent
;
394 /* Loop through each location monitor resource */
395 list_for_each_safe(pos
, n
, &fake_bridge
->lm_resources
) {
396 lm
= list_entry(pos
, struct vme_lm_resource
, list
);
398 /* If disabled, we're done */
399 if (bridge
->lm_enabled
== 0)
402 lm_base
= bridge
->lm_base
;
403 lm_aspace
= bridge
->lm_aspace
;
404 lm_cycle
= bridge
->lm_cycle
;
406 /* First make sure that the cycle and address space match */
407 if ((lm_aspace
== aspace
) && (lm_cycle
== cycle
)) {
408 for (i
= 0; i
< lm
->monitors
; i
++) {
409 /* Each location monitor covers 8 bytes */
410 if (((lm_base
+ (8 * i
)) <= addr
) &&
411 ((lm_base
+ (8 * i
) + 8) > addr
)) {
412 if (bridge
->lm_callback
[i
])
413 bridge
->lm_callback
[i
](
421 static noinline_for_stack u8
fake_vmeread8(struct fake_driver
*bridge
,
422 unsigned long long addr
,
423 u32 aspace
, u32 cycle
)
427 unsigned long long start
, end
, offset
;
430 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
431 start
= bridge
->slaves
[i
].vme_base
;
432 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
434 if (aspace
!= bridge
->slaves
[i
].aspace
)
437 if (cycle
!= bridge
->slaves
[i
].cycle
)
440 if ((addr
>= start
) && (addr
< end
)) {
441 offset
= addr
- bridge
->slaves
[i
].vme_base
;
442 loc
= (u8
*)(bridge
->slaves
[i
].buf_base
+ offset
);
449 fake_lm_check(bridge
, addr
, aspace
, cycle
);
454 static noinline_for_stack u16
fake_vmeread16(struct fake_driver
*bridge
,
455 unsigned long long addr
,
456 u32 aspace
, u32 cycle
)
460 unsigned long long start
, end
, offset
;
463 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
464 if (aspace
!= bridge
->slaves
[i
].aspace
)
467 if (cycle
!= bridge
->slaves
[i
].cycle
)
470 start
= bridge
->slaves
[i
].vme_base
;
471 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
473 if ((addr
>= start
) && ((addr
+ 1) < end
)) {
474 offset
= addr
- bridge
->slaves
[i
].vme_base
;
475 loc
= (u16
*)(bridge
->slaves
[i
].buf_base
+ offset
);
482 fake_lm_check(bridge
, addr
, aspace
, cycle
);
487 static noinline_for_stack u32
fake_vmeread32(struct fake_driver
*bridge
,
488 unsigned long long addr
,
489 u32 aspace
, u32 cycle
)
491 u32 retval
= 0xffffffff;
493 unsigned long long start
, end
, offset
;
496 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
497 if (aspace
!= bridge
->slaves
[i
].aspace
)
500 if (cycle
!= bridge
->slaves
[i
].cycle
)
503 start
= bridge
->slaves
[i
].vme_base
;
504 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
506 if ((addr
>= start
) && ((addr
+ 3) < end
)) {
507 offset
= addr
- bridge
->slaves
[i
].vme_base
;
508 loc
= (u32
*)(bridge
->slaves
[i
].buf_base
+ offset
);
515 fake_lm_check(bridge
, addr
, aspace
, cycle
);
520 static ssize_t
fake_master_read(struct vme_master_resource
*image
, void *buf
,
521 size_t count
, loff_t offset
)
524 u32 aspace
, cycle
, dwidth
;
525 struct vme_bridge
*fake_bridge
;
526 struct fake_driver
*priv
;
528 unsigned long long addr
;
529 unsigned int done
= 0;
530 unsigned int count32
;
532 fake_bridge
= image
->parent
;
534 priv
= fake_bridge
->driver_priv
;
538 addr
= (unsigned long long)priv
->masters
[i
].vme_base
+ offset
;
539 aspace
= priv
->masters
[i
].aspace
;
540 cycle
= priv
->masters
[i
].cycle
;
541 dwidth
= priv
->masters
[i
].dwidth
;
543 spin_lock(&image
->lock
);
545 /* The following code handles VME address alignment. We cannot use
546 * memcpy_xxx here because it may cut data transfers in to 8-bit
547 * cycles when D16 or D32 cycles are required on the VME bus.
548 * On the other hand, the bridge itself assures that the maximum data
549 * cycle configured for the transfer is used and splits it
550 * automatically for non-aligned addresses, so we don't want the
551 * overhead of needlessly forcing small transfers for the entire cycle.
554 *(u8
*)buf
= fake_vmeread8(priv
, addr
, aspace
, cycle
);
559 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
560 if ((addr
+ done
) & 0x2) {
561 if ((count
- done
) < 2) {
562 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
,
563 addr
+ done
, aspace
, cycle
);
567 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
,
568 addr
+ done
, aspace
, cycle
);
574 if (dwidth
== VME_D32
) {
575 count32
= (count
- done
) & ~0x3;
576 while (done
< count32
) {
577 *(u32
*)(buf
+ done
) = fake_vmeread32(priv
, addr
+ done
,
581 } else if (dwidth
== VME_D16
) {
582 count32
= (count
- done
) & ~0x3;
583 while (done
< count32
) {
584 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
, addr
+ done
,
588 } else if (dwidth
== VME_D8
) {
589 count32
= (count
- done
);
590 while (done
< count32
) {
591 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
, addr
+ done
,
598 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
599 if ((count
- done
) & 0x2) {
600 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
, addr
+ done
,
605 if ((count
- done
) & 0x1) {
606 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
, addr
+ done
, aspace
,
614 spin_unlock(&image
->lock
);
619 static noinline_for_stack
void fake_vmewrite8(struct fake_driver
*bridge
,
620 u8
*buf
, unsigned long long addr
,
621 u32 aspace
, u32 cycle
)
624 unsigned long long start
, end
, offset
;
627 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
628 if (aspace
!= bridge
->slaves
[i
].aspace
)
631 if (cycle
!= bridge
->slaves
[i
].cycle
)
634 start
= bridge
->slaves
[i
].vme_base
;
635 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
637 if ((addr
>= start
) && (addr
< end
)) {
638 offset
= addr
- bridge
->slaves
[i
].vme_base
;
639 loc
= (u8
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
646 fake_lm_check(bridge
, addr
, aspace
, cycle
);
650 static noinline_for_stack
void fake_vmewrite16(struct fake_driver
*bridge
,
651 u16
*buf
, unsigned long long addr
,
652 u32 aspace
, u32 cycle
)
655 unsigned long long start
, end
, offset
;
658 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
659 if (aspace
!= bridge
->slaves
[i
].aspace
)
662 if (cycle
!= bridge
->slaves
[i
].cycle
)
665 start
= bridge
->slaves
[i
].vme_base
;
666 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
668 if ((addr
>= start
) && ((addr
+ 1) < end
)) {
669 offset
= addr
- bridge
->slaves
[i
].vme_base
;
670 loc
= (u16
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
677 fake_lm_check(bridge
, addr
, aspace
, cycle
);
681 static noinline_for_stack
void fake_vmewrite32(struct fake_driver
*bridge
,
682 u32
*buf
, unsigned long long addr
,
683 u32 aspace
, u32 cycle
)
686 unsigned long long start
, end
, offset
;
689 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
690 if (aspace
!= bridge
->slaves
[i
].aspace
)
693 if (cycle
!= bridge
->slaves
[i
].cycle
)
696 start
= bridge
->slaves
[i
].vme_base
;
697 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
699 if ((addr
>= start
) && ((addr
+ 3) < end
)) {
700 offset
= addr
- bridge
->slaves
[i
].vme_base
;
701 loc
= (u32
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
708 fake_lm_check(bridge
, addr
, aspace
, cycle
);
712 static ssize_t
fake_master_write(struct vme_master_resource
*image
, void *buf
,
713 size_t count
, loff_t offset
)
716 u32 aspace
, cycle
, dwidth
;
717 unsigned long long addr
;
719 unsigned int done
= 0;
720 unsigned int count32
;
722 struct vme_bridge
*fake_bridge
;
723 struct fake_driver
*bridge
;
725 fake_bridge
= image
->parent
;
727 bridge
= fake_bridge
->driver_priv
;
731 addr
= bridge
->masters
[i
].vme_base
+ offset
;
732 aspace
= bridge
->masters
[i
].aspace
;
733 cycle
= bridge
->masters
[i
].cycle
;
734 dwidth
= bridge
->masters
[i
].dwidth
;
736 spin_lock(&image
->lock
);
738 /* Here we apply for the same strategy we do in master_read
739 * function in order to assure the correct cycles.
742 fake_vmewrite8(bridge
, (u8
*)buf
, addr
, aspace
, cycle
);
748 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
749 if ((addr
+ done
) & 0x2) {
750 if ((count
- done
) < 2) {
751 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
),
752 addr
+ done
, aspace
, cycle
);
756 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
757 addr
+ done
, aspace
, cycle
);
763 if (dwidth
== VME_D32
) {
764 count32
= (count
- done
) & ~0x3;
765 while (done
< count32
) {
766 fake_vmewrite32(bridge
, (u32
*)(buf
+ done
),
767 addr
+ done
, aspace
, cycle
);
770 } else if (dwidth
== VME_D16
) {
771 count32
= (count
- done
) & ~0x3;
772 while (done
< count32
) {
773 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
774 addr
+ done
, aspace
, cycle
);
777 } else if (dwidth
== VME_D8
) {
778 count32
= (count
- done
);
779 while (done
< count32
) {
780 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
), addr
+ done
,
787 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
788 if ((count
- done
) & 0x2) {
789 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
790 addr
+ done
, aspace
, cycle
);
795 if ((count
- done
) & 0x1) {
796 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
), addr
+ done
, aspace
,
804 spin_unlock(&image
->lock
);
810 * Perform an RMW cycle on the VME bus.
812 * Requires a previously configured master window, returns final value.
814 static unsigned int fake_master_rmw(struct vme_master_resource
*image
,
815 unsigned int mask
, unsigned int compare
, unsigned int swap
,
821 struct fake_driver
*bridge
;
823 bridge
= image
->parent
->driver_priv
;
825 /* Find the PCI address that maps to the desired VME address */
828 base
= bridge
->masters
[i
].vme_base
;
829 aspace
= bridge
->masters
[i
].aspace
;
830 cycle
= bridge
->masters
[i
].cycle
;
833 spin_lock(&image
->lock
);
835 /* Read existing value */
836 tmp
= fake_vmeread32(bridge
, base
+ offset
, aspace
, cycle
);
839 if ((tmp
&& mask
) == (compare
&& mask
)) {
840 tmp
= tmp
| (mask
| swap
);
841 tmp
= tmp
& (~mask
| swap
);
844 fake_vmewrite32(bridge
, &tmp
, base
+ offset
, aspace
, cycle
);
848 spin_unlock(&image
->lock
);
854 * All 4 location monitors reside at the same base - this is therefore a
855 * system wide configuration.
857 * This does not enable the LM monitor - that should be done when the first
858 * callback is attached and disabled when the last callback is removed.
860 static int fake_lm_set(struct vme_lm_resource
*lm
, unsigned long long lm_base
,
861 u32 aspace
, u32 cycle
)
864 struct vme_bridge
*fake_bridge
;
865 struct fake_driver
*bridge
;
867 fake_bridge
= lm
->parent
;
869 bridge
= fake_bridge
->driver_priv
;
871 mutex_lock(&lm
->mtx
);
873 /* If we already have a callback attached, we can't move it! */
874 for (i
= 0; i
< lm
->monitors
; i
++) {
875 if (bridge
->lm_callback
[i
]) {
876 mutex_unlock(&lm
->mtx
);
877 pr_err("Location monitor callback attached, can't reset\n");
889 mutex_unlock(&lm
->mtx
);
890 pr_err("Invalid address space\n");
894 bridge
->lm_base
= lm_base
;
895 bridge
->lm_aspace
= aspace
;
896 bridge
->lm_cycle
= cycle
;
898 mutex_unlock(&lm
->mtx
);
903 /* Get configuration of the callback monitor and return whether it is enabled
906 static int fake_lm_get(struct vme_lm_resource
*lm
,
907 unsigned long long *lm_base
, u32
*aspace
, u32
*cycle
)
909 struct fake_driver
*bridge
;
911 bridge
= lm
->parent
->driver_priv
;
913 mutex_lock(&lm
->mtx
);
915 *lm_base
= bridge
->lm_base
;
916 *aspace
= bridge
->lm_aspace
;
917 *cycle
= bridge
->lm_cycle
;
919 mutex_unlock(&lm
->mtx
);
921 return bridge
->lm_enabled
;
925 * Attach a callback to a specific location monitor.
927 * Callback will be passed the monitor triggered.
929 static int fake_lm_attach(struct vme_lm_resource
*lm
, int monitor
,
930 void (*callback
)(void *), void *data
)
932 struct vme_bridge
*fake_bridge
;
933 struct fake_driver
*bridge
;
935 fake_bridge
= lm
->parent
;
937 bridge
= fake_bridge
->driver_priv
;
939 mutex_lock(&lm
->mtx
);
941 /* Ensure that the location monitor is configured - need PGM or DATA */
942 if (bridge
->lm_cycle
== 0) {
943 mutex_unlock(&lm
->mtx
);
944 pr_err("Location monitor not properly configured\n");
948 /* Check that a callback isn't already attached */
949 if (bridge
->lm_callback
[monitor
]) {
950 mutex_unlock(&lm
->mtx
);
951 pr_err("Existing callback attached\n");
955 /* Attach callback */
956 bridge
->lm_callback
[monitor
] = callback
;
957 bridge
->lm_data
[monitor
] = data
;
959 /* Ensure that global Location Monitor Enable set */
960 bridge
->lm_enabled
= 1;
962 mutex_unlock(&lm
->mtx
);
968 * Detach a callback function forn a specific location monitor.
970 static int fake_lm_detach(struct vme_lm_resource
*lm
, int monitor
)
974 struct fake_driver
*bridge
;
976 bridge
= lm
->parent
->driver_priv
;
978 mutex_lock(&lm
->mtx
);
980 /* Detach callback */
981 bridge
->lm_callback
[monitor
] = NULL
;
982 bridge
->lm_data
[monitor
] = NULL
;
984 /* If all location monitors disabled, disable global Location Monitor */
986 for (i
= 0; i
< lm
->monitors
; i
++) {
987 if (bridge
->lm_callback
[i
])
992 bridge
->lm_enabled
= 0;
994 mutex_unlock(&lm
->mtx
);
1000 * Determine Geographical Addressing
1002 static int fake_slot_get(struct vme_bridge
*fake_bridge
)
1007 static void *fake_alloc_consistent(struct device
*parent
, size_t size
,
1010 void *alloc
= kmalloc(size
, GFP_KERNEL
);
1013 *dma
= fake_ptr_to_pci(alloc
);
1018 static void fake_free_consistent(struct device
*parent
, size_t size
,
1019 void *vaddr
, dma_addr_t dma
)
1023 dma_free_coherent(parent, size, vaddr, dma);
1028 * Configure CR/CSR space
1030 * Access to the CR/CSR can be configured at power-up. The location of the
1031 * CR/CSR registers in the CR/CSR address space is determined by the boards
1032 * Geographic address.
1034 * Each board has a 512kB window, with the highest 4kB being used for the
1035 * boards registers, this means there is a fix length 508kB window which must
1036 * be mapped onto PCI memory.
1038 static int fake_crcsr_init(struct vme_bridge
*fake_bridge
)
1041 struct fake_driver
*bridge
;
1043 bridge
= fake_bridge
->driver_priv
;
1045 /* Allocate mem for CR/CSR image */
1046 bridge
->crcsr_kernel
= kzalloc(VME_CRCSR_BUF_SIZE
, GFP_KERNEL
);
1047 bridge
->crcsr_bus
= fake_ptr_to_pci(bridge
->crcsr_kernel
);
1048 if (!bridge
->crcsr_kernel
)
1051 vstat
= fake_slot_get(fake_bridge
);
1053 pr_info("CR/CSR Offset: %d\n", vstat
);
1058 static void fake_crcsr_exit(struct vme_bridge
*fake_bridge
)
1060 struct fake_driver
*bridge
;
1062 bridge
= fake_bridge
->driver_priv
;
1064 kfree(bridge
->crcsr_kernel
);
1068 static int __init
fake_init(void)
1071 struct list_head
*pos
= NULL
, *n
;
1072 struct vme_bridge
*fake_bridge
;
1073 struct fake_driver
*fake_device
;
1074 struct vme_master_resource
*master_image
;
1075 struct vme_slave_resource
*slave_image
;
1076 struct vme_lm_resource
*lm
;
1078 /* We need a fake parent device */
1079 vme_root
= __root_device_register("vme", THIS_MODULE
);
1081 /* If we want to support more than one bridge at some point, we need to
1082 * dynamically allocate this so we get one per device.
1084 fake_bridge
= kzalloc(sizeof(*fake_bridge
), GFP_KERNEL
);
1090 fake_device
= kzalloc(sizeof(*fake_device
), GFP_KERNEL
);
1096 fake_bridge
->driver_priv
= fake_device
;
1098 fake_bridge
->parent
= vme_root
;
1100 fake_device
->parent
= fake_bridge
;
1102 /* Initialize wait queues & mutual exclusion flags */
1103 mutex_init(&fake_device
->vme_int
);
1104 mutex_init(&fake_bridge
->irq_mtx
);
1105 tasklet_init(&fake_device
->int_tasklet
, fake_VIRQ_tasklet
,
1106 (unsigned long) fake_bridge
);
1108 strcpy(fake_bridge
->name
, driver_name
);
1110 /* Add master windows to list */
1111 INIT_LIST_HEAD(&fake_bridge
->master_resources
);
1112 for (i
= 0; i
< FAKE_MAX_MASTER
; i
++) {
1113 master_image
= kmalloc(sizeof(*master_image
), GFP_KERNEL
);
1114 if (!master_image
) {
1118 master_image
->parent
= fake_bridge
;
1119 spin_lock_init(&master_image
->lock
);
1120 master_image
->locked
= 0;
1121 master_image
->number
= i
;
1122 master_image
->address_attr
= VME_A16
| VME_A24
| VME_A32
|
1124 master_image
->cycle_attr
= VME_SCT
| VME_BLT
| VME_MBLT
|
1125 VME_2eVME
| VME_2eSST
| VME_2eSSTB
| VME_2eSST160
|
1126 VME_2eSST267
| VME_2eSST320
| VME_SUPER
| VME_USER
|
1127 VME_PROG
| VME_DATA
;
1128 master_image
->width_attr
= VME_D16
| VME_D32
;
1129 memset(&master_image
->bus_resource
, 0,
1130 sizeof(struct resource
));
1131 master_image
->kern_base
= NULL
;
1132 list_add_tail(&master_image
->list
,
1133 &fake_bridge
->master_resources
);
1136 /* Add slave windows to list */
1137 INIT_LIST_HEAD(&fake_bridge
->slave_resources
);
1138 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
1139 slave_image
= kmalloc(sizeof(*slave_image
), GFP_KERNEL
);
1144 slave_image
->parent
= fake_bridge
;
1145 mutex_init(&slave_image
->mtx
);
1146 slave_image
->locked
= 0;
1147 slave_image
->number
= i
;
1148 slave_image
->address_attr
= VME_A16
| VME_A24
| VME_A32
|
1149 VME_A64
| VME_CRCSR
| VME_USER1
| VME_USER2
|
1150 VME_USER3
| VME_USER4
;
1151 slave_image
->cycle_attr
= VME_SCT
| VME_BLT
| VME_MBLT
|
1152 VME_2eVME
| VME_2eSST
| VME_2eSSTB
| VME_2eSST160
|
1153 VME_2eSST267
| VME_2eSST320
| VME_SUPER
| VME_USER
|
1154 VME_PROG
| VME_DATA
;
1155 list_add_tail(&slave_image
->list
,
1156 &fake_bridge
->slave_resources
);
1159 /* Add location monitor to list */
1160 INIT_LIST_HEAD(&fake_bridge
->lm_resources
);
1161 lm
= kmalloc(sizeof(*lm
), GFP_KERNEL
);
1166 lm
->parent
= fake_bridge
;
1167 mutex_init(&lm
->mtx
);
1171 list_add_tail(&lm
->list
, &fake_bridge
->lm_resources
);
1173 fake_bridge
->slave_get
= fake_slave_get
;
1174 fake_bridge
->slave_set
= fake_slave_set
;
1175 fake_bridge
->master_get
= fake_master_get
;
1176 fake_bridge
->master_set
= fake_master_set
;
1177 fake_bridge
->master_read
= fake_master_read
;
1178 fake_bridge
->master_write
= fake_master_write
;
1179 fake_bridge
->master_rmw
= fake_master_rmw
;
1180 fake_bridge
->irq_set
= fake_irq_set
;
1181 fake_bridge
->irq_generate
= fake_irq_generate
;
1182 fake_bridge
->lm_set
= fake_lm_set
;
1183 fake_bridge
->lm_get
= fake_lm_get
;
1184 fake_bridge
->lm_attach
= fake_lm_attach
;
1185 fake_bridge
->lm_detach
= fake_lm_detach
;
1186 fake_bridge
->slot_get
= fake_slot_get
;
1187 fake_bridge
->alloc_consistent
= fake_alloc_consistent
;
1188 fake_bridge
->free_consistent
= fake_free_consistent
;
1190 pr_info("Board is%s the VME system controller\n",
1191 (geoid
== 1) ? "" : " not");
1193 pr_info("VME geographical address is set to %d\n", geoid
);
1195 retval
= fake_crcsr_init(fake_bridge
);
1197 pr_err("CR/CSR configuration failed.\n");
1201 retval
= vme_register_bridge(fake_bridge
);
1203 pr_err("Chip Registration failed.\n");
1207 exit_pointer
= fake_bridge
;
1212 fake_crcsr_exit(fake_bridge
);
1215 /* resources are stored in link list */
1216 list_for_each_safe(pos
, n
, &fake_bridge
->lm_resources
) {
1217 lm
= list_entry(pos
, struct vme_lm_resource
, list
);
1222 /* resources are stored in link list */
1223 list_for_each_safe(pos
, n
, &fake_bridge
->slave_resources
) {
1224 slave_image
= list_entry(pos
, struct vme_slave_resource
, list
);
1229 /* resources are stored in link list */
1230 list_for_each_safe(pos
, n
, &fake_bridge
->master_resources
) {
1231 master_image
= list_entry(pos
, struct vme_master_resource
,
1234 kfree(master_image
);
1246 static void __exit
fake_exit(void)
1248 struct list_head
*pos
= NULL
;
1249 struct list_head
*tmplist
;
1250 struct vme_master_resource
*master_image
;
1251 struct vme_slave_resource
*slave_image
;
1253 struct vme_bridge
*fake_bridge
;
1254 struct fake_driver
*bridge
;
1256 fake_bridge
= exit_pointer
;
1258 bridge
= fake_bridge
->driver_priv
;
1260 pr_debug("Driver is being unloaded.\n");
1263 * Shutdown all inbound and outbound windows.
1265 for (i
= 0; i
< FAKE_MAX_MASTER
; i
++)
1266 bridge
->masters
[i
].enabled
= 0;
1268 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++)
1269 bridge
->slaves
[i
].enabled
= 0;
1272 * Shutdown Location monitor.
1274 bridge
->lm_enabled
= 0;
1276 vme_unregister_bridge(fake_bridge
);
1278 fake_crcsr_exit(fake_bridge
);
1279 /* resources are stored in link list */
1280 list_for_each_safe(pos
, tmplist
, &fake_bridge
->slave_resources
) {
1281 slave_image
= list_entry(pos
, struct vme_slave_resource
, list
);
1286 /* resources are stored in link list */
1287 list_for_each_safe(pos
, tmplist
, &fake_bridge
->master_resources
) {
1288 master_image
= list_entry(pos
, struct vme_master_resource
,
1291 kfree(master_image
);
1294 kfree(fake_bridge
->driver_priv
);
1298 root_device_unregister(vme_root
);
1302 MODULE_PARM_DESC(geoid
, "Set geographical addressing");
1303 module_param(geoid
, int, 0);
1305 MODULE_DESCRIPTION("Fake VME bridge driver");
1306 MODULE_LICENSE("GPL");
1308 module_init(fake_init
);
1309 module_exit(fake_exit
);