2005-04-17 02:20:36 +04:00
# include <linux/types.h>
# include <linux/mm.h>
# include <linux/blkdev.h>
# include <linux/interrupt.h>
# include <asm/page.h>
# include <asm/pgtable.h>
# include <asm/mvme147hw.h>
# include <asm/irq.h>
# include "scsi.h"
# include <scsi/scsi_host.h>
# include "wd33c93.h"
# include "mvme147.h"
2010-04-04 13:00:34 +04:00
# include <linux/stat.h>
2005-04-17 02:20:36 +04:00
2010-04-04 13:00:34 +04:00
2009-05-17 15:35:13 +04:00
static irqreturn_t mvme147_intr ( int irq , void * data )
2005-04-17 02:20:36 +04:00
{
2009-05-17 15:35:13 +04:00
struct Scsi_Host * instance = data ;
2010-04-04 13:00:34 +04:00
if ( irq = = MVME147_IRQ_SCSI_PORT )
2009-05-17 15:35:13 +04:00
wd33c93_intr ( instance ) ;
2010-04-04 13:00:34 +04:00
else
m147_pcc - > dma_intr = 0x89 ; /* Ack and enable ints */
return IRQ_HANDLED ;
2005-04-17 02:20:36 +04:00
}
2006-09-13 01:49:33 +04:00
static int dma_setup ( struct scsi_cmnd * cmd , int dir_in )
2005-04-17 02:20:36 +04:00
{
2009-05-17 15:35:13 +04:00
struct Scsi_Host * instance = cmd - > device - > host ;
struct WD33C93_hostdata * hdata = shost_priv ( instance ) ;
2010-04-04 13:00:34 +04:00
unsigned char flags = 0x01 ;
unsigned long addr = virt_to_bus ( cmd - > SCp . ptr ) ;
/* setup dma direction */
if ( ! dir_in )
flags | = 0x04 ;
/* remember direction */
2010-04-04 13:00:38 +04:00
hdata - > dma_dir = dir_in ;
2010-04-04 13:00:34 +04:00
if ( dir_in ) {
/* invalidate any cache */
cache_clear ( addr , cmd - > SCp . this_residual ) ;
} else {
/* push any dirty cache */
cache_push ( addr , cmd - > SCp . this_residual ) ;
}
/* start DMA */
m147_pcc - > dma_bcr = cmd - > SCp . this_residual | ( 1 < < 24 ) ;
m147_pcc - > dma_dadr = addr ;
m147_pcc - > dma_cntrl = flags ;
/* return success */
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-09-13 01:49:33 +04:00
static void dma_stop ( struct Scsi_Host * instance , struct scsi_cmnd * SCpnt ,
2010-04-04 13:00:34 +04:00
int status )
2005-04-17 02:20:36 +04:00
{
2010-04-04 13:00:34 +04:00
m147_pcc - > dma_cntrl = 0 ;
2005-04-17 02:20:36 +04:00
}
2005-10-31 20:31:40 +03:00
int mvme147_detect ( struct scsi_host_template * tpnt )
2005-04-17 02:20:36 +04:00
{
2010-04-04 13:00:34 +04:00
static unsigned char called = 0 ;
2009-05-17 15:35:13 +04:00
struct Scsi_Host * instance ;
2010-04-04 13:00:34 +04:00
wd33c93_regs regs ;
2010-04-04 13:00:38 +04:00
struct WD33C93_hostdata * hdata ;
2010-04-04 13:00:34 +04:00
if ( ! MACH_IS_MVME147 | | called )
return 0 ;
called + + ;
tpnt - > proc_name = " MVME147 " ;
2013-03-31 08:30:35 +04:00
tpnt - > show_info = wd33c93_show_info ,
tpnt - > write_info = wd33c93_write_info ,
2010-04-04 13:00:34 +04:00
2009-05-17 15:35:13 +04:00
instance = scsi_register ( tpnt , sizeof ( struct WD33C93_hostdata ) ) ;
if ( ! instance )
2010-04-04 13:00:34 +04:00
goto err_out ;
2009-05-17 15:35:13 +04:00
instance - > base = 0xfffe4000 ;
instance - > irq = MVME147_IRQ_SCSI_PORT ;
2010-04-04 13:00:34 +04:00
regs . SASR = ( volatile unsigned char * ) 0xfffe4000 ;
regs . SCMD = ( volatile unsigned char * ) 0xfffe4001 ;
2009-05-17 15:35:13 +04:00
hdata = shost_priv ( instance ) ;
2010-04-04 13:00:38 +04:00
hdata - > no_sync = 0xff ;
hdata - > fast = 0 ;
hdata - > dma_mode = CTRL_DMA ;
2009-05-17 15:35:13 +04:00
wd33c93_init ( instance , regs , dma_setup , dma_stop , WD33C93_FS_8_10 ) ;
2010-04-04 13:00:34 +04:00
if ( request_irq ( MVME147_IRQ_SCSI_PORT , mvme147_intr , 0 ,
2009-05-17 15:35:13 +04:00
" MVME147 SCSI PORT " , instance ) )
2010-04-04 13:00:34 +04:00
goto err_unregister ;
if ( request_irq ( MVME147_IRQ_SCSI_DMA , mvme147_intr , 0 ,
2009-05-17 15:35:13 +04:00
" MVME147 SCSI DMA " , instance ) )
2010-04-04 13:00:34 +04:00
goto err_free_irq ;
2005-04-17 02:20:36 +04:00
#if 0 /* Disabled; causes problems booting */
2010-04-04 13:00:34 +04:00
m147_pcc - > scsi_interrupt = 0x10 ; /* Assert SCSI bus reset */
udelay ( 100 ) ;
m147_pcc - > scsi_interrupt = 0x00 ; /* Negate SCSI bus reset */
udelay ( 2000 ) ;
m147_pcc - > scsi_interrupt = 0x40 ; /* Clear bus reset interrupt */
2005-04-17 02:20:36 +04:00
# endif
2010-04-04 13:00:34 +04:00
m147_pcc - > scsi_interrupt = 0x09 ; /* Enable interrupt */
2005-04-17 02:20:36 +04:00
2010-04-04 13:00:34 +04:00
m147_pcc - > dma_cntrl = 0x00 ; /* ensure DMA is stopped */
m147_pcc - > dma_intr = 0x89 ; /* Ack and enable ints */
2005-04-17 02:20:36 +04:00
2010-04-04 13:00:34 +04:00
return 1 ;
2005-04-17 02:20:36 +04:00
2010-04-04 13:00:34 +04:00
err_free_irq :
free_irq ( MVME147_IRQ_SCSI_PORT , mvme147_intr ) ;
err_unregister :
2009-05-17 15:35:13 +04:00
scsi_unregister ( instance ) ;
2010-04-04 13:00:34 +04:00
err_out :
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-09-13 01:49:33 +04:00
static int mvme147_bus_reset ( struct scsi_cmnd * cmd )
2005-04-17 02:20:36 +04:00
{
/* FIXME perform bus-specific reset */
2005-05-28 15:56:31 +04:00
2010-04-04 13:00:34 +04:00
/* FIXME 2: kill this function, and let midlayer fallback to
2005-05-28 15:57:14 +04:00
the same result , calling wd33c93_host_reset ( ) */
2005-05-28 15:56:31 +04:00
spin_lock_irq ( cmd - > device - > host - > host_lock ) ;
2005-04-17 02:20:36 +04:00
wd33c93_host_reset ( cmd ) ;
2005-05-28 15:56:31 +04:00
spin_unlock_irq ( cmd - > device - > host - > host_lock ) ;
2005-04-17 02:20:36 +04:00
return SUCCESS ;
}
2005-10-31 20:31:40 +03:00
static struct scsi_host_template driver_template = {
2005-04-17 02:20:36 +04:00
. proc_name = " MVME147 " ,
. name = " MVME147 built-in SCSI " ,
. detect = mvme147_detect ,
. release = mvme147_release ,
. queuecommand = wd33c93_queuecommand ,
. eh_abort_handler = wd33c93_abort ,
. eh_bus_reset_handler = mvme147_bus_reset ,
. eh_host_reset_handler = wd33c93_host_reset ,
. can_queue = CAN_QUEUE ,
. this_id = 7 ,
. sg_tablesize = SG_ALL ,
. cmd_per_lun = CMD_PER_LUN ,
. use_clustering = ENABLE_CLUSTERING
} ;
# include "scsi_module.c"
int mvme147_release ( struct Scsi_Host * instance )
{
# ifdef MODULE
2010-04-04 13:00:34 +04:00
/* XXX Make sure DMA is stopped! */
free_irq ( MVME147_IRQ_SCSI_PORT , mvme147_intr ) ;
free_irq ( MVME147_IRQ_SCSI_DMA , mvme147_intr ) ;
2005-04-17 02:20:36 +04:00
# endif
2010-04-04 13:00:34 +04:00
return 1 ;
2005-04-17 02:20:36 +04:00
}