1 2 /* 3 * linux/atari/stmda.c 4 * 5 * Copyright (C) 1994 Roman Hodek 6 * 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file README.legal in the main directory of this archive 10 * for more details. 11 */ 12 13 14 /* This file contains some function for controlling the access to the */ 15 /* ST-DMA chip that may be shared between devices. Currently we have: */ 16 /* TT: Floppy and ACSI bus */ 17 /* Falcon: Floppy and SCSI */ 18 /* */ 19 /* The controlling functions set up a wait queue for access to the */ 20 /* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */ 21 /* put onto a queue and waked up later if the owner calls */ 22 /* stdma_release(). Additionally, the caller gives his interrupt */ 23 /* service routine to stdma_lock(). */ 24 /* */ 25 /* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */ 26 /* not the ST-DMA chip itself. So falhd.c needs not to lock the */ 27 /* chip. The interrupt is routed to falhd.c if IDE is configured, the */ 28 /* model is a Falcon and the interrupt was caused by the HD controller */ 29 /* (can be determined by looking at its status register). */ 30 31 32 #include <linux/types.h> 33 #include <linux/genhd.h> 34 #include <linux/sched.h> 35 #include <asm/bootinfo.h> 36 #include <asm/atari_stdma.h> 37 #include <asm/atariints.h> 38 #include <asm/atarihw.h> 39 #include <asm/atarihdreg.h> 40 #include <asm/io.h> 41 #include <asm/irq.h> 42 43 static int stdma_locked = 0; /* the semaphore */ 44 static isrfunc stdma_isr = NULL; /* int func to be called */ 45 static void *stdma_isr_data = NULL; /* data passed to isr */ 46 static struct wait_queue *stdma_wait = NULL; /* wait queue for ST-DMA */ 47 48 49 50 51 /***************************** Prototypes *****************************/ 52 53 static void stdma_int (int irq, struct pt_regs *fp, void *dummy); 54 55 /************************* End of Prototypes **************************/ 56 57 58 59 /* 60 * Function: void stdma_lock( isrfunc isr, void *data ) 61 * 62 * Purpose: Tries to get a lock on the ST-DMA chip that is used by more 63 * then one device driver. Waits on stdma_wait until lock is free. 64 * stdma_lock() may not be called from an interrupt! You have to 65 * get the lock in your main routine and release it when your 66 * request is finished. 67 * 68 * Inputs: A interrupt function that is called until the lock is 69 * released. 70 * 71 * Returns: nothing 72 * 73 */ 74 75 void stdma_lock(isrfunc isr, void *data) /* */ 76 { 77 unsigned long oldflags; 78 79 save_flags(oldflags); 80 cli(); /* protect lock */ 81 82 while(stdma_locked) 83 /* Since the DMA is used for file system purposes, we 84 have to sleep uninterruptible (there may be locked 85 buffers) */ 86 sleep_on(&stdma_wait); 87 88 stdma_locked = 1; 89 stdma_isr = isr; 90 stdma_isr_data = data; 91 restore_flags(oldflags); 92 } 93 94 95 /* 96 * Function: void stdma_release( void ) 97 * 98 * Purpose: Releases the lock on the ST-DMA chip. 99 * 100 * Inputs: none 101 * 102 * Returns: nothing 103 * 104 */ 105 106 void stdma_release(void) /* */ 107 { 108 unsigned long oldflags; 109 110 save_flags(oldflags); 111 cli(); 112 113 stdma_locked = 0; 114 stdma_isr = NULL; 115 stdma_isr_data = NULL; 116 wake_up(&stdma_wait); 117 118 restore_flags(oldflags); 119 } 120 121 122 /* 123 * Function: int stdma_others_waiting( void ) 124 * 125 * Purpose: Check if someone waits for the ST-DMA lock. 126 * 127 * Inputs: none 128 * 129 * Returns: 0 if no one is waiting, != 0 otherwise 130 * 131 */ 132 133 int stdma_others_waiting(void) /* */ 134 { 135 return stdma_wait != NULL; 136 } 137 138 139 /* 140 * Function: int stdma_islocked( void ) 141 * 142 * Purpose: Check if the ST-DMA is currently locked. 143 * Note: Returned status is only valid if ints are disabled while calling and 144 * as long as they remain disabled. 145 * If called with ints enabled, status can change only from locked to 146 * unlocked, because ints may not lock the ST-DMA. 147 * 148 * Inputs: none 149 * 150 * Returns: != 0 if locked, 0 otherwise 151 * 152 */ 153 154 int stdma_islocked(void) /* */ 155 { 156 return stdma_locked; 157 } 158 159 160 /* 161 * Function: void stdma_init( void ) 162 * 163 * Purpose: Initialize the ST-DMA chip access controlling. 164 * It sets up the interrupt and its service routine. The int is registered 165 * as slow int, client devices have to live with that (no problem 166 * currently). 167 * 168 * Inputs: none 169 * 170 * Return: nothing 171 * 172 */ 173 174 void stdma_init(void) /* */ 175 { 176 stdma_isr = NULL; 177 add_isr(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW, NULL, 178 "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI"); 179 } 180 181 182 /* 183 * Function: void stdma_int() 184 * 185 * Purpose: The interrupt routine for the ST-DMA. It calls the isr 186 * registered by stdma_lock(). 187 * 188 */ 189 190 static void stdma_int(int irq, struct pt_regs *fp, void *dummy) /* */ 191 { 192 if (stdma_isr) 193 (*stdma_isr)(irq, fp, stdma_isr_data); 194 }