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
] != NULL
)
413 bridge
->lm_callback
[i
](
421 static u8
fake_vmeread8(struct fake_driver
*bridge
, unsigned long long addr
,
422 u32 aspace
, u32 cycle
)
426 unsigned long long start
, end
, offset
;
429 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
430 start
= bridge
->slaves
[i
].vme_base
;
431 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
433 if (aspace
!= bridge
->slaves
[i
].aspace
)
436 if (cycle
!= bridge
->slaves
[i
].cycle
)
439 if ((addr
>= start
) && (addr
< end
)) {
440 offset
= addr
- bridge
->slaves
[i
].vme_base
;
441 loc
= (u8
*)(bridge
->slaves
[i
].buf_base
+ offset
);
448 fake_lm_check(bridge
, addr
, aspace
, cycle
);
453 static u16
fake_vmeread16(struct fake_driver
*bridge
, unsigned long long addr
,
454 u32 aspace
, u32 cycle
)
458 unsigned long long start
, end
, offset
;
461 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
462 if (aspace
!= bridge
->slaves
[i
].aspace
)
465 if (cycle
!= bridge
->slaves
[i
].cycle
)
468 start
= bridge
->slaves
[i
].vme_base
;
469 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
471 if ((addr
>= start
) && ((addr
+ 1) < end
)) {
472 offset
= addr
- bridge
->slaves
[i
].vme_base
;
473 loc
= (u16
*)(bridge
->slaves
[i
].buf_base
+ offset
);
480 fake_lm_check(bridge
, addr
, aspace
, cycle
);
485 static u32
fake_vmeread32(struct fake_driver
*bridge
, unsigned long long addr
,
486 u32 aspace
, u32 cycle
)
488 u32 retval
= 0xffffffff;
490 unsigned long long start
, end
, offset
;
493 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
494 if (aspace
!= bridge
->slaves
[i
].aspace
)
497 if (cycle
!= bridge
->slaves
[i
].cycle
)
500 start
= bridge
->slaves
[i
].vme_base
;
501 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
503 if ((addr
>= start
) && ((addr
+ 3) < end
)) {
504 offset
= addr
- bridge
->slaves
[i
].vme_base
;
505 loc
= (u32
*)(bridge
->slaves
[i
].buf_base
+ offset
);
512 fake_lm_check(bridge
, addr
, aspace
, cycle
);
517 static ssize_t
fake_master_read(struct vme_master_resource
*image
, void *buf
,
518 size_t count
, loff_t offset
)
521 u32 aspace
, cycle
, dwidth
;
522 struct vme_bridge
*fake_bridge
;
523 struct fake_driver
*priv
;
525 unsigned long long addr
;
526 unsigned int done
= 0;
527 unsigned int count32
;
529 fake_bridge
= image
->parent
;
531 priv
= fake_bridge
->driver_priv
;
535 addr
= (unsigned long long)priv
->masters
[i
].vme_base
+ offset
;
536 aspace
= priv
->masters
[i
].aspace
;
537 cycle
= priv
->masters
[i
].cycle
;
538 dwidth
= priv
->masters
[i
].dwidth
;
540 spin_lock(&image
->lock
);
542 /* The following code handles VME address alignment. We cannot use
543 * memcpy_xxx here because it may cut data transfers in to 8-bit
544 * cycles when D16 or D32 cycles are required on the VME bus.
545 * On the other hand, the bridge itself assures that the maximum data
546 * cycle configured for the transfer is used and splits it
547 * automatically for non-aligned addresses, so we don't want the
548 * overhead of needlessly forcing small transfers for the entire cycle.
551 *(u8
*)buf
= fake_vmeread8(priv
, addr
, aspace
, cycle
);
556 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
557 if ((addr
+ done
) & 0x2) {
558 if ((count
- done
) < 2) {
559 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
,
560 addr
+ done
, aspace
, cycle
);
564 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
,
565 addr
+ done
, aspace
, cycle
);
571 if (dwidth
== VME_D32
) {
572 count32
= (count
- done
) & ~0x3;
573 while (done
< count32
) {
574 *(u32
*)(buf
+ done
) = fake_vmeread32(priv
, addr
+ done
,
578 } else if (dwidth
== VME_D16
) {
579 count32
= (count
- done
) & ~0x3;
580 while (done
< count32
) {
581 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
, addr
+ done
,
585 } else if (dwidth
== VME_D8
) {
586 count32
= (count
- done
);
587 while (done
< count32
) {
588 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
, addr
+ done
,
595 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
596 if ((count
- done
) & 0x2) {
597 *(u16
*)(buf
+ done
) = fake_vmeread16(priv
, addr
+ done
,
602 if ((count
- done
) & 0x1) {
603 *(u8
*)(buf
+ done
) = fake_vmeread8(priv
, addr
+ done
, aspace
,
611 spin_unlock(&image
->lock
);
616 static void fake_vmewrite8(struct fake_driver
*bridge
, u8
*buf
,
617 unsigned long long addr
, u32 aspace
, u32 cycle
)
620 unsigned long long start
, end
, offset
;
623 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
624 if (aspace
!= bridge
->slaves
[i
].aspace
)
627 if (cycle
!= bridge
->slaves
[i
].cycle
)
630 start
= bridge
->slaves
[i
].vme_base
;
631 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
633 if ((addr
>= start
) && (addr
< end
)) {
634 offset
= addr
- bridge
->slaves
[i
].vme_base
;
635 loc
= (u8
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
642 fake_lm_check(bridge
, addr
, aspace
, cycle
);
646 static void fake_vmewrite16(struct fake_driver
*bridge
, u16
*buf
,
647 unsigned long long addr
, u32 aspace
, u32 cycle
)
650 unsigned long long start
, end
, offset
;
653 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
654 if (aspace
!= bridge
->slaves
[i
].aspace
)
657 if (cycle
!= bridge
->slaves
[i
].cycle
)
660 start
= bridge
->slaves
[i
].vme_base
;
661 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
663 if ((addr
>= start
) && ((addr
+ 1) < end
)) {
664 offset
= addr
- bridge
->slaves
[i
].vme_base
;
665 loc
= (u16
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
672 fake_lm_check(bridge
, addr
, aspace
, cycle
);
676 static void fake_vmewrite32(struct fake_driver
*bridge
, u32
*buf
,
677 unsigned long long addr
, u32 aspace
, u32 cycle
)
680 unsigned long long start
, end
, offset
;
683 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
684 if (aspace
!= bridge
->slaves
[i
].aspace
)
687 if (cycle
!= bridge
->slaves
[i
].cycle
)
690 start
= bridge
->slaves
[i
].vme_base
;
691 end
= bridge
->slaves
[i
].vme_base
+ bridge
->slaves
[i
].size
;
693 if ((addr
>= start
) && ((addr
+ 3) < end
)) {
694 offset
= addr
- bridge
->slaves
[i
].vme_base
;
695 loc
= (u32
*)((void *)bridge
->slaves
[i
].buf_base
+ offset
);
702 fake_lm_check(bridge
, addr
, aspace
, cycle
);
706 static ssize_t
fake_master_write(struct vme_master_resource
*image
, void *buf
,
707 size_t count
, loff_t offset
)
710 u32 aspace
, cycle
, dwidth
;
711 unsigned long long addr
;
713 unsigned int done
= 0;
714 unsigned int count32
;
716 struct vme_bridge
*fake_bridge
;
717 struct fake_driver
*bridge
;
719 fake_bridge
= image
->parent
;
721 bridge
= fake_bridge
->driver_priv
;
725 addr
= bridge
->masters
[i
].vme_base
+ offset
;
726 aspace
= bridge
->masters
[i
].aspace
;
727 cycle
= bridge
->masters
[i
].cycle
;
728 dwidth
= bridge
->masters
[i
].dwidth
;
730 spin_lock(&image
->lock
);
732 /* Here we apply for the same strategy we do in master_read
733 * function in order to assure the correct cycles.
736 fake_vmewrite8(bridge
, (u8
*)buf
, addr
, aspace
, cycle
);
742 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
743 if ((addr
+ done
) & 0x2) {
744 if ((count
- done
) < 2) {
745 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
),
746 addr
+ done
, aspace
, cycle
);
750 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
751 addr
+ done
, aspace
, cycle
);
757 if (dwidth
== VME_D32
) {
758 count32
= (count
- done
) & ~0x3;
759 while (done
< count32
) {
760 fake_vmewrite32(bridge
, (u32
*)(buf
+ done
),
761 addr
+ done
, aspace
, cycle
);
764 } else if (dwidth
== VME_D16
) {
765 count32
= (count
- done
) & ~0x3;
766 while (done
< count32
) {
767 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
768 addr
+ done
, aspace
, cycle
);
771 } else if (dwidth
== VME_D8
) {
772 count32
= (count
- done
);
773 while (done
< count32
) {
774 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
), addr
+ done
,
781 if ((dwidth
== VME_D16
) || (dwidth
== VME_D32
)) {
782 if ((count
- done
) & 0x2) {
783 fake_vmewrite16(bridge
, (u16
*)(buf
+ done
),
784 addr
+ done
, aspace
, cycle
);
789 if ((count
- done
) & 0x1) {
790 fake_vmewrite8(bridge
, (u8
*)(buf
+ done
), addr
+ done
, aspace
,
798 spin_unlock(&image
->lock
);
804 * Perform an RMW cycle on the VME bus.
806 * Requires a previously configured master window, returns final value.
808 static unsigned int fake_master_rmw(struct vme_master_resource
*image
,
809 unsigned int mask
, unsigned int compare
, unsigned int swap
,
815 struct fake_driver
*bridge
;
817 bridge
= image
->parent
->driver_priv
;
819 /* Find the PCI address that maps to the desired VME address */
822 base
= bridge
->masters
[i
].vme_base
;
823 aspace
= bridge
->masters
[i
].aspace
;
824 cycle
= bridge
->masters
[i
].cycle
;
827 spin_lock(&image
->lock
);
829 /* Read existing value */
830 tmp
= fake_vmeread32(bridge
, base
+ offset
, aspace
, cycle
);
833 if ((tmp
&& mask
) == (compare
&& mask
)) {
834 tmp
= tmp
| (mask
| swap
);
835 tmp
= tmp
& (~mask
| swap
);
838 fake_vmewrite32(bridge
, &tmp
, base
+ offset
, aspace
, cycle
);
842 spin_unlock(&image
->lock
);
848 * All 4 location monitors reside at the same base - this is therefore a
849 * system wide configuration.
851 * This does not enable the LM monitor - that should be done when the first
852 * callback is attached and disabled when the last callback is removed.
854 static int fake_lm_set(struct vme_lm_resource
*lm
, unsigned long long lm_base
,
855 u32 aspace
, u32 cycle
)
858 struct vme_bridge
*fake_bridge
;
859 struct fake_driver
*bridge
;
861 fake_bridge
= lm
->parent
;
863 bridge
= fake_bridge
->driver_priv
;
865 mutex_lock(&lm
->mtx
);
867 /* If we already have a callback attached, we can't move it! */
868 for (i
= 0; i
< lm
->monitors
; i
++) {
869 if (bridge
->lm_callback
[i
] != NULL
) {
870 mutex_unlock(&lm
->mtx
);
871 pr_err("Location monitor callback attached, can't reset\n");
883 mutex_unlock(&lm
->mtx
);
884 pr_err("Invalid address space\n");
888 bridge
->lm_base
= lm_base
;
889 bridge
->lm_aspace
= aspace
;
890 bridge
->lm_cycle
= cycle
;
892 mutex_unlock(&lm
->mtx
);
897 /* Get configuration of the callback monitor and return whether it is enabled
900 static int fake_lm_get(struct vme_lm_resource
*lm
,
901 unsigned long long *lm_base
, u32
*aspace
, u32
*cycle
)
903 struct fake_driver
*bridge
;
905 bridge
= lm
->parent
->driver_priv
;
907 mutex_lock(&lm
->mtx
);
909 *lm_base
= bridge
->lm_base
;
910 *aspace
= bridge
->lm_aspace
;
911 *cycle
= bridge
->lm_cycle
;
913 mutex_unlock(&lm
->mtx
);
915 return bridge
->lm_enabled
;
919 * Attach a callback to a specific location monitor.
921 * Callback will be passed the monitor triggered.
923 static int fake_lm_attach(struct vme_lm_resource
*lm
, int monitor
,
924 void (*callback
)(void *), void *data
)
926 struct vme_bridge
*fake_bridge
;
927 struct fake_driver
*bridge
;
929 fake_bridge
= lm
->parent
;
931 bridge
= fake_bridge
->driver_priv
;
933 mutex_lock(&lm
->mtx
);
935 /* Ensure that the location monitor is configured - need PGM or DATA */
936 if (bridge
->lm_cycle
== 0) {
937 mutex_unlock(&lm
->mtx
);
938 pr_err("Location monitor not properly configured\n");
942 /* Check that a callback isn't already attached */
943 if (bridge
->lm_callback
[monitor
] != NULL
) {
944 mutex_unlock(&lm
->mtx
);
945 pr_err("Existing callback attached\n");
949 /* Attach callback */
950 bridge
->lm_callback
[monitor
] = callback
;
951 bridge
->lm_data
[monitor
] = data
;
953 /* Ensure that global Location Monitor Enable set */
954 bridge
->lm_enabled
= 1;
956 mutex_unlock(&lm
->mtx
);
962 * Detach a callback function forn a specific location monitor.
964 static int fake_lm_detach(struct vme_lm_resource
*lm
, int monitor
)
968 struct fake_driver
*bridge
;
970 bridge
= lm
->parent
->driver_priv
;
972 mutex_lock(&lm
->mtx
);
974 /* Detach callback */
975 bridge
->lm_callback
[monitor
] = NULL
;
976 bridge
->lm_data
[monitor
] = NULL
;
978 /* If all location monitors disabled, disable global Location Monitor */
980 for (i
= 0; i
< lm
->monitors
; i
++) {
981 if (bridge
->lm_callback
[i
] != NULL
)
986 bridge
->lm_enabled
= 0;
988 mutex_unlock(&lm
->mtx
);
994 * Determine Geographical Addressing
996 static int fake_slot_get(struct vme_bridge
*fake_bridge
)
1001 static void *fake_alloc_consistent(struct device
*parent
, size_t size
,
1004 void *alloc
= kmalloc(size
, GFP_KERNEL
);
1007 *dma
= fake_ptr_to_pci(alloc
);
1012 static void fake_free_consistent(struct device
*parent
, size_t size
,
1013 void *vaddr
, dma_addr_t dma
)
1017 dma_free_coherent(parent, size, vaddr, dma);
1022 * Configure CR/CSR space
1024 * Access to the CR/CSR can be configured at power-up. The location of the
1025 * CR/CSR registers in the CR/CSR address space is determined by the boards
1026 * Geographic address.
1028 * Each board has a 512kB window, with the highest 4kB being used for the
1029 * boards registers, this means there is a fix length 508kB window which must
1030 * be mapped onto PCI memory.
1032 static int fake_crcsr_init(struct vme_bridge
*fake_bridge
)
1035 struct fake_driver
*bridge
;
1037 bridge
= fake_bridge
->driver_priv
;
1039 /* Allocate mem for CR/CSR image */
1040 bridge
->crcsr_kernel
= kzalloc(VME_CRCSR_BUF_SIZE
, GFP_KERNEL
);
1041 bridge
->crcsr_bus
= fake_ptr_to_pci(bridge
->crcsr_kernel
);
1042 if (bridge
->crcsr_kernel
== NULL
)
1045 vstat
= fake_slot_get(fake_bridge
);
1047 pr_info("CR/CSR Offset: %d\n", vstat
);
1052 static void fake_crcsr_exit(struct vme_bridge
*fake_bridge
)
1054 struct fake_driver
*bridge
;
1056 bridge
= fake_bridge
->driver_priv
;
1058 kfree(bridge
->crcsr_kernel
);
1062 static int __init
fake_init(void)
1065 struct list_head
*pos
= NULL
, *n
;
1066 struct vme_bridge
*fake_bridge
;
1067 struct fake_driver
*fake_device
;
1068 struct vme_master_resource
*master_image
;
1069 struct vme_slave_resource
*slave_image
;
1070 struct vme_lm_resource
*lm
;
1072 /* We need a fake parent device */
1073 vme_root
= __root_device_register("vme", THIS_MODULE
);
1075 /* If we want to support more than one bridge at some point, we need to
1076 * dynamically allocate this so we get one per device.
1078 fake_bridge
= kzalloc(sizeof(struct vme_bridge
), GFP_KERNEL
);
1079 if (fake_bridge
== NULL
) {
1084 fake_device
= kzalloc(sizeof(struct fake_driver
), GFP_KERNEL
);
1085 if (fake_device
== NULL
) {
1090 fake_bridge
->driver_priv
= fake_device
;
1092 fake_bridge
->parent
= vme_root
;
1094 fake_device
->parent
= fake_bridge
;
1096 /* Initialize wait queues & mutual exclusion flags */
1097 mutex_init(&fake_device
->vme_int
);
1098 mutex_init(&fake_bridge
->irq_mtx
);
1099 tasklet_init(&fake_device
->int_tasklet
, fake_VIRQ_tasklet
,
1100 (unsigned long) fake_bridge
);
1102 strcpy(fake_bridge
->name
, driver_name
);
1104 /* Add master windows to list */
1105 INIT_LIST_HEAD(&fake_bridge
->master_resources
);
1106 for (i
= 0; i
< FAKE_MAX_MASTER
; i
++) {
1107 master_image
= kmalloc(sizeof(struct vme_master_resource
),
1109 if (master_image
== NULL
) {
1113 master_image
->parent
= fake_bridge
;
1114 spin_lock_init(&master_image
->lock
);
1115 master_image
->locked
= 0;
1116 master_image
->number
= i
;
1117 master_image
->address_attr
= VME_A16
| VME_A24
| VME_A32
|
1119 master_image
->cycle_attr
= VME_SCT
| VME_BLT
| VME_MBLT
|
1120 VME_2eVME
| VME_2eSST
| VME_2eSSTB
| VME_2eSST160
|
1121 VME_2eSST267
| VME_2eSST320
| VME_SUPER
| VME_USER
|
1122 VME_PROG
| VME_DATA
;
1123 master_image
->width_attr
= VME_D16
| VME_D32
;
1124 memset(&master_image
->bus_resource
, 0,
1125 sizeof(struct resource
));
1126 master_image
->kern_base
= NULL
;
1127 list_add_tail(&master_image
->list
,
1128 &fake_bridge
->master_resources
);
1131 /* Add slave windows to list */
1132 INIT_LIST_HEAD(&fake_bridge
->slave_resources
);
1133 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++) {
1134 slave_image
= kmalloc(sizeof(struct vme_slave_resource
),
1136 if (slave_image
== NULL
) {
1140 slave_image
->parent
= fake_bridge
;
1141 mutex_init(&slave_image
->mtx
);
1142 slave_image
->locked
= 0;
1143 slave_image
->number
= i
;
1144 slave_image
->address_attr
= VME_A16
| VME_A24
| VME_A32
|
1145 VME_A64
| VME_CRCSR
| VME_USER1
| VME_USER2
|
1146 VME_USER3
| VME_USER4
;
1147 slave_image
->cycle_attr
= VME_SCT
| VME_BLT
| VME_MBLT
|
1148 VME_2eVME
| VME_2eSST
| VME_2eSSTB
| VME_2eSST160
|
1149 VME_2eSST267
| VME_2eSST320
| VME_SUPER
| VME_USER
|
1150 VME_PROG
| VME_DATA
;
1151 list_add_tail(&slave_image
->list
,
1152 &fake_bridge
->slave_resources
);
1155 /* Add location monitor to list */
1156 INIT_LIST_HEAD(&fake_bridge
->lm_resources
);
1157 lm
= kmalloc(sizeof(struct vme_lm_resource
), GFP_KERNEL
);
1159 pr_err("Failed to allocate memory for location monitor resource structure\n");
1163 lm
->parent
= fake_bridge
;
1164 mutex_init(&lm
->mtx
);
1168 list_add_tail(&lm
->list
, &fake_bridge
->lm_resources
);
1170 fake_bridge
->slave_get
= fake_slave_get
;
1171 fake_bridge
->slave_set
= fake_slave_set
;
1172 fake_bridge
->master_get
= fake_master_get
;
1173 fake_bridge
->master_set
= fake_master_set
;
1174 fake_bridge
->master_read
= fake_master_read
;
1175 fake_bridge
->master_write
= fake_master_write
;
1176 fake_bridge
->master_rmw
= fake_master_rmw
;
1177 fake_bridge
->irq_set
= fake_irq_set
;
1178 fake_bridge
->irq_generate
= fake_irq_generate
;
1179 fake_bridge
->lm_set
= fake_lm_set
;
1180 fake_bridge
->lm_get
= fake_lm_get
;
1181 fake_bridge
->lm_attach
= fake_lm_attach
;
1182 fake_bridge
->lm_detach
= fake_lm_detach
;
1183 fake_bridge
->slot_get
= fake_slot_get
;
1184 fake_bridge
->alloc_consistent
= fake_alloc_consistent
;
1185 fake_bridge
->free_consistent
= fake_free_consistent
;
1187 pr_info("Board is%s the VME system controller\n",
1188 (geoid
== 1) ? "" : " not");
1190 pr_info("VME geographical address is set to %d\n", geoid
);
1192 retval
= fake_crcsr_init(fake_bridge
);
1194 pr_err("CR/CSR configuration failed.\n");
1198 retval
= vme_register_bridge(fake_bridge
);
1200 pr_err("Chip Registration failed.\n");
1204 exit_pointer
= fake_bridge
;
1209 fake_crcsr_exit(fake_bridge
);
1212 /* resources are stored in link list */
1213 list_for_each_safe(pos
, n
, &fake_bridge
->lm_resources
) {
1214 lm
= list_entry(pos
, struct vme_lm_resource
, list
);
1219 /* resources are stored in link list */
1220 list_for_each_safe(pos
, n
, &fake_bridge
->slave_resources
) {
1221 slave_image
= list_entry(pos
, struct vme_slave_resource
, list
);
1226 /* resources are stored in link list */
1227 list_for_each_safe(pos
, n
, &fake_bridge
->master_resources
) {
1228 master_image
= list_entry(pos
, struct vme_master_resource
,
1231 kfree(master_image
);
1243 static void __exit
fake_exit(void)
1245 struct list_head
*pos
= NULL
;
1246 struct list_head
*tmplist
;
1247 struct vme_master_resource
*master_image
;
1248 struct vme_slave_resource
*slave_image
;
1250 struct vme_bridge
*fake_bridge
;
1251 struct fake_driver
*bridge
;
1253 fake_bridge
= exit_pointer
;
1255 bridge
= fake_bridge
->driver_priv
;
1257 pr_debug("Driver is being unloaded.\n");
1260 * Shutdown all inbound and outbound windows.
1262 for (i
= 0; i
< FAKE_MAX_MASTER
; i
++)
1263 bridge
->masters
[i
].enabled
= 0;
1265 for (i
= 0; i
< FAKE_MAX_SLAVE
; i
++)
1266 bridge
->slaves
[i
].enabled
= 0;
1269 * Shutdown Location monitor.
1271 bridge
->lm_enabled
= 0;
1273 vme_unregister_bridge(fake_bridge
);
1275 fake_crcsr_exit(fake_bridge
);
1276 /* resources are stored in link list */
1277 list_for_each_safe(pos
, tmplist
, &fake_bridge
->slave_resources
) {
1278 slave_image
= list_entry(pos
, struct vme_slave_resource
, list
);
1283 /* resources are stored in link list */
1284 list_for_each_safe(pos
, tmplist
, &fake_bridge
->master_resources
) {
1285 master_image
= list_entry(pos
, struct vme_master_resource
,
1288 kfree(master_image
);
1291 kfree(fake_bridge
->driver_priv
);
1295 root_device_unregister(vme_root
);
1299 MODULE_PARM_DESC(geoid
, "Set geographical addressing");
1300 module_param(geoid
, int, 0);
1302 MODULE_DESCRIPTION("Fake VME bridge driver");
1303 MODULE_LICENSE("GPL");
1305 module_init(fake_init
);
1306 module_exit(fake_exit
);