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 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 45static int stdma_locked; /* the semaphore */ 46 /* int func to be called */ 47static irq_handler_t stdma_isr; 48static void *stdma_isr_data; /* data passed to isr */ 49static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */ 50 51 52 53 54/***************************** Prototypes *****************************/ 55 56static irqreturn_t stdma_int (int irq, void *dummy); 57 58/************************* End of Prototypes **************************/ 59 60 61 62/* 63 * Function: void stdma_lock( isrfunc isr, void *data ) 64 * 65 * Purpose: Tries to get a lock on the ST-DMA chip that is used by more 66 * then one device driver. Waits on stdma_wait until lock is free. 67 * stdma_lock() may not be called from an interrupt! You have to 68 * get the lock in your main routine and release it when your 69 * request is finished. 70 * 71 * Inputs: A interrupt function that is called until the lock is 72 * released. 73 * 74 * Returns: nothing 75 * 76 */ 77 78void stdma_lock(irq_handler_t handler, void *data) 79{ 80 unsigned long flags; 81 82 local_irq_save(flags); /* protect lock */ 83 84 /* Since the DMA is used for file system purposes, we 85 have to sleep uninterruptible (there may be locked 86 buffers) */ 87 wait_event(stdma_wait, !stdma_locked); 88 89 stdma_locked = 1; 90 stdma_isr = handler; 91 stdma_isr_data = data; 92 local_irq_restore(flags); 93} 94 95 96/* 97 * Function: void stdma_release( void ) 98 * 99 * Purpose: Releases the lock on the ST-DMA chip. 100 * 101 * Inputs: none 102 * 103 * Returns: nothing 104 * 105 */ 106 107void stdma_release(void) 108{ 109 unsigned long flags; 110 111 local_irq_save(flags); 112 113 stdma_locked = 0; 114 stdma_isr = NULL; 115 stdma_isr_data = NULL; 116 wake_up(&stdma_wait); 117 118 local_irq_restore(flags); 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 133int stdma_others_waiting(void) 134{ 135 return waitqueue_active(&stdma_wait); 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 154int 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 174void __init stdma_init(void) 175{ 176 stdma_isr = NULL; 177 request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED, 178 "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int); 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 190static irqreturn_t stdma_int(int irq, void *dummy) 191{ 192 if (stdma_isr) 193 (*stdma_isr)(irq, stdma_isr_data); 194 return IRQ_HANDLED; 195} 196