]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/m68k/atari/stmda.c | |
3 | * | |
4 | * Copyright (C) 1994 Roman Hodek | |
5 | * | |
6 | * | |
7 | * This file is subject to the terms and conditions of the GNU General Public | |
8 | * License. See the file COPYING in the main directory of this archive | |
9 | * for more details. | |
10 | */ | |
11 | ||
12 | ||
13 | /* This file contains some function for controlling the access to the */ | |
14 | /* ST-DMA chip that may be shared between devices. Currently we have: */ | |
15 | /* TT: Floppy and ACSI bus */ | |
16 | /* Falcon: Floppy and SCSI */ | |
17 | /* */ | |
18 | /* The controlling functions set up a wait queue for access to the */ | |
19 | /* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */ | |
20 | /* put onto a queue and waked up later if the owner calls */ | |
21 | /* stdma_release(). Additionally, the caller gives his interrupt */ | |
22 | /* service routine to stdma_lock(). */ | |
23 | /* */ | |
24 | /* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */ | |
25 | /* not the ST-DMA chip itself. So falhd.c needs not to lock the */ | |
26 | /* chip. The interrupt is routed to falhd.c if IDE is configured, the */ | |
27 | /* model is a Falcon and the interrupt was caused by the HD controller */ | |
28 | /* (can be determined by looking at its status register). */ | |
29 | ||
30 | ||
31 | #include <linux/types.h> | |
32 | #include <linux/kdev_t.h> | |
1da177e4 LT |
33 | #include <linux/sched.h> |
34 | #include <linux/init.h> | |
35 | #include <linux/interrupt.h> | |
36 | #include <linux/wait.h> | |
a3b2004a | 37 | #include <linux/module.h> |
1da177e4 LT |
38 | |
39 | #include <asm/atari_stdma.h> | |
40 | #include <asm/atariints.h> | |
41 | #include <asm/atarihw.h> | |
42 | #include <asm/io.h> | |
43 | #include <asm/irq.h> | |
44 | ||
45 | static int stdma_locked; /* the semaphore */ | |
46 | /* int func to be called */ | |
40220c1a | 47 | static irq_handler_t stdma_isr; |
1da177e4 LT |
48 | static void *stdma_isr_data; /* data passed to isr */ |
49 | static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */ | |
50 | ||
51 | ||
52 | ||
53 | ||
54 | /***************************** Prototypes *****************************/ | |
55 | ||
2850bc27 | 56 | static irqreturn_t stdma_int (int irq, void *dummy); |
1da177e4 LT |
57 | |
58 | /************************* End of Prototypes **************************/ | |
59 | ||
60 | ||
16b29e75 FT |
61 | /** |
62 | * stdma_try_lock - attempt to acquire ST DMA interrupt "lock" | |
63 | * @handler: interrupt handler to use after acquisition | |
4ad69503 | 64 | * @data: cookie passed to the interrupt handler function |
16b29e75 FT |
65 | * |
66 | * Returns !0 if lock was acquired; otherwise 0. | |
67 | */ | |
68 | ||
69 | int stdma_try_lock(irq_handler_t handler, void *data) | |
70 | { | |
71 | unsigned long flags; | |
72 | ||
73 | local_irq_save(flags); | |
74 | if (stdma_locked) { | |
75 | local_irq_restore(flags); | |
76 | return 0; | |
77 | } | |
78 | ||
79 | stdma_locked = 1; | |
80 | stdma_isr = handler; | |
81 | stdma_isr_data = data; | |
82 | local_irq_restore(flags); | |
83 | return 1; | |
84 | } | |
85 | EXPORT_SYMBOL(stdma_try_lock); | |
86 | ||
1da177e4 LT |
87 | |
88 | /* | |
89 | * Function: void stdma_lock( isrfunc isr, void *data ) | |
90 | * | |
91 | * Purpose: Tries to get a lock on the ST-DMA chip that is used by more | |
92 | * then one device driver. Waits on stdma_wait until lock is free. | |
93 | * stdma_lock() may not be called from an interrupt! You have to | |
94 | * get the lock in your main routine and release it when your | |
95 | * request is finished. | |
96 | * | |
97 | * Inputs: A interrupt function that is called until the lock is | |
98 | * released. | |
99 | * | |
100 | * Returns: nothing | |
101 | * | |
102 | */ | |
103 | ||
40220c1a | 104 | void stdma_lock(irq_handler_t handler, void *data) |
1da177e4 | 105 | { |
1da177e4 LT |
106 | /* Since the DMA is used for file system purposes, we |
107 | have to sleep uninterruptible (there may be locked | |
108 | buffers) */ | |
16b29e75 | 109 | wait_event(stdma_wait, stdma_try_lock(handler, data)); |
1da177e4 | 110 | } |
a3b2004a | 111 | EXPORT_SYMBOL(stdma_lock); |
1da177e4 LT |
112 | |
113 | ||
114 | /* | |
115 | * Function: void stdma_release( void ) | |
116 | * | |
117 | * Purpose: Releases the lock on the ST-DMA chip. | |
118 | * | |
119 | * Inputs: none | |
120 | * | |
121 | * Returns: nothing | |
122 | * | |
123 | */ | |
124 | ||
125 | void stdma_release(void) | |
126 | { | |
127 | unsigned long flags; | |
128 | ||
129 | local_irq_save(flags); | |
130 | ||
131 | stdma_locked = 0; | |
132 | stdma_isr = NULL; | |
133 | stdma_isr_data = NULL; | |
134 | wake_up(&stdma_wait); | |
135 | ||
136 | local_irq_restore(flags); | |
137 | } | |
a3b2004a | 138 | EXPORT_SYMBOL(stdma_release); |
1da177e4 LT |
139 | |
140 | ||
16b29e75 FT |
141 | /** |
142 | * stdma_is_locked_by - allow lock holder to check whether it needs to release. | |
143 | * @handler: interrupt handler previously used to acquire lock. | |
1da177e4 | 144 | * |
16b29e75 | 145 | * Returns !0 if locked for the given handler; 0 otherwise. |
1da177e4 LT |
146 | */ |
147 | ||
16b29e75 | 148 | int stdma_is_locked_by(irq_handler_t handler) |
1da177e4 | 149 | { |
16b29e75 FT |
150 | unsigned long flags; |
151 | int result; | |
152 | ||
153 | local_irq_save(flags); | |
154 | result = stdma_locked && (stdma_isr == handler); | |
155 | local_irq_restore(flags); | |
156 | ||
157 | return result; | |
1da177e4 | 158 | } |
16b29e75 | 159 | EXPORT_SYMBOL(stdma_is_locked_by); |
1da177e4 LT |
160 | |
161 | ||
162 | /* | |
163 | * Function: int stdma_islocked( void ) | |
164 | * | |
165 | * Purpose: Check if the ST-DMA is currently locked. | |
166 | * Note: Returned status is only valid if ints are disabled while calling and | |
167 | * as long as they remain disabled. | |
168 | * If called with ints enabled, status can change only from locked to | |
169 | * unlocked, because ints may not lock the ST-DMA. | |
170 | * | |
171 | * Inputs: none | |
172 | * | |
173 | * Returns: != 0 if locked, 0 otherwise | |
174 | * | |
175 | */ | |
176 | ||
177 | int stdma_islocked(void) | |
178 | { | |
179 | return stdma_locked; | |
180 | } | |
a3b2004a | 181 | EXPORT_SYMBOL(stdma_islocked); |
1da177e4 LT |
182 | |
183 | ||
184 | /* | |
185 | * Function: void stdma_init( void ) | |
186 | * | |
187 | * Purpose: Initialize the ST-DMA chip access controlling. | |
188 | * It sets up the interrupt and its service routine. The int is registered | |
189 | * as slow int, client devices have to live with that (no problem | |
190 | * currently). | |
191 | * | |
192 | * Inputs: none | |
193 | * | |
194 | * Return: nothing | |
195 | * | |
196 | */ | |
197 | ||
198 | void __init stdma_init(void) | |
199 | { | |
200 | stdma_isr = NULL; | |
87511d09 | 201 | if (request_irq(IRQ_MFP_FDC, stdma_int, IRQF_SHARED, |
79abeed6 | 202 | "ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int)) |
5b8b4c3d | 203 | pr_err("Couldn't register ST-DMA interrupt\n"); |
1da177e4 LT |
204 | } |
205 | ||
206 | ||
207 | /* | |
208 | * Function: void stdma_int() | |
209 | * | |
210 | * Purpose: The interrupt routine for the ST-DMA. It calls the isr | |
211 | * registered by stdma_lock(). | |
212 | * | |
213 | */ | |
214 | ||
2850bc27 | 215 | static irqreturn_t stdma_int(int irq, void *dummy) |
1da177e4 LT |
216 | { |
217 | if (stdma_isr) | |
2850bc27 | 218 | (*stdma_isr)(irq, stdma_isr_data); |
1da177e4 LT |
219 | return IRQ_HANDLED; |
220 | } |