2006-08-30 02:12:40 +04:00
/*
* pata_cypress . c - Cypress PATA for new ATA layer
* ( C ) 2006 Red Hat Inc
* Alan Cox < alan @ redhat . com >
*
* Based heavily on
* linux / drivers / ide / pci / cy82c693 . c Version 0.40 Sep . 10 , 2002
*
*/
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/pci.h>
# include <linux/init.h>
# include <linux/blkdev.h>
# include <linux/delay.h>
# include <scsi/scsi_host.h>
# include <linux/libata.h>
# define DRV_NAME "pata_cypress"
2007-05-22 04:26:38 +04:00
# define DRV_VERSION "0.1.5"
2006-08-30 02:12:40 +04:00
/* here are the offset definitions for the registers */
enum {
CY82_IDE_CMDREG = 0x04 ,
CY82_IDE_ADDRSETUP = 0x48 ,
CY82_IDE_MASTER_IOR = 0x4C ,
CY82_IDE_MASTER_IOW = 0x4D ,
CY82_IDE_SLAVE_IOR = 0x4E ,
CY82_IDE_SLAVE_IOW = 0x4F ,
CY82_IDE_MASTER_8BIT = 0x50 ,
CY82_IDE_SLAVE_8BIT = 0x51 ,
CY82_INDEX_PORT = 0x22 ,
CY82_DATA_PORT = 0x23 ,
CY82_INDEX_CTRLREG1 = 0x01 ,
CY82_INDEX_CHANNEL0 = 0x30 ,
CY82_INDEX_CHANNEL1 = 0x31 ,
CY82_INDEX_TIMEOUT = 0x32
} ;
/**
* cy82c693_set_piomode - set initial PIO mode data
* @ ap : ATA interface
* @ adev : ATA device
*
* Called to do the PIO mode setup .
*/
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
static void cy82c693_set_piomode ( struct ata_port * ap , struct ata_device * adev )
{
struct pci_dev * pdev = to_pci_dev ( ap - > host - > dev ) ;
struct ata_timing t ;
const unsigned long T = 1000000 / 33 ;
short time_16 , time_8 ;
u32 addr ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
if ( ata_timing_compute ( adev , adev - > pio_mode , & t , T , 1 ) < 0 ) {
printk ( KERN_ERR DRV_NAME " : mome computation failed. \n " ) ;
return ;
}
time_16 = FIT ( t . recover , 0 , 15 ) | ( FIT ( t . active , 0 , 15 ) < < 4 ) ;
time_8 = FIT ( t . act8b , 0 , 15 ) | ( FIT ( t . rec8b , 0 , 15 ) < < 4 ) ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
if ( adev - > devno = = 0 ) {
pci_read_config_dword ( pdev , CY82_IDE_ADDRSETUP , & addr ) ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
addr & = ~ 0x0F ; /* Mask bits */
addr | = FIT ( t . setup , 0 , 15 ) ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
pci_write_config_dword ( pdev , CY82_IDE_ADDRSETUP , addr ) ;
pci_write_config_byte ( pdev , CY82_IDE_MASTER_IOR , time_16 ) ;
pci_write_config_byte ( pdev , CY82_IDE_MASTER_IOW , time_16 ) ;
pci_write_config_byte ( pdev , CY82_IDE_MASTER_8BIT , time_8 ) ;
} else {
pci_read_config_dword ( pdev , CY82_IDE_ADDRSETUP , & addr ) ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
addr & = ~ 0xF0 ; /* Mask bits */
addr | = ( FIT ( t . setup , 0 , 15 ) < < 4 ) ;
pci_write_config_dword ( pdev , CY82_IDE_ADDRSETUP , addr ) ;
pci_write_config_byte ( pdev , CY82_IDE_SLAVE_IOR , time_16 ) ;
pci_write_config_byte ( pdev , CY82_IDE_SLAVE_IOW , time_16 ) ;
pci_write_config_byte ( pdev , CY82_IDE_SLAVE_8BIT , time_8 ) ;
}
}
/**
* cy82c693_set_dmamode - set initial DMA mode data
* @ ap : ATA interface
* @ adev : ATA device
*
* Called to do the DMA mode setup .
*/
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
static void cy82c693_set_dmamode ( struct ata_port * ap , struct ata_device * adev )
{
int reg = CY82_INDEX_CHANNEL0 + ap - > port_no ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
/* Be afraid, be very afraid. Magic registers in low I/O space */
outb ( reg , 0x22 ) ;
outb ( adev - > dma_mode - XFER_MW_DMA_0 , 0x23 ) ;
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
/* 0x50 gives the best behaviour on the Alpha's using this chip */
outb ( CY82_INDEX_TIMEOUT , 0x22 ) ;
outb ( 0x50 , 0x23 ) ;
}
static struct scsi_host_template cy82c693_sht = {
. module = THIS_MODULE ,
. name = DRV_NAME ,
. ioctl = ata_scsi_ioctl ,
. queuecommand = ata_scsi_queuecmd ,
. can_queue = ATA_DEF_QUEUE ,
. this_id = ATA_SHT_THIS_ID ,
. sg_tablesize = LIBATA_MAX_PRD ,
. cmd_per_lun = ATA_SHT_CMD_PER_LUN ,
. emulated = ATA_SHT_EMULATED ,
. use_clustering = ATA_SHT_USE_CLUSTERING ,
. proc_name = DRV_NAME ,
. dma_boundary = ATA_DMA_BOUNDARY ,
. slave_configure = ata_scsi_slave_config ,
2006-11-29 05:26:47 +03:00
. slave_destroy = ata_scsi_slave_destroy ,
2006-08-30 02:12:40 +04:00
. bios_param = ata_std_bios_param ,
} ;
static struct ata_port_operations cy82c693_port_ops = {
. set_piomode = cy82c693_set_piomode ,
. set_dmamode = cy82c693_set_dmamode ,
. mode_filter = ata_pci_default_filter ,
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
. tf_load = ata_tf_load ,
. tf_read = ata_tf_read ,
. check_status = ata_check_status ,
. exec_command = ata_exec_command ,
. dev_select = ata_std_dev_select ,
. freeze = ata_bmdma_freeze ,
. thaw = ata_bmdma_thaw ,
2007-04-11 03:04:20 +04:00
. error_handler = ata_bmdma_error_handler ,
2006-08-30 02:12:40 +04:00
. post_internal_cmd = ata_bmdma_post_internal_cmd ,
2007-04-11 03:04:20 +04:00
. cable_detect = ata_cable_40wire ,
2006-08-30 02:12:40 +04:00
. bmdma_setup = ata_bmdma_setup ,
. bmdma_start = ata_bmdma_start ,
. bmdma_stop = ata_bmdma_stop ,
. bmdma_status = ata_bmdma_status ,
. qc_prep = ata_qc_prep ,
. qc_issue = ata_qc_issue_prot ,
2006-09-27 13:41:13 +04:00
2007-02-01 09:06:36 +03:00
. data_xfer = ata_data_xfer ,
2006-08-30 02:12:40 +04:00
. irq_handler = ata_interrupt ,
. irq_clear = ata_bmdma_irq_clear ,
2007-01-26 10:27:58 +03:00
. irq_on = ata_irq_on ,
2006-08-31 08:03:49 +04:00
2007-08-23 01:55:41 +04:00
. port_start = ata_sff_port_start ,
2006-08-31 08:03:49 +04:00
} ;
2006-08-30 02:12:40 +04:00
static int cy82c693_init_one ( struct pci_dev * pdev , const struct pci_device_id * id )
{
2007-05-04 14:43:58 +04:00
static const struct ata_port_info info = {
2006-08-30 02:12:40 +04:00
. sht = & cy82c693_sht ,
2007-05-28 14:59:48 +04:00
. flags = ATA_FLAG_SLAVE_POSS ,
2006-08-30 02:12:40 +04:00
. pio_mask = 0x1f ,
. mwdma_mask = 0x07 ,
. port_ops = & cy82c693_port_ops
} ;
2007-05-04 14:43:58 +04:00
const struct ata_port_info * ppi [ ] = { & info , & ata_dummy_port_info } ;
2006-08-31 08:03:49 +04:00
2006-09-29 04:21:59 +04:00
/* Devfn 1 is the ATA primary. The secondary is magic and on devfn2.
For the moment we don ' t handle the secondary . FIXME */
2006-08-31 08:03:49 +04:00
2006-08-30 02:12:40 +04:00
if ( PCI_FUNC ( pdev - > devfn ) ! = 1 )
return - ENODEV ;
2006-08-31 08:03:49 +04:00
2007-05-04 14:43:58 +04:00
return ata_pci_init_one ( pdev , ppi ) ;
2006-08-30 02:12:40 +04:00
}
2006-09-29 04:21:59 +04:00
static const struct pci_device_id cy82c693 [ ] = {
{ PCI_VDEVICE ( CONTAQ , PCI_DEVICE_ID_CONTAQ_82C693 ) , } ,
{ } ,
2006-08-30 02:12:40 +04:00
} ;
static struct pci_driver cy82c693_pci_driver = {
2006-09-29 04:21:59 +04:00
. name = DRV_NAME ,
2006-08-30 02:12:40 +04:00
. id_table = cy82c693 ,
. probe = cy82c693_init_one ,
2006-11-22 19:57:36 +03:00
. remove = ata_pci_remove_one ,
2007-03-02 11:31:26 +03:00
# ifdef CONFIG_PM
2006-11-22 19:57:36 +03:00
. suspend = ata_pci_device_suspend ,
. resume = ata_pci_device_resume ,
2007-03-02 11:31:26 +03:00
# endif
2006-08-30 02:12:40 +04:00
} ;
static int __init cy82c693_init ( void )
{
return pci_register_driver ( & cy82c693_pci_driver ) ;
}
static void __exit cy82c693_exit ( void )
{
pci_unregister_driver ( & cy82c693_pci_driver ) ;
}
MODULE_AUTHOR ( " Alan Cox " ) ;
MODULE_DESCRIPTION ( " low-level driver for the CY82C693 PATA controller " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DEVICE_TABLE ( pci , cy82c693 ) ;
MODULE_VERSION ( DRV_VERSION ) ;
module_init ( cy82c693_init ) ;
module_exit ( cy82c693_exit ) ;