2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-17 02:20:36 +04:00
/*
* Generic Macintosh NCR5380 driver
*
* Copyright 1998 , Michael Schmitz < mschmitz @ lbl . gov >
*
2019-06-09 04:19:11 +03:00
* Copyright 2019 Finn Thain
*
2005-04-17 02:20:36 +04:00
* derived in part from :
*/
/*
* Generic Generic NCR5380 driver
*
* Copyright 1995 , Russell King
*/
2019-06-09 04:19:11 +03:00
# include <linux/delay.h>
2005-04-17 02:20:36 +04:00
# include <linux/types.h>
# include <linux/module.h>
# include <linux/ioport.h>
# include <linux/init.h>
# include <linux/blkdev.h>
# include <linux/interrupt.h>
2014-11-12 08:12:07 +03:00
# include <linux/platform_device.h>
2005-04-17 02:20:36 +04:00
2014-11-12 08:12:07 +03:00
# include <asm/hwtest.h>
2005-04-17 02:20:36 +04:00
# include <asm/io.h>
2019-06-09 04:19:11 +03:00
# include <asm/macintosh.h>
2005-04-17 02:20:36 +04:00
# include <asm/macints.h>
2014-11-12 08:12:07 +03:00
# include <asm/setup.h>
2005-04-17 02:20:36 +04:00
# include <scsi/scsi_host.h>
2014-11-12 08:12:04 +03:00
/* Definitions for the core NCR5380 driver. */
2007-10-16 12:25:01 +04:00
2016-10-10 07:46:53 +03:00
# define NCR5380_implementation_fields int pdma_residual
2014-11-12 08:12:04 +03:00
2016-10-10 07:46:53 +03:00
# define NCR5380_read(reg) in_8(hostdata->io + ((reg) << 4))
# define NCR5380_write(reg, value) out_8(hostdata->io + ((reg) << 4), value)
2014-11-12 08:12:04 +03:00
2016-10-10 07:46:53 +03:00
# define NCR5380_dma_xfer_len macscsi_dma_xfer_len
2016-03-23 13:10:17 +03:00
# define NCR5380_dma_recv_setup macscsi_pread
# define NCR5380_dma_send_setup macscsi_pwrite
2016-10-10 07:46:53 +03:00
# define NCR5380_dma_residual macscsi_dma_residual
2014-11-12 08:12:04 +03:00
# define NCR5380_intr macscsi_intr
# define NCR5380_queue_command macscsi_queue_command
# define NCR5380_abort macscsi_abort
2017-08-25 14:57:10 +03:00
# define NCR5380_host_reset macscsi_host_reset
2014-11-12 08:12:04 +03:00
# define NCR5380_info macscsi_info
2005-04-17 02:20:36 +04:00
# include "NCR5380.h"
static int setup_can_queue = - 1 ;
2014-11-12 08:12:05 +03:00
module_param ( setup_can_queue , int , 0 ) ;
2005-04-17 02:20:36 +04:00
static int setup_cmd_per_lun = - 1 ;
2014-11-12 08:12:05 +03:00
module_param ( setup_cmd_per_lun , int , 0 ) ;
2005-04-17 02:20:36 +04:00
static int setup_sg_tablesize = - 1 ;
2014-11-12 08:12:05 +03:00
module_param ( setup_sg_tablesize , int , 0 ) ;
2019-06-09 04:19:11 +03:00
static int setup_use_pdma = 512 ;
2014-11-12 08:12:05 +03:00
module_param ( setup_use_pdma , int , 0 ) ;
2005-04-17 02:20:36 +04:00
static int setup_hostid = - 1 ;
2014-11-12 08:12:05 +03:00
module_param ( setup_hostid , int , 0 ) ;
2016-01-03 08:05:11 +03:00
static int setup_toshiba_delay = - 1 ;
module_param ( setup_toshiba_delay , int , 0 ) ;
2005-04-17 02:20:36 +04:00
2014-11-12 08:12:05 +03:00
# ifndef MODULE
static int __init mac_scsi_setup ( char * str )
{
2016-01-03 08:05:11 +03:00
int ints [ 8 ] ;
2014-11-12 08:12:05 +03:00
( void ) get_options ( str , ARRAY_SIZE ( ints ) , ints ) ;
2016-01-03 08:05:11 +03:00
if ( ints [ 0 ] < 1 ) {
pr_err ( " Usage: mac5380=<can_queue>[,<cmd_per_lun>[,<sg_tablesize>[,<hostid>[,<use_tags>[,<use_pdma>[,<toshiba_delay>]]]]]] \n " ) ;
2014-11-12 08:12:05 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2014-11-12 08:12:05 +03:00
if ( ints [ 0 ] > = 1 )
setup_can_queue = ints [ 1 ] ;
if ( ints [ 0 ] > = 2 )
setup_cmd_per_lun = ints [ 2 ] ;
if ( ints [ 0 ] > = 3 )
setup_sg_tablesize = ints [ 3 ] ;
if ( ints [ 0 ] > = 4 )
setup_hostid = ints [ 4 ] ;
2016-03-23 13:10:22 +03:00
/* ints[5] (use_tagged_queuing) is ignored */
2014-11-12 08:12:05 +03:00
if ( ints [ 0 ] > = 6 )
2005-04-17 02:20:36 +04:00
setup_use_pdma = ints [ 6 ] ;
2016-01-03 08:05:11 +03:00
if ( ints [ 0 ] > = 7 )
setup_toshiba_delay = ints [ 7 ] ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
__setup ( " mac5380= " , mac_scsi_setup ) ;
2014-11-12 08:12:05 +03:00
# endif /* !MODULE */
2005-04-17 02:20:36 +04:00
2019-06-09 04:19:11 +03:00
/*
* According to " Inside Macintosh: Devices " , Mac OS requires disk drivers to
* specify the number of bytes between the delays expected from a SCSI target .
* This allows the operating system to " prevent bus errors when a target fails
* to deliver the next byte within the processor bus error timeout period . "
* Linux SCSI drivers lack knowledge of the timing behaviour of SCSI targets
* so bus errors are unavoidable .
*
* If a MOVE . B instruction faults , we assume that zero bytes were transferred
* and simply retry . That assumption probably depends on target behaviour but
* seems to hold up okay . The NOP provides synchronization : without it the
* fault can sometimes occur after the program counter has moved past the
* offending instruction . Post - increment addressing can ' t be used .
*/
# define MOVE_BYTE(operands) \
asm volatile ( \
" 1: moveb " operands " \n " \
" 11: nop \n " \
" addq #1,%0 \n " \
" subq #1,%1 \n " \
" 40: \n " \
" \n " \
" .section .fixup, \" ax \" \n " \
" .even \n " \
" 90: movel #1, %2 \n " \
" jra 40b \n " \
" .previous \n " \
" \n " \
" .section __ex_table, \" a \" \n " \
" .align 4 \n " \
" .long 1b,90b \n " \
" .long 11b,90b \n " \
" .previous \n " \
: " +a " ( addr ) , " +r " ( n ) , " +r " ( result ) : " a " ( io ) )
/*
* If a MOVE . W ( or MOVE . L ) instruction faults , it cannot be retried because
* the residual byte count would be uncertain . In that situation the MOVE_WORD
* macro clears n in the fixup section to abort the transfer .
*/
# define MOVE_WORD(operands) \
asm volatile ( \
" 1: movew " operands " \n " \
" 11: nop \n " \
" subq #2,%1 \n " \
" 40: \n " \
" \n " \
" .section .fixup, \" ax \" \n " \
" .even \n " \
" 90: movel #0, %1 \n " \
" movel #2, %2 \n " \
" jra 40b \n " \
" .previous \n " \
" \n " \
" .section __ex_table, \" a \" \n " \
" .align 4 \n " \
" .long 1b,90b \n " \
" .long 11b,90b \n " \
" .previous \n " \
: " +a " ( addr ) , " +r " ( n ) , " +r " ( result ) : " a " ( io ) )
# define MOVE_16_WORDS(operands) \
asm volatile ( \
" 1: movew " operands " \n " \
" 2: movew " operands " \n " \
" 3: movew " operands " \n " \
" 4: movew " operands " \n " \
" 5: movew " operands " \n " \
" 6: movew " operands " \n " \
" 7: movew " operands " \n " \
" 8: movew " operands " \n " \
" 9: movew " operands " \n " \
" 10: movew " operands " \n " \
" 11: movew " operands " \n " \
" 12: movew " operands " \n " \
" 13: movew " operands " \n " \
" 14: movew " operands " \n " \
" 15: movew " operands " \n " \
" 16: movew " operands " \n " \
" 17: nop \n " \
" subl #32,%1 \n " \
" 40: \n " \
" \n " \
" .section .fixup, \" ax \" \n " \
" .even \n " \
" 90: movel #0, %1 \n " \
" movel #2, %2 \n " \
" jra 40b \n " \
" .previous \n " \
" \n " \
" .section __ex_table, \" a \" \n " \
" .align 4 \n " \
" .long 1b,90b \n " \
" .long 2b,90b \n " \
" .long 3b,90b \n " \
" .long 4b,90b \n " \
" .long 5b,90b \n " \
" .long 6b,90b \n " \
" .long 7b,90b \n " \
" .long 8b,90b \n " \
" .long 9b,90b \n " \
" .long 10b,90b \n " \
" .long 11b,90b \n " \
" .long 12b,90b \n " \
" .long 13b,90b \n " \
" .long 14b,90b \n " \
" .long 15b,90b \n " \
" .long 16b,90b \n " \
" .long 17b,90b \n " \
" .previous \n " \
: " +a " ( addr ) , " +r " ( n ) , " +r " ( result ) : " a " ( io ) )
# define MAC_PDMA_DELAY 32
static inline int mac_pdma_recv ( void __iomem * io , unsigned char * start , int n )
{
unsigned char * addr = start ;
int result = 0 ;
if ( n > = 1 ) {
MOVE_BYTE ( " %3@,%0@ " ) ;
if ( result )
goto out ;
}
if ( n > = 1 & & ( ( unsigned long ) addr & 1 ) ) {
MOVE_BYTE ( " %3@,%0@ " ) ;
if ( result )
goto out ;
}
while ( n > = 32 )
MOVE_16_WORDS ( " %3@,%0@+ " ) ;
while ( n > = 2 )
MOVE_WORD ( " %3@,%0@+ " ) ;
if ( result )
return start - addr ; /* Negated to indicate uncertain length */
if ( n = = 1 )
MOVE_BYTE ( " %3@,%0@ " ) ;
out :
return addr - start ;
}
static inline int mac_pdma_send ( unsigned char * start , void __iomem * io , int n )
{
unsigned char * addr = start ;
int result = 0 ;
if ( n > = 1 ) {
MOVE_BYTE ( " %0@,%3@ " ) ;
if ( result )
goto out ;
}
if ( n > = 1 & & ( ( unsigned long ) addr & 1 ) ) {
MOVE_BYTE ( " %0@,%3@ " ) ;
if ( result )
goto out ;
}
while ( n > = 32 )
MOVE_16_WORDS ( " %0@+,%3@ " ) ;
while ( n > = 2 )
MOVE_WORD ( " %0@+,%3@ " ) ;
if ( result )
return start - addr ; /* Negated to indicate uncertain length */
if ( n = = 1 )
MOVE_BYTE ( " %0@,%3@ " ) ;
out :
return addr - start ;
}
2005-04-17 02:20:36 +04:00
2019-06-09 04:19:11 +03:00
/* The "SCSI DMA" chip on the IIfx implements this register. */
# define CTRL_REG 0x8
# define CTRL_INTERRUPTS_ENABLE BIT(1)
# define CTRL_HANDSHAKE_MODE BIT(3)
static inline void write_ctrl_reg ( struct NCR5380_hostdata * hostdata , u32 value )
{
out_be32 ( hostdata - > io + ( CTRL_REG < < 4 ) , value ) ;
}
2005-04-17 02:20:36 +04:00
2016-10-10 07:46:53 +03:00
static inline int macscsi_pread ( struct NCR5380_hostdata * hostdata ,
unsigned char * dst , int len )
2005-04-17 02:20:36 +04:00
{
2017-01-16 02:50:57 +03:00
u8 __iomem * s = hostdata - > pdma_io + ( INPUT_DATA_REG < < 4 ) ;
2016-03-23 13:10:31 +03:00
unsigned char * d = dst ;
2019-06-09 04:19:11 +03:00
int result = 0 ;
2019-06-09 04:19:11 +03:00
hostdata - > pdma_residual = len ;
2016-03-23 13:10:31 +03:00
2016-10-10 07:46:53 +03:00
while ( ! NCR5380_poll_politely ( hostdata , BUS_AND_STATUS_REG ,
2016-03-23 13:10:31 +03:00
BASR_DRQ | BASR_PHASE_MATCH ,
BASR_DRQ | BASR_PHASE_MATCH , HZ / 64 ) ) {
2019-06-09 04:19:11 +03:00
int bytes ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
if ( macintosh_config - > ident = = MAC_MODEL_IIFX )
write_ctrl_reg ( hostdata , CTRL_HANDSHAKE_MODE |
CTRL_INTERRUPTS_ENABLE ) ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
bytes = mac_pdma_recv ( s , d , min ( hostdata - > pdma_residual , 512 ) ) ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
if ( bytes > 0 ) {
d + = bytes ;
hostdata - > pdma_residual - = bytes ;
}
if ( hostdata - > pdma_residual = = 0 )
2019-06-09 04:19:11 +03:00
goto out ;
2016-03-23 13:10:31 +03:00
2016-10-10 07:46:53 +03:00
if ( NCR5380_poll_politely2 ( hostdata , STATUS_REG , SR_REQ , SR_REQ ,
2019-06-09 04:19:11 +03:00
BUS_AND_STATUS_REG , BASR_ACK ,
BASR_ACK , HZ / 64 ) < 0 )
scmd_printk ( KERN_DEBUG , hostdata - > connected ,
2016-03-23 13:10:31 +03:00
" %s: !REQ and !ACK \n " , __func__ ) ;
if ( ! ( NCR5380_read ( BUS_AND_STATUS_REG ) & BASR_PHASE_MATCH ) )
2019-06-09 04:19:11 +03:00
goto out ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
if ( bytes = = 0 )
udelay ( MAC_PDMA_DELAY ) ;
if ( bytes > = 0 )
continue ;
2016-03-23 13:10:31 +03:00
2016-10-10 07:46:53 +03:00
dsprintk ( NDEBUG_PSEUDO_DMA , hostdata - > host ,
2019-06-09 04:19:11 +03:00
" %s: bus error (%d/%d) \n " , __func__ , d - dst , len ) ;
2016-10-10 07:46:53 +03:00
NCR5380_dprint ( NDEBUG_PSEUDO_DMA , hostdata - > host ) ;
2019-06-09 04:19:11 +03:00
result = - 1 ;
goto out ;
2014-11-12 08:12:06 +03:00
}
2016-03-23 13:10:31 +03:00
scmd_printk ( KERN_ERR , hostdata - > connected ,
" %s: phase mismatch or !DRQ \n " , __func__ ) ;
2016-10-10 07:46:53 +03:00
NCR5380_dprint ( NDEBUG_PSEUDO_DMA , hostdata - > host ) ;
2019-06-09 04:19:11 +03:00
result = - 1 ;
out :
if ( macintosh_config - > ident = = MAC_MODEL_IIFX )
write_ctrl_reg ( hostdata , CTRL_INTERRUPTS_ENABLE ) ;
return result ;
2005-04-17 02:20:36 +04:00
}
2016-10-10 07:46:53 +03:00
static inline int macscsi_pwrite ( struct NCR5380_hostdata * hostdata ,
unsigned char * src , int len )
2005-04-17 02:20:36 +04:00
{
2016-03-23 13:10:31 +03:00
unsigned char * s = src ;
2017-01-16 02:50:57 +03:00
u8 __iomem * d = hostdata - > pdma_io + ( OUTPUT_DATA_REG < < 4 ) ;
2019-06-09 04:19:11 +03:00
int result = 0 ;
2019-06-09 04:19:11 +03:00
hostdata - > pdma_residual = len ;
2016-03-23 13:10:31 +03:00
2016-10-10 07:46:53 +03:00
while ( ! NCR5380_poll_politely ( hostdata , BUS_AND_STATUS_REG ,
2016-03-23 13:10:31 +03:00
BASR_DRQ | BASR_PHASE_MATCH ,
BASR_DRQ | BASR_PHASE_MATCH , HZ / 64 ) ) {
2019-06-09 04:19:11 +03:00
int bytes ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
if ( macintosh_config - > ident = = MAC_MODEL_IIFX )
write_ctrl_reg ( hostdata , CTRL_HANDSHAKE_MODE |
CTRL_INTERRUPTS_ENABLE ) ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
bytes = mac_pdma_send ( s , d , min ( hostdata - > pdma_residual , 512 ) ) ;
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
if ( bytes > 0 ) {
s + = bytes ;
hostdata - > pdma_residual - = bytes ;
}
2016-03-23 13:10:31 +03:00
2019-06-09 04:19:11 +03:00
if ( hostdata - > pdma_residual = = 0 ) {
2016-10-10 07:46:53 +03:00
if ( NCR5380_poll_politely ( hostdata , TARGET_COMMAND_REG ,
2016-03-23 13:10:31 +03:00
TCR_LAST_BYTE_SENT ,
2019-06-09 04:19:11 +03:00
TCR_LAST_BYTE_SENT ,
HZ / 64 ) < 0 ) {
2016-03-23 13:10:31 +03:00
scmd_printk ( KERN_ERR , hostdata - > connected ,
" %s: Last Byte Sent timeout \n " , __func__ ) ;
2019-06-09 04:19:11 +03:00
result = - 1 ;
}
2019-06-09 04:19:11 +03:00
goto out ;
2016-03-23 13:10:31 +03:00
}
2019-06-09 04:19:11 +03:00
if ( NCR5380_poll_politely2 ( hostdata , STATUS_REG , SR_REQ , SR_REQ ,
BUS_AND_STATUS_REG , BASR_ACK ,
BASR_ACK , HZ / 64 ) < 0 )
scmd_printk ( KERN_DEBUG , hostdata - > connected ,
" %s: !REQ and !ACK \n " , __func__ ) ;
if ( ! ( NCR5380_read ( BUS_AND_STATUS_REG ) & BASR_PHASE_MATCH ) )
2019-06-09 04:19:11 +03:00
goto out ;
2019-06-09 04:19:11 +03:00
if ( bytes = = 0 )
udelay ( MAC_PDMA_DELAY ) ;
if ( bytes > = 0 )
continue ;
2016-10-10 07:46:53 +03:00
dsprintk ( NDEBUG_PSEUDO_DMA , hostdata - > host ,
2019-06-09 04:19:11 +03:00
" %s: bus error (%d/%d) \n " , __func__ , s - src , len ) ;
2016-10-10 07:46:53 +03:00
NCR5380_dprint ( NDEBUG_PSEUDO_DMA , hostdata - > host ) ;
2019-06-09 04:19:11 +03:00
result = - 1 ;
goto out ;
2014-11-12 08:12:06 +03:00
}
2016-03-23 13:10:31 +03:00
scmd_printk ( KERN_ERR , hostdata - > connected ,
" %s: phase mismatch or !DRQ \n " , __func__ ) ;
2016-10-10 07:46:53 +03:00
NCR5380_dprint ( NDEBUG_PSEUDO_DMA , hostdata - > host ) ;
2019-06-09 04:19:11 +03:00
result = - 1 ;
out :
if ( macintosh_config - > ident = = MAC_MODEL_IIFX )
write_ctrl_reg ( hostdata , CTRL_INTERRUPTS_ENABLE ) ;
return result ;
2014-11-12 08:12:06 +03:00
}
2005-04-17 02:20:36 +04:00
2016-10-10 07:46:53 +03:00
static int macscsi_dma_xfer_len ( struct NCR5380_hostdata * hostdata ,
2016-03-23 13:10:11 +03:00
struct scsi_cmnd * cmd )
{
2016-03-23 13:10:31 +03:00
if ( hostdata - > flags & FLAG_NO_PSEUDO_DMA | |
2019-06-09 04:19:11 +03:00
cmd - > SCp . this_residual < setup_use_pdma )
2016-03-23 13:10:11 +03:00
return 0 ;
2016-03-23 13:10:31 +03:00
return cmd - > SCp . this_residual ;
2016-03-23 13:10:11 +03:00
}
2016-10-10 07:46:53 +03:00
static int macscsi_dma_residual ( struct NCR5380_hostdata * hostdata )
{
return hostdata - > pdma_residual ;
}
2005-04-17 02:20:36 +04:00
# include "NCR5380.c"
2014-11-12 08:12:07 +03:00
# define DRV_MODULE_NAME "mac_scsi"
# define PFX DRV_MODULE_NAME ": "
static struct scsi_host_template mac_scsi_template = {
2016-01-03 08:05:48 +03:00
. module = THIS_MODULE ,
. proc_name = DRV_MODULE_NAME ,
. name = " Macintosh NCR5380 SCSI " ,
. info = macscsi_info ,
. queuecommand = macscsi_queue_command ,
. eh_abort_handler = macscsi_abort ,
2017-08-25 14:57:10 +03:00
. eh_host_reset_handler = macscsi_host_reset ,
2016-01-03 08:05:48 +03:00
. can_queue = 16 ,
. this_id = 7 ,
2016-03-23 13:10:31 +03:00
. sg_tablesize = 1 ,
2016-01-03 08:05:48 +03:00
. cmd_per_lun = 2 ,
2018-12-13 18:17:09 +03:00
. dma_boundary = PAGE_SIZE - 1 ,
2016-01-03 08:05:58 +03:00
. cmd_size = NCR5380_CMD_SIZE ,
2016-01-03 08:06:07 +03:00
. max_sectors = 128 ,
2005-04-17 02:20:36 +04:00
} ;
2014-11-12 08:12:07 +03:00
static int __init mac_scsi_probe ( struct platform_device * pdev )
{
struct Scsi_Host * instance ;
2016-10-10 07:46:53 +03:00
struct NCR5380_hostdata * hostdata ;
2014-11-12 08:12:07 +03:00
int error ;
int host_flags = 0 ;
struct resource * irq , * pio_mem , * pdma_mem = NULL ;
pio_mem = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! pio_mem )
return - ENODEV ;
pdma_mem = platform_get_resource ( pdev , IORESOURCE_MEM , 1 ) ;
irq = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
if ( ! hwreg_present ( ( unsigned char * ) pio_mem - > start +
( STATUS_REG < < 4 ) ) ) {
pr_info ( PFX " no device detected at %pap \n " , & pio_mem - > start ) ;
return - ENODEV ;
}
if ( setup_can_queue > 0 )
mac_scsi_template . can_queue = setup_can_queue ;
if ( setup_cmd_per_lun > 0 )
mac_scsi_template . cmd_per_lun = setup_cmd_per_lun ;
2019-11-02 04:06:54 +03:00
if ( setup_sg_tablesize > 0 )
2014-11-12 08:12:07 +03:00
mac_scsi_template . sg_tablesize = setup_sg_tablesize ;
if ( setup_hostid > = 0 )
mac_scsi_template . this_id = setup_hostid & 7 ;
instance = scsi_host_alloc ( & mac_scsi_template ,
sizeof ( struct NCR5380_hostdata ) ) ;
if ( ! instance )
return - ENOMEM ;
if ( irq )
instance - > irq = irq - > start ;
else
instance - > irq = NO_IRQ ;
2016-10-10 07:46:53 +03:00
hostdata = shost_priv ( instance ) ;
hostdata - > base = pio_mem - > start ;
2017-01-16 02:50:57 +03:00
hostdata - > io = ( u8 __iomem * ) pio_mem - > start ;
2014-11-12 08:12:07 +03:00
2016-10-10 07:46:53 +03:00
if ( pdma_mem & & setup_use_pdma )
2017-01-16 02:50:57 +03:00
hostdata - > pdma_io = ( u8 __iomem * ) pdma_mem - > start ;
2016-10-10 07:46:53 +03:00
else
2014-11-12 08:12:07 +03:00
host_flags | = FLAG_NO_PSEUDO_DMA ;
2016-01-03 08:05:11 +03:00
host_flags | = setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0 ;
2014-11-12 08:12:19 +03:00
2016-03-23 13:10:19 +03:00
error = NCR5380_init ( instance , host_flags | FLAG_LATE_DMA_SETUP ) ;
2016-01-03 08:05:21 +03:00
if ( error )
goto fail_init ;
2014-11-12 08:12:07 +03:00
if ( instance - > irq ! = NO_IRQ ) {
error = request_irq ( instance - > irq , macscsi_intr , IRQF_SHARED ,
" NCR5380 " , instance ) ;
if ( error )
goto fail_irq ;
}
2016-01-03 08:05:11 +03:00
NCR5380_maybe_reset_bus ( instance ) ;
2014-11-12 08:12:07 +03:00
error = scsi_add_host ( instance , NULL ) ;
if ( error )
goto fail_host ;
platform_set_drvdata ( pdev , instance ) ;
scsi_scan_host ( instance ) ;
return 0 ;
fail_host :
if ( instance - > irq ! = NO_IRQ )
free_irq ( instance - > irq , instance ) ;
fail_irq :
NCR5380_exit ( instance ) ;
2016-01-03 08:05:21 +03:00
fail_init :
2014-11-12 08:12:07 +03:00
scsi_host_put ( instance ) ;
return error ;
}
static int __exit mac_scsi_remove ( struct platform_device * pdev )
{
struct Scsi_Host * instance = platform_get_drvdata ( pdev ) ;
scsi_remove_host ( instance ) ;
if ( instance - > irq ! = NO_IRQ )
free_irq ( instance - > irq , instance ) ;
NCR5380_exit ( instance ) ;
scsi_host_put ( instance ) ;
return 0 ;
}
static struct platform_driver mac_scsi_driver = {
. remove = __exit_p ( mac_scsi_remove ) ,
. driver = {
. name = DRV_MODULE_NAME ,
} ,
} ;
2005-04-17 02:20:36 +04:00
2014-11-12 08:12:07 +03:00
module_platform_driver_probe ( mac_scsi_driver , mac_scsi_probe ) ;
2014-11-12 08:12:05 +03:00
2014-11-12 08:12:07 +03:00
MODULE_ALIAS ( " platform: " DRV_MODULE_NAME ) ;
2014-11-12 08:12:05 +03:00
MODULE_LICENSE ( " GPL " ) ;