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>
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
2008-04-29 01:44:36 +04:00
static void falconide_input_data ( ide_drive_t * drive , struct request * rq ,
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
if ( drive - > media = = ide_disk & & rq & & rq - > cmd_type = = REQ_TYPE_FS )
2008-04-29 01:44:36 +04:00
return insw ( data_addr , buf , ( len + 1 ) / 2 ) ;
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
}
2008-04-29 01:44:36 +04:00
static void falconide_output_data ( ide_drive_t * drive , struct request * rq ,
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
if ( drive - > media = = ide_disk & & rq & & rq - > cmd_type = = REQ_TYPE_FS )
2008-05-05 23:15:19 +04:00
return outsw ( data_addr , buf , ( len + 1 ) / 2 ) ;
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 ,
. set_irq = ide_set_irq ,
. 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 ,
2008-07-23 21:55:56 +04:00
} ;
2008-02-06 04:57:50 +03:00
static void __init falconide_setup_ports ( hw_regs_t * hw )
{
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 ;
hw - > ack_intr = NULL ;
2008-06-10 22:56:37 +04:00
hw - > chipset = ide_generic ;
2008-02-06 04:57:50 +03:00
}
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 ;
2008-07-23 21:55:50 +04:00
hw_regs_t hw , * hws [ ] = { & hw , NULL , NULL , NULL } ;
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
2008-07-23 21:55:57 +04:00
host = ide_host_alloc ( & falconide_port_info , hws ) ;
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 " ) ;