2005-04-17 02:20:36 +04:00
/*
2008-02-02 01:09:33 +03:00
* Atari Falcon IDE Driver
2005-04-17 02:20:36 +04:00
*
* Created 12 Jul 1997 by Geert Uytterhoeven
*
* 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 .
*/
2007-07-20 07:33:18 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/blkdev.h>
# include <linux/ide.h>
# include <linux/init.h>
# include <asm/setup.h>
# include <asm/atarihw.h>
# include <asm/atariints.h>
# include <asm/atari_stdma.h>
2009-04-08 16:12:48 +04:00
# include <asm/ide.h>
2005-04-17 02:20:36 +04:00
2008-04-26 19:36:38 +04:00
# define DRV_NAME "falconide"
2005-04-17 02:20:36 +04:00
/*
* Base of the IDE interface
*/
# define ATA_HD_BASE 0xfff00000
/*
* Offsets from the above base
*/
# define ATA_HD_CONTROL 0x39
/*
* falconide_intr_lock is used to obtain access to the IDE interrupt ,
* which is shared between several drivers .
*/
2009-03-27 14:46:22 +03:00
static int falconide_intr_lock ;
static void falconide_release_lock ( void )
{
if ( falconide_intr_lock = = 0 ) {
printk ( KERN_ERR " %s: bug \n " , __func__ ) ;
return ;
}
falconide_intr_lock = 0 ;
stdma_release ( ) ;
}
static void falconide_get_lock ( irq_handler_t handler , void * data )
{
if ( falconide_intr_lock = = 0 ) {
if ( in_interrupt ( ) > 0 )
panic ( " Falcon IDE hasn't ST-DMA lock in interrupt " ) ;
stdma_lock ( handler , data ) ;
falconide_intr_lock = 1 ;
}
}
2005-04-17 02:20:36 +04:00
2009-03-27 14:46:38 +03:00
static void falconide_input_data ( ide_drive_t * drive , struct ide_cmd * cmd ,
2008-04-29 01:44:36 +04:00
void * buf , unsigned int len )
2008-04-29 01:44:36 +04:00
{
2008-04-29 01:44:36 +04:00
unsigned long data_addr = drive - > hwif - > io_ports . data_addr ;
2008-04-29 01:44:36 +04:00
2009-04-08 16:12:48 +04:00
if ( drive - > media = = ide_disk & & cmd & & ( cmd - > tf_flags & IDE_TFLAG_FS ) ) {
__ide_mm_insw ( data_addr , buf , ( len + 1 ) / 2 ) ;
return ;
}
2008-04-29 01:44:36 +04:00
2009-03-27 14:46:23 +03:00
raw_insw_swapw ( ( u16 * ) data_addr , buf , ( len + 1 ) / 2 ) ;
2008-04-29 01:44:36 +04:00
}
2009-03-27 14:46:38 +03:00
static void falconide_output_data ( ide_drive_t * drive , struct ide_cmd * cmd ,
2008-04-29 01:44:36 +04:00
void * buf , unsigned int len )
2008-04-29 01:44:36 +04:00
{
2008-04-29 01:44:36 +04:00
unsigned long data_addr = drive - > hwif - > io_ports . data_addr ;
2009-04-08 16:12:48 +04:00
if ( drive - > media = = ide_disk & & cmd & & ( cmd - > tf_flags & IDE_TFLAG_FS ) ) {
__ide_mm_outsw ( data_addr , buf , ( len + 1 ) / 2 ) ;
return ;
}
2008-04-29 01:44:36 +04:00
2009-03-27 14:46:23 +03:00
raw_outsw_swapw ( ( u16 * ) data_addr , buf , ( len + 1 ) / 2 ) ;
2008-04-29 01:44:36 +04:00
}
2008-07-23 21:55:56 +04:00
/* Atari has a byte-swapped IDE interface */
static const struct ide_tp_ops falconide_tp_ops = {
. exec_command = ide_exec_command ,
. read_status = ide_read_status ,
. read_altstatus = ide_read_altstatus ,
2009-03-31 22:15:30 +04:00
. write_devctl = ide_write_devctl ,
2008-07-23 21:55:56 +04:00
2009-03-31 22:15:32 +04:00
. dev_select = ide_dev_select ,
2008-07-23 21:55:56 +04:00
. tf_load = ide_tf_load ,
. tf_read = ide_tf_read ,
. input_data = falconide_input_data ,
. output_data = falconide_output_data ,
} ;
static const struct ide_port_info falconide_port_info = {
2009-03-27 14:46:22 +03:00
. get_lock = falconide_get_lock ,
. release_lock = falconide_release_lock ,
2008-07-23 21:55:56 +04:00
. tp_ops = & falconide_tp_ops ,
2009-03-27 14:46:23 +03:00
. host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE |
IDE_HFLAG_NO_DMA ,
2009-03-27 14:46:27 +03:00
. irq_flags = IRQF_SHARED ,
2009-05-17 21:12:22 +04:00
. chipset = ide_generic ,
2008-07-23 21:55:56 +04:00
} ;
2009-05-17 21:12:25 +04:00
static void __init falconide_setup_ports ( struct ide_hw * hw )
2008-02-06 04:57:50 +03:00
{
int i ;
memset ( hw , 0 , sizeof ( * hw ) ) ;
2008-04-27 17:38:32 +04:00
hw - > io_ports . data_addr = ATA_HD_BASE ;
2008-02-06 04:57:50 +03:00
for ( i = 1 ; i < 8 ; i + + )
2008-04-27 17:38:32 +04:00
hw - > io_ports_array [ i ] = ATA_HD_BASE + 1 + i * 4 ;
2008-02-06 04:57:50 +03:00
2008-04-27 17:38:32 +04:00
hw - > io_ports . ctl_addr = ATA_HD_BASE + ATA_HD_CONTROL ;
2008-02-06 04:57:50 +03:00
hw - > irq = IRQ_MFP_IDE ;
}
2005-04-17 02:20:36 +04:00
/*
* Probe for a Falcon IDE interface
*/
2008-01-26 22:13:07 +03:00
static int __init falconide_init ( void )
2005-04-17 02:20:36 +04:00
{
2008-07-23 21:55:57 +04:00
struct ide_host * host ;
2009-05-17 21:12:25 +04:00
struct ide_hw hw , * hws [ ] = { & hw } ;
2008-07-23 21:55:59 +04:00
int rc ;
2005-04-17 02:20:36 +04:00
2008-02-06 04:57:50 +03:00
if ( ! MACH_IS_ATARI | | ! ATARIHW_PRESENT ( IDE ) )
2008-07-23 21:55:59 +04:00
return - ENODEV ;
2008-02-06 04:57:50 +03:00
2008-01-26 22:13:09 +03:00
printk ( KERN_INFO " ide: Falcon IDE controller \n " ) ;
2008-04-26 19:36:38 +04:00
if ( ! request_mem_region ( ATA_HD_BASE , 0x40 , DRV_NAME ) ) {
printk ( KERN_ERR " %s: resources busy \n " , DRV_NAME ) ;
return - EBUSY ;
}
2008-02-06 04:57:50 +03:00
falconide_setup_ports ( & hw ) ;
2005-04-17 02:20:36 +04:00
2009-05-17 21:12:24 +04:00
host = ide_host_alloc ( & falconide_port_info , hws , 1 ) ;
2008-07-23 21:55:59 +04:00
if ( host = = NULL ) {
rc = - ENOMEM ;
goto err ;
2008-01-26 22:13:06 +03:00
}
2008-01-26 22:13:07 +03:00
2009-03-27 14:46:22 +03:00
falconide_get_lock ( NULL , NULL ) ;
2008-07-23 21:55:59 +04:00
rc = ide_host_register ( host , & falconide_port_info , hws ) ;
2009-03-27 14:46:22 +03:00
falconide_release_lock ( ) ;
2008-07-23 21:55:59 +04:00
if ( rc )
goto err_free ;
2008-02-06 04:57:50 +03:00
return 0 ;
2008-07-23 21:55:59 +04:00
err_free :
ide_host_free ( host ) ;
err :
release_mem_region ( ATA_HD_BASE , 0x40 ) ;
return rc ;
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:13:07 +03:00
module_init ( falconide_init ) ;
2008-04-02 23:22:04 +04:00
MODULE_LICENSE ( " GPL " ) ;