2007-10-17 22:24:56 +04:00
/*
* Architecture specific parts of the Floppy driver
*
* 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 .
*
* Copyright ( C ) 1995
*/
2008-10-23 09:26:29 +04:00
# ifndef _ASM_X86_FLOPPY_H
# define _ASM_X86_FLOPPY_H
2007-10-17 22:24:56 +04:00
# include <linux/vmalloc.h>
/*
* The DMA channel used by the floppy controller cannot access data at
* addresses > = 16 MB
*
* Went back to the 1 MB limit , as some people had problems with the floppy
* driver otherwise . It doesn ' t matter much for performance anyway , as most
* floppy accesses go through the track buffer .
*/
2008-03-23 11:02:11 +03:00
# define _CROSS_64KB(a, s, vdma) \
( ! ( vdma ) & & \
( ( unsigned long ) ( a ) / K_64 ! = ( ( unsigned long ) ( a ) + ( s ) - 1 ) / K_64 ) )
2007-10-17 22:24:56 +04:00
2008-03-23 11:02:11 +03:00
# define CROSS_64KB(a, s) _CROSS_64KB(a, s, use_virtual_dma & 1)
2007-10-17 22:24:56 +04:00
2008-03-23 11:02:11 +03:00
# define SW fd_routine[use_virtual_dma & 1]
2007-10-17 22:24:56 +04:00
# define CSW fd_routine[can_use_virtual_dma & 1]
# define fd_inb(port) inb_p(port)
2008-03-23 11:02:11 +03:00
# define fd_outb(value, port) outb_p(value, port)
2007-10-17 22:24:56 +04:00
2008-03-23 11:02:11 +03:00
# define fd_request_dma() CSW._request_dma(FLOPPY_DMA, "floppy")
2007-10-17 22:24:56 +04:00
# define fd_free_dma() CSW._free_dma(FLOPPY_DMA)
# define fd_enable_irq() enable_irq(FLOPPY_IRQ)
# define fd_disable_irq() disable_irq(FLOPPY_IRQ)
# define fd_free_irq() free_irq(FLOPPY_IRQ, NULL)
# define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA)
# define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size)
# define fd_dma_setup(addr, size, mode, io) SW._dma_setup(addr, size, mode, io)
# define FLOPPY_CAN_FALLBACK_ON_NODMA
static int virtual_dma_count ;
static int virtual_dma_residue ;
static char * virtual_dma_addr ;
static int virtual_dma_mode ;
static int doing_pdma ;
static irqreturn_t floppy_hardint ( int irq , void * dev_id )
{
2008-03-26 04:16:15 +03:00
unsigned char st ;
2007-10-17 22:24:56 +04:00
# undef TRACE_FLPY_INT
# ifdef TRACE_FLPY_INT
2008-03-23 11:02:11 +03:00
static int calls ;
static int bytes ;
static int dma_wait ;
2007-10-11 13:20:03 +04:00
# endif
2007-10-17 22:24:56 +04:00
if ( ! doing_pdma )
return floppy_interrupt ( irq , dev_id ) ;
# ifdef TRACE_FLPY_INT
2008-03-23 11:02:11 +03:00
if ( ! calls )
2007-10-17 22:24:56 +04:00
bytes = virtual_dma_count ;
# endif
{
2008-03-26 04:16:15 +03:00
int lcount ;
char * lptr ;
2007-10-17 22:24:56 +04:00
st = 1 ;
2008-03-23 11:02:11 +03:00
for ( lcount = virtual_dma_count , lptr = virtual_dma_addr ;
lcount ; lcount - - , lptr + + ) {
st = inb ( virtual_dma_port + 4 ) & 0xa0 ;
if ( st ! = 0xa0 )
2007-10-17 22:24:56 +04:00
break ;
2008-03-23 11:02:11 +03:00
if ( virtual_dma_mode )
outb_p ( * lptr , virtual_dma_port + 5 ) ;
2007-10-17 22:24:56 +04:00
else
2008-03-23 11:02:11 +03:00
* lptr = inb_p ( virtual_dma_port + 5 ) ;
2007-10-17 22:24:56 +04:00
}
virtual_dma_count = lcount ;
virtual_dma_addr = lptr ;
2008-03-23 11:02:11 +03:00
st = inb ( virtual_dma_port + 4 ) ;
2007-10-17 22:24:56 +04:00
}
# ifdef TRACE_FLPY_INT
calls + + ;
# endif
2008-03-23 11:02:11 +03:00
if ( st = = 0x20 )
2007-10-17 22:24:56 +04:00
return IRQ_HANDLED ;
2008-03-23 11:02:11 +03:00
if ( ! ( st & 0x20 ) ) {
2007-10-17 22:24:56 +04:00
virtual_dma_residue + = virtual_dma_count ;
2008-03-23 11:02:11 +03:00
virtual_dma_count = 0 ;
2007-10-17 22:24:56 +04:00
# ifdef TRACE_FLPY_INT
printk ( " count=%x, residue=%x calls=%d bytes=%d dma_wait=%d \n " ,
virtual_dma_count , virtual_dma_residue , calls , bytes ,
dma_wait ) ;
calls = 0 ;
2008-03-23 11:02:11 +03:00
dma_wait = 0 ;
2007-10-17 22:24:56 +04:00
# endif
doing_pdma = 0 ;
floppy_interrupt ( irq , dev_id ) ;
return IRQ_HANDLED ;
}
# ifdef TRACE_FLPY_INT
2008-03-23 11:02:11 +03:00
if ( ! virtual_dma_count )
2007-10-17 22:24:56 +04:00
dma_wait + + ;
# endif
return IRQ_HANDLED ;
}
static void fd_disable_dma ( void )
{
2008-03-23 11:02:11 +03:00
if ( ! ( can_use_virtual_dma & 1 ) )
2007-10-17 22:24:56 +04:00
disable_dma ( FLOPPY_DMA ) ;
doing_pdma = 0 ;
virtual_dma_residue + = virtual_dma_count ;
2008-03-23 11:02:11 +03:00
virtual_dma_count = 0 ;
2007-10-17 22:24:56 +04:00
}
2008-03-23 11:02:11 +03:00
static int vdma_request_dma ( unsigned int dmanr , const char * device_id )
2007-10-17 22:24:56 +04:00
{
return 0 ;
}
static void vdma_nop ( unsigned int dummy )
{
}
static int vdma_get_dma_residue ( unsigned int dummy )
{
return virtual_dma_count + virtual_dma_residue ;
}
static int fd_request_irq ( void )
{
2008-03-23 11:02:11 +03:00
if ( can_use_virtual_dma )
2007-10-17 22:24:56 +04:00
return request_irq ( FLOPPY_IRQ , floppy_hardint ,
IRQF_DISABLED , " floppy " , NULL ) ;
else
return request_irq ( FLOPPY_IRQ , floppy_interrupt ,
IRQF_DISABLED , " floppy " , NULL ) ;
}
static unsigned long dma_mem_alloc ( unsigned long size )
{
2008-03-23 11:02:11 +03:00
return __get_dma_pages ( GFP_KERNEL | __GFP_NORETRY , get_order ( size ) ) ;
2007-10-17 22:24:56 +04:00
}
static unsigned long vdma_mem_alloc ( unsigned long size )
{
2008-03-23 11:02:11 +03:00
return ( unsigned long ) vmalloc ( size ) ;
2007-10-17 22:24:56 +04:00
}
# define nodma_mem_alloc(size) vdma_mem_alloc(size)
static void _fd_dma_mem_free ( unsigned long addr , unsigned long size )
{
2008-03-23 11:02:11 +03:00
if ( ( unsigned long ) addr > = ( unsigned long ) high_memory )
2007-10-17 22:24:56 +04:00
vfree ( ( void * ) addr ) ;
else
free_pages ( addr , get_order ( size ) ) ;
}
# define fd_dma_mem_free(addr, size) _fd_dma_mem_free(addr, size)
static void _fd_chose_dma_mode ( char * addr , unsigned long size )
{
2008-03-23 11:02:11 +03:00
if ( can_use_virtual_dma = = 2 ) {
if ( ( unsigned long ) addr > = ( unsigned long ) high_memory | |
isa_virt_to_bus ( addr ) > = 0x1000000 | |
_CROSS_64KB ( addr , size , 0 ) )
2007-10-17 22:24:56 +04:00
use_virtual_dma = 1 ;
else
use_virtual_dma = 0 ;
} else {
use_virtual_dma = can_use_virtual_dma & 1 ;
}
}
# define fd_chose_dma_mode(addr, size) _fd_chose_dma_mode(addr, size)
static int vdma_dma_setup ( char * addr , unsigned long size , int mode , int io )
{
doing_pdma = 1 ;
virtual_dma_port = io ;
2008-03-23 11:02:11 +03:00
virtual_dma_mode = ( mode = = DMA_MODE_WRITE ) ;
2007-10-17 22:24:56 +04:00
virtual_dma_addr = addr ;
virtual_dma_count = size ;
virtual_dma_residue = 0 ;
return 0 ;
}
static int hard_dma_setup ( char * addr , unsigned long size , int mode , int io )
{
# ifdef FLOPPY_SANITY_CHECK
if ( CROSS_64KB ( addr , size ) ) {
printk ( " DMA crossing 64-K boundary %p-%p \n " , addr , addr + size ) ;
return - 1 ;
}
# endif
/* actual, physical DMA */
doing_pdma = 0 ;
clear_dma_ff ( FLOPPY_DMA ) ;
2008-03-23 11:02:11 +03:00
set_dma_mode ( FLOPPY_DMA , mode ) ;
set_dma_addr ( FLOPPY_DMA , isa_virt_to_bus ( addr ) ) ;
set_dma_count ( FLOPPY_DMA , size ) ;
2007-10-17 22:24:56 +04:00
enable_dma ( FLOPPY_DMA ) ;
return 0 ;
}
static struct fd_routine_l {
2008-03-23 11:02:11 +03:00
int ( * _request_dma ) ( unsigned int dmanr , const char * device_id ) ;
2007-10-17 22:24:56 +04:00
void ( * _free_dma ) ( unsigned int dmanr ) ;
int ( * _get_dma_residue ) ( unsigned int dummy ) ;
2008-03-23 11:02:11 +03:00
unsigned long ( * _dma_mem_alloc ) ( unsigned long size ) ;
2007-10-17 22:24:56 +04:00
int ( * _dma_setup ) ( char * addr , unsigned long size , int mode , int io ) ;
} fd_routine [ ] = {
{
request_dma ,
free_dma ,
get_dma_residue ,
dma_mem_alloc ,
hard_dma_setup
} ,
{
vdma_request_dma ,
vdma_nop ,
vdma_get_dma_residue ,
vdma_mem_alloc ,
vdma_dma_setup
}
} ;
static int FDC1 = 0x3f0 ;
static int FDC2 = - 1 ;
/*
* Floppy types are stored in the rtc ' s CMOS RAM and so rtc_lock
* is needed to prevent corrupted CMOS RAM in case " insmod floppy "
* coincides with another rtc CMOS user . Paul G .
*/
2008-03-23 11:02:11 +03:00
# define FLOPPY0_TYPE \
( { \
2007-10-17 22:24:56 +04:00
unsigned long flags ; \
unsigned char val ; \
spin_lock_irqsave ( & rtc_lock , flags ) ; \
val = ( CMOS_READ ( 0x10 ) > > 4 ) & 15 ; \
spin_unlock_irqrestore ( & rtc_lock , flags ) ; \
val ; \
} )
2008-03-23 11:02:11 +03:00
# define FLOPPY1_TYPE \
( { \
2007-10-17 22:24:56 +04:00
unsigned long flags ; \
unsigned char val ; \
spin_lock_irqsave ( & rtc_lock , flags ) ; \
val = CMOS_READ ( 0x10 ) & 15 ; \
spin_unlock_irqrestore ( & rtc_lock , flags ) ; \
val ; \
} )
# define N_FDC 2
# define N_DRIVE 8
# define EXTRA_FLOPPY_PARAMS
2008-10-23 09:26:29 +04:00
# endif /* _ASM_X86_FLOPPY_H */