^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/arch/m68k/atari/stmda.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1994 Roman Hodek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* This file contains some function for controlling the access to the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /* ST-DMA chip that may be shared between devices. Currently we have: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* TT: Floppy and ACSI bus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Falcon: Floppy and SCSI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* The controlling functions set up a wait queue for access to the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* ST-DMA chip. Callers to stdma_lock() that cannot granted access are */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* put onto a queue and waked up later if the owner calls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* stdma_release(). Additionally, the caller gives his interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* service routine to stdma_lock(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* On the Falcon, the IDE bus uses just the ACSI/Floppy interrupt, but */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* not the ST-DMA chip itself. So falhd.c needs not to lock the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* chip. The interrupt is routed to falhd.c if IDE is configured, the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* model is a Falcon and the interrupt was caused by the HD controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* (can be determined by looking at its status register). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/kdev_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/genhd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/atari_stdma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/atariints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <asm/atarihw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int stdma_locked; /* the semaphore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* int func to be called */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static irq_handler_t stdma_isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void *stdma_isr_data; /* data passed to isr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static DECLARE_WAIT_QUEUE_HEAD(stdma_wait); /* wait queue for ST-DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /***************************** Prototypes *****************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static irqreturn_t stdma_int (int irq, void *dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /************************* End of Prototypes **************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * stdma_try_lock - attempt to acquire ST DMA interrupt "lock"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * @handler: interrupt handler to use after acquisition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Returns !0 if lock was acquired; otherwise 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int stdma_try_lock(irq_handler_t handler, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (stdma_locked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) stdma_locked = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) stdma_isr = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) stdma_isr_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) EXPORT_SYMBOL(stdma_try_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Function: void stdma_lock( isrfunc isr, void *data )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Purpose: Tries to get a lock on the ST-DMA chip that is used by more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * then one device driver. Waits on stdma_wait until lock is free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * stdma_lock() may not be called from an interrupt! You have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * get the lock in your main routine and release it when your
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * request is finished.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Inputs: A interrupt function that is called until the lock is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * released.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Returns: nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) void stdma_lock(irq_handler_t handler, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Since the DMA is used for file system purposes, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) have to sleep uninterruptible (there may be locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) buffers) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) wait_event(stdma_wait, stdma_try_lock(handler, data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) EXPORT_SYMBOL(stdma_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Function: void stdma_release( void )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Purpose: Releases the lock on the ST-DMA chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Inputs: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * Returns: nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void stdma_release(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) stdma_locked = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) stdma_isr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) stdma_isr_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) wake_up(&stdma_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) EXPORT_SYMBOL(stdma_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * stdma_is_locked_by - allow lock holder to check whether it needs to release.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @handler: interrupt handler previously used to acquire lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Returns !0 if locked for the given handler; 0 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int stdma_is_locked_by(irq_handler_t handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) result = stdma_locked && (stdma_isr == handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) EXPORT_SYMBOL(stdma_is_locked_by);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Function: int stdma_islocked( void )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Purpose: Check if the ST-DMA is currently locked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Note: Returned status is only valid if ints are disabled while calling and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * as long as they remain disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * If called with ints enabled, status can change only from locked to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * unlocked, because ints may not lock the ST-DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * Inputs: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Returns: != 0 if locked, 0 otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int stdma_islocked(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return stdma_locked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) EXPORT_SYMBOL(stdma_islocked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * Function: void stdma_init( void )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * Purpose: Initialize the ST-DMA chip access controlling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * It sets up the interrupt and its service routine. The int is registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * as slow int, client devices have to live with that (no problem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * currently).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * Inputs: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Return: nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void __init stdma_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) stdma_isr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (request_irq(IRQ_MFP_FDC, stdma_int, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) "ST-DMA floppy,ACSI,IDE,Falcon-SCSI", stdma_int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) pr_err("Couldn't register ST-DMA interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * Function: void stdma_int()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Purpose: The interrupt routine for the ST-DMA. It calls the isr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * registered by stdma_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static irqreturn_t stdma_int(int irq, void *dummy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (stdma_isr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) (*stdma_isr)(irq, stdma_isr_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }