2005-04-17 02:20:36 +04:00
/*
* linux / arch / m68k / atari / stmda . c
*
* Copyright ( C ) 1994 Roman Hodek
*
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of this archive
* for more details .
*/
/* This file contains some function for controlling the access to the */
/* ST-DMA chip that may be shared between devices. Currently we have: */
/* TT: Floppy and ACSI bus */
/* Falcon: Floppy and SCSI */
/* */
/* The controlling functions set up a wait queue for access to the */
/* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */
/* put onto a queue and waked up later if the owner calls */
/* stdma_release(). Additionally, the caller gives his interrupt */
/* service routine to stdma_lock(). */
/* */
/* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */
/* not the ST-DMA chip itself. So falhd.c needs not to lock the */
/* chip. The interrupt is routed to falhd.c if IDE is configured, the */
/* model is a Falcon and the interrupt was caused by the HD controller */
/* (can be determined by looking at its status register). */
# include <linux/types.h>
# include <linux/kdev_t.h>
# include <linux/genhd.h>
# include <linux/sched.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/wait.h>
2008-02-05 09:30:26 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/atari_stdma.h>
# include <asm/atariints.h>
# include <asm/atarihw.h>
# include <asm/io.h>
# include <asm/irq.h>
static int stdma_locked ; /* the semaphore */
/* int func to be called */
2006-10-09 15:19:47 +04:00
static irq_handler_t stdma_isr ;
2005-04-17 02:20:36 +04:00
static void * stdma_isr_data ; /* data passed to isr */
static DECLARE_WAIT_QUEUE_HEAD ( stdma_wait ) ; /* wait queue for ST-DMA */
/***************************** Prototypes *****************************/
2006-10-07 17:16:45 +04:00
static irqreturn_t stdma_int ( int irq , void * dummy ) ;
2005-04-17 02:20:36 +04:00
/************************* End of Prototypes **************************/
2014-11-12 08:12:08 +03:00
/**
* stdma_try_lock - attempt to acquire ST DMA interrupt " lock "
* @ handler : interrupt handler to use after acquisition
*
* Returns ! 0 if lock was acquired ; otherwise 0.
*/
int stdma_try_lock ( irq_handler_t handler , void * data )
{
unsigned long flags ;
local_irq_save ( flags ) ;
if ( stdma_locked ) {
local_irq_restore ( flags ) ;
return 0 ;
}
stdma_locked = 1 ;
stdma_isr = handler ;
stdma_isr_data = data ;
local_irq_restore ( flags ) ;
return 1 ;
}
EXPORT_SYMBOL ( stdma_try_lock ) ;
2005-04-17 02:20:36 +04:00
/*
* Function : void stdma_lock ( isrfunc isr , void * data )
*
* Purpose : Tries to get a lock on the ST - DMA chip that is used by more
* then one device driver . Waits on stdma_wait until lock is free .
* stdma_lock ( ) may not be called from an interrupt ! You have to
* get the lock in your main routine and release it when your
* request is finished .
*
* Inputs : A interrupt function that is called until the lock is
* released .
*
* Returns : nothing
*
*/
2006-10-09 15:19:47 +04:00
void stdma_lock ( irq_handler_t handler , void * data )
2005-04-17 02:20:36 +04:00
{
/* Since the DMA is used for file system purposes, we
have to sleep uninterruptible ( there may be locked
buffers ) */
2014-11-12 08:12:08 +03:00
wait_event ( stdma_wait , stdma_try_lock ( handler , data ) ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-05 09:30:26 +03:00
EXPORT_SYMBOL ( stdma_lock ) ;
2005-04-17 02:20:36 +04:00
/*
* Function : void stdma_release ( void )
*
* Purpose : Releases the lock on the ST - DMA chip .
*
* Inputs : none
*
* Returns : nothing
*
*/
void stdma_release ( void )
{
unsigned long flags ;
local_irq_save ( flags ) ;
stdma_locked = 0 ;
stdma_isr = NULL ;
stdma_isr_data = NULL ;
wake_up ( & stdma_wait ) ;
local_irq_restore ( flags ) ;
}
2008-02-05 09:30:26 +03:00
EXPORT_SYMBOL ( stdma_release ) ;
2005-04-17 02:20:36 +04:00
2014-11-12 08:12:08 +03:00
/**
* stdma_is_locked_by - allow lock holder to check whether it needs to release .
* @ handler : interrupt handler previously used to acquire lock .
2005-04-17 02:20:36 +04:00
*
2014-11-12 08:12:08 +03:00
* Returns ! 0 if locked for the given handler ; 0 otherwise .
2005-04-17 02:20:36 +04:00
*/
2014-11-12 08:12:08 +03:00
int stdma_is_locked_by ( irq_handler_t handler )
2005-04-17 02:20:36 +04:00
{
2014-11-12 08:12:08 +03:00
unsigned long flags ;
int result ;
local_irq_save ( flags ) ;
result = stdma_locked & & ( stdma_isr = = handler ) ;
local_irq_restore ( flags ) ;
return result ;
2005-04-17 02:20:36 +04:00
}
2014-11-12 08:12:08 +03:00
EXPORT_SYMBOL ( stdma_is_locked_by ) ;
2005-04-17 02:20:36 +04:00
/*
* Function : int stdma_islocked ( void )
*
* Purpose : Check if the ST - DMA is currently locked .
* Note : Returned status is only valid if ints are disabled while calling and
* as long as they remain disabled .
* If called with ints enabled , status can change only from locked to
* unlocked , because ints may not lock the ST - DMA .
*
* Inputs : none
*
* Returns : ! = 0 if locked , 0 otherwise
*
*/
int stdma_islocked ( void )
{
return stdma_locked ;
}
2008-02-05 09:30:26 +03:00
EXPORT_SYMBOL ( stdma_islocked ) ;
2005-04-17 02:20:36 +04:00
/*
* Function : void stdma_init ( void )
*
* Purpose : Initialize the ST - DMA chip access controlling .
* It sets up the interrupt and its service routine . The int is registered
* as slow int , client devices have to live with that ( no problem
* currently ) .
*
* Inputs : none
*
* Return : nothing
*
*/
void __init stdma_init ( void )
{
stdma_isr = NULL ;
2014-10-06 00:34:40 +04:00
if ( request_irq ( IRQ_MFP_FDC , stdma_int , IRQF_SHARED ,
2011-05-04 16:55:41 +04:00
" ST-DMA floppy,ACSI,IDE,Falcon-SCSI " , stdma_int ) )
2008-12-30 16:01:32 +03:00
pr_err ( " Couldn't register ST-DMA interrupt \n " ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Function : void stdma_int ( )
*
* Purpose : The interrupt routine for the ST - DMA . It calls the isr
* registered by stdma_lock ( ) .
*
*/
2006-10-07 17:16:45 +04:00
static irqreturn_t stdma_int ( int irq , void * dummy )
2005-04-17 02:20:36 +04:00
{
if ( stdma_isr )
2006-10-07 17:16:45 +04:00
( * stdma_isr ) ( irq , stdma_isr_data ) ;
2005-04-17 02:20:36 +04:00
return IRQ_HANDLED ;
}