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