2006-08-30 02:12:40 +04:00
/*
* pata_hpt3x3 - HPT3x3 driver
* ( c ) Copyright 2005 - 2006 Red Hat
*
* Was pata_hpt34x but the naming was confusing as it supported the
* 343 and 363 so it has been renamed .
*
* Based on :
* linux / drivers / ide / pci / hpt34x . c Version 0.40 Sept 10 , 2002
* Copyright ( C ) 1998 - 2000 Andre Hedrick < andre @ linux - ide . org >
*
* May be copied or modified under the terms of the GNU General Public
* License
*/
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_hpt3x3"
# define DRV_VERSION "0.4.1"
static int hpt3x3_probe_init ( struct ata_port * ap )
{
ap - > cbl = ATA_CBL_PATA40 ;
return ata_std_prereset ( ap ) ;
}
/**
* hpt3x3_probe_reset - reset the hpt3x3 bus
* @ ap : ATA port to reset
*
* Perform the housekeeping when doing an ATA bus reeset . We just
* need to force the cable type .
*/
static void hpt3x3_error_handler ( struct ata_port * ap )
{
return ata_bmdma_drive_eh ( ap , hpt3x3_probe_init , ata_std_softreset , NULL , ata_std_postreset ) ;
}
/**
* hpt3x3_set_piomode - PIO setup
* @ ap : ATA interface
* @ adev : device on the interface
*
* Set our PIO requirements . This is fairly simple on the HPT3x3 as
* all we have to do is clear the MWDMA and UDMA bits then load the
* mode number .
*/
static void hpt3x3_set_piomode ( struct ata_port * ap , struct ata_device * adev )
{
struct pci_dev * pdev = to_pci_dev ( ap - > host - > dev ) ;
u32 r1 , r2 ;
int dn = 2 * ap - > port_no + adev - > devno ;
pci_read_config_dword ( pdev , 0x44 , & r1 ) ;
pci_read_config_dword ( pdev , 0x48 , & r2 ) ;
/* Load the PIO timing number */
r1 & = ~ ( 7 < < ( 3 * dn ) ) ;
r1 | = ( adev - > pio_mode - XFER_PIO_0 ) < < ( 3 * dn ) ;
r2 & = ~ ( 0x11 < < dn ) ; /* Clear MWDMA and UDMA bits */
pci_write_config_dword ( pdev , 0x44 , r1 ) ;
pci_write_config_dword ( pdev , 0x48 , r2 ) ;
}
/**
* hpt3x3_set_dmamode - DMA timing setup
* @ ap : ATA interface
* @ adev : Device being configured
*
* Set up the channel for MWDMA or UDMA modes . Much the same as with
* PIO , load the mode number and then set MWDMA or UDMA flag .
*/
static void hpt3x3_set_dmamode ( struct ata_port * ap , struct ata_device * adev )
{
struct pci_dev * pdev = to_pci_dev ( ap - > host - > dev ) ;
u32 r1 , r2 ;
int dn = 2 * ap - > port_no + adev - > devno ;
int mode_num = adev - > dma_mode & 0x0F ;
pci_read_config_dword ( pdev , 0x44 , & r1 ) ;
pci_read_config_dword ( pdev , 0x48 , & r2 ) ;
/* Load the timing number */
r1 & = ~ ( 7 < < ( 3 * dn ) ) ;
r1 | = ( mode_num < < ( 3 * dn ) ) ;
r2 & = ~ ( 0x11 < < dn ) ; /* Clear MWDMA and UDMA bits */
if ( adev - > dma_mode > = XFER_UDMA_0 )
r2 | = 0x01 < < dn ; /* Ultra mode */
else
r2 | = 0x10 < < dn ; /* MWDMA */
pci_write_config_dword ( pdev , 0x44 , r1 ) ;
pci_write_config_dword ( pdev , 0x48 , r2 ) ;
}
static struct scsi_host_template hpt3x3_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 ,
. max_sectors = ATA_MAX_SECTORS ,
. 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 ,
. bios_param = ata_std_bios_param ,
} ;
static struct ata_port_operations hpt3x3_port_ops = {
. port_disable = ata_port_disable ,
. set_piomode = hpt3x3_set_piomode ,
. set_dmamode = hpt3x3_set_dmamode ,
. mode_filter = ata_pci_default_filter ,
. 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 ,
. error_handler = hpt3x3_error_handler ,
. post_internal_cmd = ata_bmdma_post_internal_cmd ,
. 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
2006-08-30 02:12:40 +04:00
. data_xfer = ata_pio_data_xfer ,
. irq_handler = ata_interrupt ,
. irq_clear = ata_bmdma_irq_clear ,
. port_start = ata_port_start ,
. port_stop = ata_port_stop ,
. host_stop = ata_host_stop
} ;
/**
* hpt3x3_init_one - Initialise an HPT343 / 363
* @ dev : PCI device
* @ id : Entry in match table
*
* Perform basic initialisation . The chip has a quirk that it won ' t
* function unless it is at XX00 . The old ATA driver touched this up
* but we leave it for pci quirks to do properly .
*/
static int hpt3x3_init_one ( struct pci_dev * dev , const struct pci_device_id * id )
{
static struct ata_port_info info = {
. sht = & hpt3x3_sht ,
. flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST ,
. pio_mask = 0x1f ,
. mwdma_mask = 0x07 ,
. udma_mask = 0x07 ,
. port_ops = & hpt3x3_port_ops
} ;
static struct ata_port_info * port_info [ 2 ] = { & info , & info } ;
u16 cmd ;
/* Initialize the board */
pci_write_config_word ( dev , 0x80 , 0x00 ) ;
/* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */
pci_read_config_word ( dev , PCI_COMMAND , & cmd ) ;
if ( cmd & PCI_COMMAND_MEMORY )
pci_write_config_byte ( dev , PCI_LATENCY_TIMER , 0xF0 ) ;
else
pci_write_config_byte ( dev , PCI_LATENCY_TIMER , 0x20 ) ;
/* Now kick off ATA set up */
return ata_pci_init_one ( dev , port_info , 2 ) ;
}
2006-09-29 04:21:59 +04:00
static const struct pci_device_id hpt3x3 [ ] = {
{ PCI_VDEVICE ( TTI , PCI_DEVICE_ID_TTI_HPT343 ) , } ,
{ } ,
2006-08-30 02:12:40 +04:00
} ;
static struct pci_driver hpt3x3_pci_driver = {
2006-09-29 04:21:59 +04:00
. name = DRV_NAME ,
2006-08-30 02:12:40 +04:00
. id_table = hpt3x3 ,
. probe = hpt3x3_init_one ,
. remove = ata_pci_remove_one
} ;
static int __init hpt3x3_init ( void )
{
return pci_register_driver ( & hpt3x3_pci_driver ) ;
}
static void __exit hpt3x3_exit ( void )
{
pci_unregister_driver ( & hpt3x3_pci_driver ) ;
}
MODULE_AUTHOR ( " Alan Cox " ) ;
MODULE_DESCRIPTION ( " low-level driver for the Highpoint HPT343/363 " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DEVICE_TABLE ( pci , hpt3x3 ) ;
MODULE_VERSION ( DRV_VERSION ) ;
module_init ( hpt3x3_init ) ;
module_exit ( hpt3x3_exit ) ;