2005-04-16 15:20:36 -07:00
# define AUTOSENSE
/* #define PSEUDO_DMA */
/*
* EcoSCSI Generic NCR5380 driver
*
* Copyright 1995 , Russell King
*
* ALPHA RELEASE 1.
*
* For more information , please consult
*
* NCR 5380 Family
* SCSI Protocol Controller
* Databook
*
* NCR Microelectronics
* 1635 Aeroplaza Drive
* Colorado Springs , CO 80916
* 1 + ( 719 ) 578 - 3400
* 1 + ( 800 ) 334 - 5454
*/
# include <linux/module.h>
# include <linux/signal.h>
# include <linux/sched.h>
# include <linux/ioport.h>
# include <linux/delay.h>
# include <linux/init.h>
# include <linux/blkdev.h>
# include <asm/io.h>
# include <asm/system.h>
# include "../scsi.h"
# include <scsi/scsi_host.h>
# define NCR5380_implementation_fields int port, ctrl
# define NCR5380_local_declare() struct Scsi_Host *_instance
# define NCR5380_setup(instance) _instance = instance
# define NCR5380_read(reg) ecoscsi_read(_instance, reg)
# define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
# define NCR5380_intr ecoscsi_intr
# define NCR5380_queue_command ecoscsi_queue_command
# define NCR5380_proc_info ecoscsi_proc_info
# include "../NCR5380.h"
# define ECOSCSI_PUBLIC_RELEASE 1
static char ecoscsi_read ( struct Scsi_Host * instance , int reg )
{
int iobase = instance - > io_port ;
outb ( reg | 8 , iobase ) ;
return inb ( iobase + 1 ) ;
}
static void ecoscsi_write ( struct Scsi_Host * instance , int reg , int value )
{
int iobase = instance - > io_port ;
outb ( reg | 8 , iobase ) ;
outb ( value , iobase + 1 ) ;
}
/*
* Function : ecoscsi_setup ( char * str , int * ints )
*
* Purpose : LILO command line initialization of the overrides array ,
*
* Inputs : str - unused , ints - array of integer parameters with ints [ 0 ]
* equal to the number of ints .
*
*/
void ecoscsi_setup ( char * str , int * ints )
{
}
const char * ecoscsi_info ( struct Scsi_Host * spnt )
{
return " " ;
}
#if 0
# define STAT(p) inw(p + 144)
static inline int NCR5380_pwrite ( struct Scsi_Host * host , unsigned char * addr ,
int len )
{
int iobase = host - > io_port ;
printk ( " writing %p len %d \n " , addr , len ) ;
if ( ! len ) return - 1 ;
while ( 1 )
{
int status ;
while ( ( ( status = STAT ( iobase ) ) & 0x100 ) = = 0 ) ;
}
}
static inline int NCR5380_pread ( struct Scsi_Host * host , unsigned char * addr ,
int len )
{
int iobase = host - > io_port ;
int iobase2 = host - > io_port + 0x100 ;
unsigned char * start = addr ;
int s ;
printk ( " reading %p len %d \n " , addr , len ) ;
outb ( inb ( iobase + 128 ) , iobase + 135 ) ;
while ( len > 0 )
{
int status , b , i , timeout ;
timeout = 0x07FFFFFF ;
while ( ( ( status = STAT ( iobase ) ) & 0x100 ) = = 0 )
{
timeout - - ;
if ( status & 0x200 | | ! timeout )
{
printk ( " status = %p \n " , status ) ;
outb ( 0 , iobase + 135 ) ;
return 1 ;
}
}
if ( len > = 128 )
{
for ( i = 0 ; i < 64 ; i + + )
{
b = inw ( iobase + 136 ) ;
* addr + + = b ;
* addr + + = b > > 8 ;
}
len - = 128 ;
}
else
{
b = inw ( iobase + 136 ) ;
* addr + + = b ;
len - = 1 ;
if ( len )
* addr + + = b > > 8 ;
len - = 1 ;
}
}
outb ( 0 , iobase + 135 ) ;
printk ( " first bytes = %02X %02X %02X %20X %02X %02X %02X \n " , * start , start [ 1 ] , start [ 2 ] , start [ 3 ] , start [ 4 ] , start [ 5 ] , start [ 6 ] ) ;
return 1 ;
}
# endif
# undef STAT
# define BOARD_NORMAL 0
# define BOARD_NCR53C400 1
# include "../NCR5380.c"
2005-10-31 18:31:40 +01:00
static struct scsi_host_template ecoscsi_template = {
2005-04-16 15:20:36 -07:00
. module = THIS_MODULE ,
. name = " Serial Port EcoSCSI NCR5380 " ,
. proc_name = " ecoscsi " ,
. info = ecoscsi_info ,
. queuecommand = ecoscsi_queue_command ,
. eh_abort_handler = NCR5380_abort ,
. eh_bus_reset_handler = NCR5380_bus_reset ,
. can_queue = 16 ,
. this_id = 7 ,
. sg_tablesize = SG_ALL ,
. cmd_per_lun = 2 ,
. use_clustering = DISABLE_CLUSTERING
} ;
static struct Scsi_Host * host ;
static int __init ecoscsi_init ( void )
{
host = scsi_host_alloc ( tpnt , sizeof ( struct NCR5380_hostdata ) ) ;
if ( ! host )
return 0 ;
host - > io_port = 0x80ce8000 ;
host - > n_io_port = 144 ;
host - > irq = IRQ_NONE ;
if ( ! ( request_region ( host - > io_port , host - > n_io_port , " ecoscsi " ) ) )
goto unregister_scsi ;
ecoscsi_write ( host , MODE_REG , 0x20 ) ; /* Is it really SCSI? */
if ( ecoscsi_read ( host , MODE_REG ) ! = 0x20 ) /* Write to a reg. */
goto release_reg ;
ecoscsi_write ( host , MODE_REG , 0x00 ) ; /* it back. */
if ( ecoscsi_read ( host , MODE_REG ) ! = 0x00 )
goto release_reg ;
NCR5380_init ( host , 0 ) ;
printk ( " scsi%d: at port 0x%08lx irqs disabled " , host - > host_no , host - > io_port ) ;
printk ( " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d " ,
host - > can_queue , host - > cmd_per_lun , ECOSCSI_PUBLIC_RELEASE ) ;
printk ( " \n scsi%d: " , host - > host_no ) ;
NCR5380_print_options ( host ) ;
printk ( " \n " ) ;
scsi_add_host ( host , NULL ) ; /* XXX handle failure */
scsi_scan_host ( host ) ;
return 0 ;
release_reg :
release_region ( host - > io_port , host - > n_io_port ) ;
unregister_scsi :
scsi_host_put ( host ) ;
return - ENODEV ;
}
static void __exit ecoscsi_exit ( void )
{
scsi_remove_host ( host ) ;
if ( shpnt - > irq ! = IRQ_NONE )
free_irq ( shpnt - > irq , NULL ) ;
NCR5380_exit ( host ) ;
if ( shpnt - > io_port )
release_region ( shpnt - > io_port , shpnt - > n_io_port ) ;
scsi_host_put ( host ) ;
return 0 ;
}
module_init ( ecoscsi_init ) ;
module_exit ( ecoscsi_exit ) ;
MODULE_AUTHOR ( " Russell King " ) ;
MODULE_DESCRIPTION ( " Econet-SCSI driver for Acorn machines " ) ;
MODULE_LICENSE ( " GPL " ) ;