2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 1996 Linus Torvalds & author ( see below )
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/delay.h>
# include <linux/timer.h>
# include <linux/mm.h>
# include <linux/ioport.h>
# include <linux/blkdev.h>
# include <linux/ide.h>
# include <linux/init.h>
# include <asm/io.h>
2008-04-27 00:25:18 +04:00
# define DRV_NAME "dtc2278"
2005-04-17 02:20:36 +04:00
/*
* Changing this # undef to # define may solve start up problems in some systems .
*/
# undef ALWAYS_SET_DTC2278_PIO_MODE
/*
* From : andy @ cercle . cts . com ( Dyan Wile )
*
* Below is a patch for DTC - 2278 - alike software - programmable controllers
* The code enables the secondary IDE controller and the PIO4 ( 3 ? ) timings on
* the primary ( EIDE ) . You may probably have to enable the 32 - bit support to
* get the full speed . You better get the disk interrupts disabled ( hdparm - u0
* / dev / hd . . ) for the drives connected to the EIDE interface . ( I get my
* filesystem corrupted with - u1 , but under heavy disk load only : - )
*
* This card is now forced to use the " serialize " feature ,
* and irq - unmasking is disallowed . If io_32bit is enabled ,
* it must be done for BOTH drives on each interface .
*
* This code was written for the DTC2278E , but might work with any of these :
*
* DTC2278S has only a single IDE interface .
* DTC2278D has two IDE interfaces and is otherwise identical to the S version .
* DTC2278E also has serial ports and a printer port
* DTC2278EB : has onboard BIOS , and " works like a charm " - - Kent Bradford < kent @ theory . caltech . edu >
*
* There may be a fourth controller type . The S and D versions use the
* Winbond chip , and I think the E version does also .
*
*/
static void sub22 ( char b , char c )
{
int i ;
for ( i = 0 ; i < 3 ; + + i ) {
inb ( 0x3f6 ) ;
outb_p ( b , 0xb0 ) ;
inb ( 0x3f6 ) ;
outb_p ( c , 0xb4 ) ;
inb ( 0x3f6 ) ;
if ( inb ( 0xb4 ) = = c ) {
outb_p ( 7 , 0xb0 ) ;
inb ( 0x3f6 ) ;
return ; /* success */
}
}
}
2007-10-20 02:32:35 +04:00
static DEFINE_SPINLOCK ( dtc2278_lock ) ;
2010-01-19 12:44:41 +03:00
static void dtc2278_set_pio_mode ( ide_hwif_t * hwif , ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
unsigned long flags ;
2010-01-19 12:44:41 +03:00
if ( drive - > pio_mode > = XFER_PIO_3 ) {
2007-10-20 02:32:35 +04:00
spin_lock_irqsave ( & dtc2278_lock , flags ) ;
2005-04-17 02:20:36 +04:00
/*
* This enables PIO mode4 ( 3 ? ) on the first interface
*/
sub22 ( 1 , 0xc3 ) ;
sub22 ( 0 , 0xa0 ) ;
2007-10-20 02:32:35 +04:00
spin_unlock_irqrestore ( & dtc2278_lock , flags ) ;
2005-04-17 02:20:36 +04:00
} else {
/* we don't know how to set it back again.. */
2007-10-20 02:32:37 +04:00
/* Actually we do - there is a data sheet available for the
Winbond but does anyone actually care */
2005-04-17 02:20:36 +04:00
}
}
2008-04-27 00:25:14 +04:00
static const struct ide_port_ops dtc2278_port_ops = {
. set_pio_mode = dtc2278_set_pio_mode ,
} ;
2008-02-02 21:56:31 +03:00
static const struct ide_port_info dtc2278_port_info __initdata = {
2008-04-27 00:25:18 +04:00
. name = DRV_NAME ,
2008-02-02 21:56:31 +03:00
. chipset = ide_dtc2278 ,
2008-04-27 00:25:14 +04:00
. port_ops = & dtc2278_port_ops ,
2008-02-02 21:56:31 +03:00
. host_flags = IDE_HFLAG_SERIALIZE |
2008-02-02 21:56:40 +03:00
IDE_HFLAG_NO_UNMASK_IRQS |
2008-02-02 21:56:31 +03:00
IDE_HFLAG_IO_32BIT |
2008-02-02 21:56:40 +03:00
/* disallow ->io_32bit changes */
IDE_HFLAG_NO_IO_32BIT |
2009-03-27 14:46:28 +03:00
IDE_HFLAG_NO_DMA |
IDE_HFLAG_DTC2278 ,
2008-02-02 21:56:31 +03:00
. pio_mask = ATA_PIO4 ,
} ;
2007-03-03 19:48:55 +03:00
static int __init dtc2278_probe ( void )
2005-04-17 02:20:36 +04:00
{
unsigned long flags ;
local_irq_save ( flags ) ;
/*
* This enables the second interface
*/
outb_p ( 4 , 0xb0 ) ;
inb ( 0x3f6 ) ;
outb_p ( 0x20 , 0xb4 ) ;
inb ( 0x3f6 ) ;
# ifdef ALWAYS_SET_DTC2278_PIO_MODE
/*
* This enables PIO mode4 ( 3 ? ) on the first interface
* and may solve start - up problems for some people .
*/
sub22 ( 1 , 0xc3 ) ;
sub22 ( 0 , 0xa0 ) ;
# endif
local_irq_restore ( flags ) ;
2008-04-27 00:25:16 +04:00
return ide_legacy_device_add ( & dtc2278_port_info , 0 ) ;
2005-04-17 02:20:36 +04:00
}
2008-04-27 17:38:24 +04:00
static int probe_dtc2278 ;
2007-03-03 19:48:55 +03:00
module_param_named ( probe , probe_dtc2278 , bool , 0 ) ;
MODULE_PARM_DESC ( probe , " probe for DTC2278xx chipsets " ) ;
2008-01-26 22:13:07 +03:00
static int __init dtc2278_init ( void )
2005-04-17 02:20:36 +04:00
{
2007-03-03 19:48:55 +03:00
if ( probe_dtc2278 = = 0 )
return - ENODEV ;
if ( dtc2278_probe ( ) ) {
2005-04-17 02:20:36 +04:00
printk ( KERN_ERR " dtc2278: ide interfaces already in use! \n " ) ;
return - EBUSY ;
}
return 0 ;
}
module_init ( dtc2278_init ) ;
MODULE_AUTHOR ( " See Local File " ) ;
MODULE_DESCRIPTION ( " support of DTC-2278 VLB IDE chipsets " ) ;
MODULE_LICENSE ( " GPL " ) ;