11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/m68k/atari/stmda.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1994 Roman Hodek 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 81da177e4SLinus Torvalds * License. See the file COPYING in the main directory of this archive 91da177e4SLinus Torvalds * for more details. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds /* This file contains some function for controlling the access to the */ 141da177e4SLinus Torvalds /* ST-DMA chip that may be shared between devices. Currently we have: */ 151da177e4SLinus Torvalds /* TT: Floppy and ACSI bus */ 161da177e4SLinus Torvalds /* Falcon: Floppy and SCSI */ 171da177e4SLinus Torvalds /* */ 181da177e4SLinus Torvalds /* The controlling functions set up a wait queue for access to the */ 191da177e4SLinus Torvalds /* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */ 201da177e4SLinus Torvalds /* put onto a queue and waked up later if the owner calls */ 211da177e4SLinus Torvalds /* stdma_release(). Additionally, the caller gives his interrupt */ 221da177e4SLinus Torvalds /* service routine to stdma_lock(). */ 231da177e4SLinus Torvalds /* */ 241da177e4SLinus Torvalds /* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */ 251da177e4SLinus Torvalds /* not the ST-DMA chip itself. So falhd.c needs not to lock the */ 261da177e4SLinus Torvalds /* chip. The interrupt is routed to falhd.c if IDE is configured, the */ 271da177e4SLinus Torvalds /* model is a Falcon and the interrupt was caused by the HD controller */ 281da177e4SLinus Torvalds /* (can be determined by looking at its status register). */ 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include <linux/types.h> 321da177e4SLinus Torvalds #include <linux/kdev_t.h> 331da177e4SLinus Torvalds #include <linux/genhd.h> 341da177e4SLinus Torvalds #include <linux/sched.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <linux/interrupt.h> 371da177e4SLinus Torvalds #include <linux/wait.h> 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds #include <asm/atari_stdma.h> 401da177e4SLinus Torvalds #include <asm/atariints.h> 411da177e4SLinus Torvalds #include <asm/atarihw.h> 421da177e4SLinus Torvalds #include <asm/io.h> 431da177e4SLinus Torvalds #include <asm/irq.h> 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds static int stdma_locked; /* the semaphore */ 461da177e4SLinus Torvalds /* int func to be called */ 47*40220c1aSDavid Howells static irq_handler_t stdma_isr; 481da177e4SLinus Torvalds static void *stdma_isr_data; /* data passed to isr */ 491da177e4SLinus Torvalds static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */ 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds /***************************** Prototypes *****************************/ 551da177e4SLinus Torvalds 562850bc27SAl Viro static irqreturn_t stdma_int (int irq, void *dummy); 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds /************************* End of Prototypes **************************/ 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds /* 631da177e4SLinus Torvalds * Function: void stdma_lock( isrfunc isr, void *data ) 641da177e4SLinus Torvalds * 651da177e4SLinus Torvalds * Purpose: Tries to get a lock on the ST-DMA chip that is used by more 661da177e4SLinus Torvalds * then one device driver. Waits on stdma_wait until lock is free. 671da177e4SLinus Torvalds * stdma_lock() may not be called from an interrupt! You have to 681da177e4SLinus Torvalds * get the lock in your main routine and release it when your 691da177e4SLinus Torvalds * request is finished. 701da177e4SLinus Torvalds * 711da177e4SLinus Torvalds * Inputs: A interrupt function that is called until the lock is 721da177e4SLinus Torvalds * released. 731da177e4SLinus Torvalds * 741da177e4SLinus Torvalds * Returns: nothing 751da177e4SLinus Torvalds * 761da177e4SLinus Torvalds */ 771da177e4SLinus Torvalds 78*40220c1aSDavid Howells void stdma_lock(irq_handler_t handler, void *data) 791da177e4SLinus Torvalds { 801da177e4SLinus Torvalds unsigned long flags; 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds local_irq_save(flags); /* protect lock */ 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds /* Since the DMA is used for file system purposes, we 851da177e4SLinus Torvalds have to sleep uninterruptible (there may be locked 861da177e4SLinus Torvalds buffers) */ 871da177e4SLinus Torvalds wait_event(stdma_wait, !stdma_locked); 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds stdma_locked = 1; 901da177e4SLinus Torvalds stdma_isr = handler; 911da177e4SLinus Torvalds stdma_isr_data = data; 921da177e4SLinus Torvalds local_irq_restore(flags); 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* 971da177e4SLinus Torvalds * Function: void stdma_release( void ) 981da177e4SLinus Torvalds * 991da177e4SLinus Torvalds * Purpose: Releases the lock on the ST-DMA chip. 1001da177e4SLinus Torvalds * 1011da177e4SLinus Torvalds * Inputs: none 1021da177e4SLinus Torvalds * 1031da177e4SLinus Torvalds * Returns: nothing 1041da177e4SLinus Torvalds * 1051da177e4SLinus Torvalds */ 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds void stdma_release(void) 1081da177e4SLinus Torvalds { 1091da177e4SLinus Torvalds unsigned long flags; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds local_irq_save(flags); 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds stdma_locked = 0; 1141da177e4SLinus Torvalds stdma_isr = NULL; 1151da177e4SLinus Torvalds stdma_isr_data = NULL; 1161da177e4SLinus Torvalds wake_up(&stdma_wait); 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds local_irq_restore(flags); 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds /* 1231da177e4SLinus Torvalds * Function: int stdma_others_waiting( void ) 1241da177e4SLinus Torvalds * 1251da177e4SLinus Torvalds * Purpose: Check if someone waits for the ST-DMA lock. 1261da177e4SLinus Torvalds * 1271da177e4SLinus Torvalds * Inputs: none 1281da177e4SLinus Torvalds * 1291da177e4SLinus Torvalds * Returns: 0 if no one is waiting, != 0 otherwise 1301da177e4SLinus Torvalds * 1311da177e4SLinus Torvalds */ 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds int stdma_others_waiting(void) 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds return waitqueue_active(&stdma_wait); 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds /* 1401da177e4SLinus Torvalds * Function: int stdma_islocked( void ) 1411da177e4SLinus Torvalds * 1421da177e4SLinus Torvalds * Purpose: Check if the ST-DMA is currently locked. 1431da177e4SLinus Torvalds * Note: Returned status is only valid if ints are disabled while calling and 1441da177e4SLinus Torvalds * as long as they remain disabled. 1451da177e4SLinus Torvalds * If called with ints enabled, status can change only from locked to 1461da177e4SLinus Torvalds * unlocked, because ints may not lock the ST-DMA. 1471da177e4SLinus Torvalds * 1481da177e4SLinus Torvalds * Inputs: none 1491da177e4SLinus Torvalds * 1501da177e4SLinus Torvalds * Returns: != 0 if locked, 0 otherwise 1511da177e4SLinus Torvalds * 1521da177e4SLinus Torvalds */ 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds int stdma_islocked(void) 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds return stdma_locked; 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds /* 1611da177e4SLinus Torvalds * Function: void stdma_init( void ) 1621da177e4SLinus Torvalds * 1631da177e4SLinus Torvalds * Purpose: Initialize the ST-DMA chip access controlling. 1641da177e4SLinus Torvalds * It sets up the interrupt and its service routine. The int is registered 1651da177e4SLinus Torvalds * as slow int, client devices have to live with that (no problem 1661da177e4SLinus Torvalds * currently). 1671da177e4SLinus Torvalds * 1681da177e4SLinus Torvalds * Inputs: none 1691da177e4SLinus Torvalds * 1701da177e4SLinus Torvalds * Return: nothing 1711da177e4SLinus Torvalds * 1721da177e4SLinus Torvalds */ 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds void __init stdma_init(void) 1751da177e4SLinus Torvalds { 1761da177e4SLinus Torvalds stdma_isr = NULL; 1771da177e4SLinus Torvalds request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW, 1781da177e4SLinus Torvalds "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int); 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds /* 1831da177e4SLinus Torvalds * Function: void stdma_int() 1841da177e4SLinus Torvalds * 1851da177e4SLinus Torvalds * Purpose: The interrupt routine for the ST-DMA. It calls the isr 1861da177e4SLinus Torvalds * registered by stdma_lock(). 1871da177e4SLinus Torvalds * 1881da177e4SLinus Torvalds */ 1891da177e4SLinus Torvalds 1902850bc27SAl Viro static irqreturn_t stdma_int(int irq, void *dummy) 1911da177e4SLinus Torvalds { 1921da177e4SLinus Torvalds if (stdma_isr) 1932850bc27SAl Viro (*stdma_isr)(irq, stdma_isr_data); 1941da177e4SLinus Torvalds return IRQ_HANDLED; 1951da177e4SLinus Torvalds } 196