2005-04-17 02:20:36 +04:00
/*
2008-02-02 01:09:33 +03:00
* Amiga Buddha , Catweasel and X - Surf IDE Driver
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 1997 , 2001 by Geert Uytterhoeven and others
*
* This driver was written based on the specifications in README . buddha and
* the X - Surf info from Inside_XSurf . txt available at
* http : //www.jschoenfeld.com
*
* 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 .
*
* TODO :
* - test it : - )
* - tune the timings using the speed - register
*/
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/blkdev.h>
# include <linux/zorro.h>
# include <linux/ide.h>
# include <linux/init.h>
2011-07-03 21:41:29 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <asm/amigahw.h>
# include <asm/amigaints.h>
/*
* The Buddha has 2 IDE interfaces , the Catweasel has 3 , X - Surf has 2
*/
# define BUDDHA_NUM_HWIFS 2
# define CATWEASEL_NUM_HWIFS 3
# define XSURF_NUM_HWIFS 2
2008-07-23 21:55:50 +04:00
# define MAX_NUM_HWIFS 3
2005-04-17 02:20:36 +04:00
/*
* Bases of the IDE interfaces ( relative to the board address )
*/
# define BUDDHA_BASE1 0x800
# define BUDDHA_BASE2 0xa00
# define BUDDHA_BASE3 0xc00
# define XSURF_BASE1 0xb000 /* 2.5" Interface */
# define XSURF_BASE2 0xd000 /* 3.5" Interface */
static u_int buddha_bases [ CATWEASEL_NUM_HWIFS ] __initdata = {
BUDDHA_BASE1 , BUDDHA_BASE2 , BUDDHA_BASE3
} ;
static u_int xsurf_bases [ XSURF_NUM_HWIFS ] __initdata = {
XSURF_BASE1 , XSURF_BASE2
} ;
/*
* Offsets from one of the above bases
*/
# define BUDDHA_CONTROL 0x11a
/*
* Other registers
*/
# define BUDDHA_IRQ1 0xf00 /* MSB = 1, Harddisk is source of */
# define BUDDHA_IRQ2 0xf40 /* interrupt */
# define BUDDHA_IRQ3 0xf80
# define XSURF_IRQ1 0x7e
# define XSURF_IRQ2 0x7e
static int buddha_irqports [ CATWEASEL_NUM_HWIFS ] __initdata = {
BUDDHA_IRQ1 , BUDDHA_IRQ2 , BUDDHA_IRQ3
} ;
static int xsurf_irqports [ XSURF_NUM_HWIFS ] __initdata = {
XSURF_IRQ1 , XSURF_IRQ2
} ;
# define BUDDHA_IRQ_MR 0xfc0 /* master interrupt enable */
/*
* Board information
*/
typedef enum BuddhaType_Enum {
BOARD_BUDDHA , BOARD_CATWEASEL , BOARD_XSURF
} BuddhaType ;
2008-01-26 22:13:09 +03:00
static const char * buddha_board_name [ ] = { " Buddha " , " Catweasel " , " X-Surf " } ;
2005-04-17 02:20:36 +04:00
/*
* Check and acknowledge the interrupt status
*/
2009-06-15 20:52:58 +04:00
static int buddha_test_irq ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
unsigned char ch ;
2008-04-27 17:38:32 +04:00
ch = z_readb ( hwif - > io_ports . irq_addr ) ;
2005-04-17 02:20:36 +04:00
if ( ! ( ch & 0x80 ) )
return 0 ;
return 1 ;
}
2009-06-15 20:52:57 +04:00
static void xsurf_clear_irq ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2009-06-15 20:52:57 +04:00
/*
* X - Surf needs 0 written to IRQ register to ensure ISA bit A11 stays at 0
*/
z_writeb ( 0 , drive - > hwif - > io_ports . irq_addr ) ;
2005-04-17 02:20:36 +04:00
}
2009-05-17 21:12:25 +04:00
static void __init buddha_setup_ports ( struct ide_hw * hw , unsigned long base ,
2009-06-15 20:52:58 +04:00
unsigned long ctl , unsigned long irq_port )
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 = 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 ] = base + 2 + i * 4 ;
2008-02-06 04:57:50 +03:00
2008-04-27 17:38:32 +04:00
hw - > io_ports . ctl_addr = ctl ;
hw - > io_ports . irq_addr = irq_port ;
2008-02-06 04:57:50 +03:00
hw - > irq = IRQ_AMIGA_PORTS ;
}
2009-06-15 20:52:58 +04:00
static const struct ide_port_ops buddha_port_ops = {
. test_irq = buddha_test_irq ,
} ;
2009-06-15 20:52:57 +04:00
static const struct ide_port_ops xsurf_port_ops = {
. clear_irq = xsurf_clear_irq ,
2009-06-15 20:52:58 +04:00
. test_irq = buddha_test_irq ,
2009-06-15 20:52:57 +04:00
} ;
2009-03-27 14:46:18 +03:00
static const struct ide_port_info buddha_port_info = {
2009-06-15 20:52:58 +04:00
. port_ops = & buddha_port_ops ,
2009-03-27 14:46:23 +03:00
. host_flags = IDE_HFLAG_MMIO | 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 ,
2009-03-27 14:46:18 +03:00
} ;
2005-04-17 02:20:36 +04:00
/*
* Probe for a Buddha or Catweasel IDE interface
*/
2008-01-26 22:13:07 +03:00
static int __init buddha_init ( void )
2005-04-17 02:20:36 +04:00
{
struct zorro_dev * z = NULL ;
u_long buddha_board = 0 ;
BuddhaType type ;
2008-07-23 21:55:57 +04:00
int buddha_num_hwifs , i ;
2005-04-17 02:20:36 +04:00
while ( ( z = zorro_find_device ( ZORRO_WILDCARD , z ) ) ) {
unsigned long board ;
2009-05-17 21:12:25 +04:00
struct ide_hw hw [ MAX_NUM_HWIFS ] , * hws [ MAX_NUM_HWIFS ] ;
2009-06-15 20:52:57 +04:00
struct ide_port_info d = buddha_port_info ;
2008-01-26 22:13:06 +03:00
2005-04-17 02:20:36 +04:00
if ( z - > id = = ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA ) {
buddha_num_hwifs = BUDDHA_NUM_HWIFS ;
type = BOARD_BUDDHA ;
} else if ( z - > id = = ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL ) {
buddha_num_hwifs = CATWEASEL_NUM_HWIFS ;
type = BOARD_CATWEASEL ;
} else if ( z - > id = = ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF ) {
buddha_num_hwifs = XSURF_NUM_HWIFS ;
type = BOARD_XSURF ;
2009-06-15 20:52:57 +04:00
d . port_ops = & xsurf_port_ops ;
2005-04-17 02:20:36 +04:00
} else
continue ;
board = z - > resource . start ;
if ( type ! = BOARD_XSURF ) {
if ( ! request_mem_region ( board + BUDDHA_BASE1 , 0x800 , " IDE " ) )
continue ;
} else {
if ( ! request_mem_region ( board + XSURF_BASE1 , 0x1000 , " IDE " ) )
continue ;
if ( ! request_mem_region ( board + XSURF_BASE2 , 0x1000 , " IDE " ) )
goto fail_base2 ;
if ( ! request_mem_region ( board + XSURF_IRQ1 , 0x8 , " IDE " ) ) {
release_mem_region ( board + XSURF_BASE2 , 0x1000 ) ;
fail_base2 :
release_mem_region ( board + XSURF_BASE1 , 0x1000 ) ;
continue ;
}
}
2011-01-09 13:03:43 +03:00
buddha_board = ( unsigned long ) ZTWO_VADDR ( board ) ;
2005-04-17 02:20:36 +04:00
/* write to BUDDHA_IRQ_MR to enable the board IRQ */
/* X-Surf doesn't have this. IRQs are always on */
if ( type ! = BOARD_XSURF )
z_writeb ( 0 , buddha_board + BUDDHA_IRQ_MR ) ;
2008-01-26 22:13:09 +03:00
printk ( KERN_INFO " ide: %s IDE controller \n " ,
buddha_board_name [ type ] ) ;
2008-02-06 04:57:50 +03:00
for ( i = 0 ; i < buddha_num_hwifs ; i + + ) {
unsigned long base , ctl , irq_port ;
if ( type ! = BOARD_XSURF ) {
base = buddha_board + buddha_bases [ i ] ;
ctl = base + BUDDHA_CONTROL ;
irq_port = buddha_board + buddha_irqports [ i ] ;
2005-04-17 02:20:36 +04:00
} else {
2008-02-06 04:57:50 +03:00
base = buddha_board + xsurf_bases [ i ] ;
/* X-Surf has no CS1* (Control/AltStat) */
ctl = 0 ;
irq_port = buddha_board + xsurf_irqports [ i ] ;
}
2009-06-15 20:52:58 +04:00
buddha_setup_ports ( & hw [ i ] , base , ctl , irq_port ) ;
2007-10-20 02:32:31 +04:00
2008-07-23 21:55:57 +04:00
hws [ i ] = & hw [ i ] ;
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:13:06 +03:00
2009-06-15 20:52:57 +04:00
ide_host_add ( & d , hws , i , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:13:07 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:13:07 +03:00
module_init ( buddha_init ) ;
2008-04-02 23:22:04 +04:00
MODULE_LICENSE ( " GPL " ) ;