/*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/genhd.h>33#include <linux/sched.h>34#include <linux/init.h>35#include <linux/interrupt.h>36#include <linux/wait.h>37#include <linux/module.h>3839#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>4445static 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 */5051525354/***************************** Prototypes *****************************/5556static irqreturn_t stdma_int (int irq, void *dummy);5758/************************* End of Prototypes **************************/59606162/*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 more66* then one device driver. Waits on stdma_wait until lock is free.67* stdma_lock() may not be called from an interrupt! You have to68* get the lock in your main routine and release it when your69* request is finished.70*71* Inputs: A interrupt function that is called until the lock is72* released.73*74* Returns: nothing75*76*/7778void stdma_lock(irq_handler_t handler, void *data)79{80unsigned long flags;8182local_irq_save(flags); /* protect lock */8384/* Since the DMA is used for file system purposes, we85have to sleep uninterruptible (there may be locked86buffers) */87wait_event(stdma_wait, !stdma_locked);8889stdma_locked = 1;90stdma_isr = handler;91stdma_isr_data = data;92local_irq_restore(flags);93}94EXPORT_SYMBOL(stdma_lock);959697/*98* Function: void stdma_release( void )99*100* Purpose: Releases the lock on the ST-DMA chip.101*102* Inputs: none103*104* Returns: nothing105*106*/107108void stdma_release(void)109{110unsigned long flags;111112local_irq_save(flags);113114stdma_locked = 0;115stdma_isr = NULL;116stdma_isr_data = NULL;117wake_up(&stdma_wait);118119local_irq_restore(flags);120}121EXPORT_SYMBOL(stdma_release);122123124/*125* Function: int stdma_others_waiting( void )126*127* Purpose: Check if someone waits for the ST-DMA lock.128*129* Inputs: none130*131* Returns: 0 if no one is waiting, != 0 otherwise132*133*/134135int stdma_others_waiting(void)136{137return waitqueue_active(&stdma_wait);138}139EXPORT_SYMBOL(stdma_others_waiting);140141142/*143* Function: int stdma_islocked( void )144*145* Purpose: Check if the ST-DMA is currently locked.146* Note: Returned status is only valid if ints are disabled while calling and147* as long as they remain disabled.148* If called with ints enabled, status can change only from locked to149* unlocked, because ints may not lock the ST-DMA.150*151* Inputs: none152*153* Returns: != 0 if locked, 0 otherwise154*155*/156157int stdma_islocked(void)158{159return stdma_locked;160}161EXPORT_SYMBOL(stdma_islocked);162163164/*165* Function: void stdma_init( void )166*167* Purpose: Initialize the ST-DMA chip access controlling.168* It sets up the interrupt and its service routine. The int is registered169* as slow int, client devices have to live with that (no problem170* currently).171*172* Inputs: none173*174* Return: nothing175*176*/177178void __init stdma_init(void)179{180stdma_isr = NULL;181if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,182"ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int))183pr_err("Couldn't register ST-DMA interrupt\n");184}185186187/*188* Function: void stdma_int()189*190* Purpose: The interrupt routine for the ST-DMA. It calls the isr191* registered by stdma_lock().192*193*/194195static irqreturn_t stdma_int(int irq, void *dummy)196{197if (stdma_isr)198(*stdma_isr)(irq, stdma_isr_data);199return IRQ_HANDLED;200}201202203