/*1* linux/arch/m68k/atari/stmda.c2*3* Copyright (C) 1994 Roman Hodek4*5*6* This file is subject to the terms and conditions of the GNU General Public7* License. See the file COPYING in the main directory of this archive8* for more details.9*/101112/* This file contains some function for controlling the access to the */13/* ST-DMA chip that may be shared between devices. Currently we have: */14/* TT: Floppy and ACSI bus */15/* Falcon: Floppy and SCSI */16/* */17/* The controlling functions set up a wait queue for access to the */18/* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */19/* put onto a queue and waked up later if the owner calls */20/* stdma_release(). Additionally, the caller gives his interrupt */21/* service routine to stdma_lock(). */22/* */23/* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */24/* not the ST-DMA chip itself. So falhd.c needs not to lock the */25/* chip. The interrupt is routed to falhd.c if IDE is configured, the */26/* model is a Falcon and the interrupt was caused by the HD controller */27/* (can be determined by looking at its status register). */282930#include <linux/types.h>31#include <linux/kdev_t.h>32#include <linux/sched.h>33#include <linux/init.h>34#include <linux/interrupt.h>35#include <linux/wait.h>36#include <linux/module.h>3738#include <asm/atari_stdma.h>39#include <asm/atariints.h>40#include <asm/atarihw.h>41#include <asm/io.h>42#include <asm/irq.h>4344static int stdma_locked; /* the semaphore */45/* int func to be called */46static irq_handler_t stdma_isr;47static void *stdma_isr_data; /* data passed to isr */48static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */4950515253/***************************** Prototypes *****************************/5455static irqreturn_t stdma_int (int irq, void *dummy);5657/************************* End of Prototypes **************************/585960/**61* stdma_try_lock - attempt to acquire ST DMA interrupt "lock"62* @handler: interrupt handler to use after acquisition63* @data: cookie passed to the interrupt handler function64*65* Returns !0 if lock was acquired; otherwise 0.66*/6768int stdma_try_lock(irq_handler_t handler, void *data)69{70unsigned long flags;7172local_irq_save(flags);73if (stdma_locked) {74local_irq_restore(flags);75return 0;76}7778stdma_locked = 1;79stdma_isr = handler;80stdma_isr_data = data;81local_irq_restore(flags);82return 1;83}84EXPORT_SYMBOL(stdma_try_lock);858687/*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 more91* then one device driver. Waits on stdma_wait until lock is free.92* stdma_lock() may not be called from an interrupt! You have to93* get the lock in your main routine and release it when your94* request is finished.95*96* Inputs: A interrupt function that is called until the lock is97* released.98*99* Returns: nothing100*101*/102103void stdma_lock(irq_handler_t handler, void *data)104{105/* Since the DMA is used for file system purposes, we106have to sleep uninterruptible (there may be locked107buffers) */108wait_event(stdma_wait, stdma_try_lock(handler, data));109}110EXPORT_SYMBOL(stdma_lock);111112113/*114* Function: void stdma_release( void )115*116* Purpose: Releases the lock on the ST-DMA chip.117*118* Inputs: none119*120* Returns: nothing121*122*/123124void stdma_release(void)125{126unsigned long flags;127128local_irq_save(flags);129130stdma_locked = 0;131stdma_isr = NULL;132stdma_isr_data = NULL;133wake_up(&stdma_wait);134135local_irq_restore(flags);136}137EXPORT_SYMBOL(stdma_release);138139140/**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*/146147int stdma_is_locked_by(irq_handler_t handler)148{149unsigned long flags;150int result;151152local_irq_save(flags);153result = stdma_locked && (stdma_isr == handler);154local_irq_restore(flags);155156return result;157}158EXPORT_SYMBOL(stdma_is_locked_by);159160161/*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 and166* as long as they remain disabled.167* If called with ints enabled, status can change only from locked to168* unlocked, because ints may not lock the ST-DMA.169*170* Inputs: none171*172* Returns: != 0 if locked, 0 otherwise173*174*/175176int stdma_islocked(void)177{178return stdma_locked;179}180EXPORT_SYMBOL(stdma_islocked);181182183/*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 registered188* as slow int, client devices have to live with that (no problem189* currently).190*191* Inputs: none192*193* Return: nothing194*195*/196197void __init stdma_init(void)198{199stdma_isr = NULL;200if (request_irq(IRQ_MFP_FDC, stdma_int, IRQF_SHARED,201"ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int))202pr_err("Couldn't register ST-DMA interrupt\n");203}204205206/*207* Function: void stdma_int()208*209* Purpose: The interrupt routine for the ST-DMA. It calls the isr210* registered by stdma_lock().211*212*/213214static irqreturn_t stdma_int(int irq, void *dummy)215{216if (stdma_isr)217(*stdma_isr)(irq, stdma_isr_data);218return IRQ_HANDLED;219}220221222