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> 33 #include <linux/sched.h> 34 #include <linux/init.h> 35 #include <linux/interrupt.h> 36 #include <linux/wait.h> 37 #include <linux/module.h> 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 */ 47 static irq_handler_t stdma_isr; 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 56 static irqreturn_t stdma_int (int irq, void *dummy); 57 58 /************************* End of Prototypes **************************/ 59 60 61 /** 62 * stdma_try_lock - attempt to acquire ST DMA interrupt "lock" 63 * @handler: interrupt handler to use after acquisition 64 * 65 * Returns !0 if lock was acquired; otherwise 0. 66 */ 67 68 int stdma_try_lock(irq_handler_t handler, void *data) 69 { 70 unsigned long flags; 71 72 local_irq_save(flags); 73 if (stdma_locked) { 74 local_irq_restore(flags); 75 return 0; 76 } 77 78 stdma_locked = 1; 79 stdma_isr = handler; 80 stdma_isr_data = data; 81 local_irq_restore(flags); 82 return 1; 83 } 84 EXPORT_SYMBOL(stdma_try_lock); 85 86 87 /* 88 * Function: void stdma_lock( isrfunc isr, void *data ) 89 * 90 * Purpose: Tries to get a lock on the ST-DMA chip that is used by more 91 * then one device driver. Waits on stdma_wait until lock is free. 92 * stdma_lock() may not be called from an interrupt! You have to 93 * get the lock in your main routine and release it when your 94 * request is finished. 95 * 96 * Inputs: A interrupt function that is called until the lock is 97 * released. 98 * 99 * Returns: nothing 100 * 101 */ 102 103 void stdma_lock(irq_handler_t handler, void *data) 104 { 105 /* Since the DMA is used for file system purposes, we 106 have to sleep uninterruptible (there may be locked 107 buffers) */ 108 wait_event(stdma_wait, stdma_try_lock(handler, data)); 109 } 110 EXPORT_SYMBOL(stdma_lock); 111 112 113 /* 114 * Function: void stdma_release( void ) 115 * 116 * Purpose: Releases the lock on the ST-DMA chip. 117 * 118 * Inputs: none 119 * 120 * Returns: nothing 121 * 122 */ 123 124 void stdma_release(void) 125 { 126 unsigned long flags; 127 128 local_irq_save(flags); 129 130 stdma_locked = 0; 131 stdma_isr = NULL; 132 stdma_isr_data = NULL; 133 wake_up(&stdma_wait); 134 135 local_irq_restore(flags); 136 } 137 EXPORT_SYMBOL(stdma_release); 138 139 140 /** 141 * stdma_is_locked_by - allow lock holder to check whether it needs to release. 142 * @handler: interrupt handler previously used to acquire lock. 143 * 144 * Returns !0 if locked for the given handler; 0 otherwise. 145 */ 146 147 int stdma_is_locked_by(irq_handler_t handler) 148 { 149 unsigned long flags; 150 int result; 151 152 local_irq_save(flags); 153 result = stdma_locked && (stdma_isr == handler); 154 local_irq_restore(flags); 155 156 return result; 157 } 158 EXPORT_SYMBOL(stdma_is_locked_by); 159 160 161 /* 162 * Function: int stdma_islocked( void ) 163 * 164 * Purpose: Check if the ST-DMA is currently locked. 165 * Note: Returned status is only valid if ints are disabled while calling and 166 * as long as they remain disabled. 167 * If called with ints enabled, status can change only from locked to 168 * unlocked, because ints may not lock the ST-DMA. 169 * 170 * Inputs: none 171 * 172 * Returns: != 0 if locked, 0 otherwise 173 * 174 */ 175 176 int stdma_islocked(void) 177 { 178 return stdma_locked; 179 } 180 EXPORT_SYMBOL(stdma_islocked); 181 182 183 /* 184 * Function: void stdma_init( void ) 185 * 186 * Purpose: Initialize the ST-DMA chip access controlling. 187 * It sets up the interrupt and its service routine. The int is registered 188 * as slow int, client devices have to live with that (no problem 189 * currently). 190 * 191 * Inputs: none 192 * 193 * Return: nothing 194 * 195 */ 196 197 void __init stdma_init(void) 198 { 199 stdma_isr = NULL; 200 if (request_irq(IRQ_MFP_FDC, stdma_int, IRQF_SHARED, 201 "ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int)) 202 pr_err("Couldn't register ST-DMA interrupt\n"); 203 } 204 205 206 /* 207 * Function: void stdma_int() 208 * 209 * Purpose: The interrupt routine for the ST-DMA. It calls the isr 210 * registered by stdma_lock(). 211 * 212 */ 213 214 static irqreturn_t stdma_int(int irq, void *dummy) 215 { 216 if (stdma_isr) 217 (*stdma_isr)(irq, stdma_isr_data); 218 return IRQ_HANDLED; 219 } 220