reg4b |= mask;
pci_write_config_byte(pdev, 0x4B, reg4b);
}
/**
* sis_old_set_piomode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Device we are configuring for.
*
* Set PIO mode for device, in host controller PCI config space. This
* function handles PIO set up for all chips that are pre ATA100 and
* also early ATA100 devices.
*
* LOCKING:
* None (inherited from caller).
*/
static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
int port = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno;
u8 t1, t2;
int speed = adev->pio_mode - XFER_PIO_0;
const u8 active[] = { 0x00, 0x07, 0x04, 0x03, 0x01 };
const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 };
sis_set_fifo(ap, adev);
pci_read_config_byte(pdev, port, &t1);
pci_read_config_byte(pdev, port + 1, &t2);
t1 &= ~0x0F; /* Clear active/recovery timings */
t2 &= ~0x07;
t1 |= active[speed];
t2 |= recovery[speed];
pci_write_config_byte(pdev, port, t1);
pci_write_config_byte(pdev, port + 1, t2);
}
/**
* sis_100_set_pioode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Device we are configuring for.
*
* Set PIO mode for device, in host controller PCI config space. This
* function handles PIO set up for ATA100 devices and early ATA133.
*
* LOCKING:
* None (inherited from caller).
*/
static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
int port = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno;
int speed = adev->pio_mode - XFER_PIO_0;
const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 };
sis_set_fifo(ap, adev);
pci_write_config_byte(pdev, port, actrec[speed]);
}
/**
* sis_133_set_pioode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: Device we are configuring for.
*
* Set PIO mode for device, in host controller PCI config space. This
* function handles PIO set up for the later ATA133 devices.
*
* LOCKING:
* None (inherited from caller).
*/
static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
int port = 0x40;
u32 t1;
u32 reg54;
int speed = adev->pio_mode - XFER_PIO_0;
const u32 timing100[] = {
0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */
0x0C266000,
0x04263000,
0x0C0A3000,
0x05093000
};
const u32 timing133[] = {
0x1E1C6000, /* Recovery << 24 | Act << 16 | Ini << 12 */
0x091C4000,
0x031C2000,
0x09072000,
0x04062000
};
sis_set_fifo(ap, adev);
pci_read_config_dword(pdev, 0x54, ®54);
if(reg54 & 0x40000000)
port = 0x70;
port += 8 * ap->hard_port_no + 4 * adev->devno;
pci_read_config_dword(pdev, port, &t1);
t1 &= 0xC0C00FFF; /* Mask out timing */
if(t1 & 0x08) /* 100 or 133 ? */
t1 |= timing133[speed];
else
t1 |= timing100[speed];
pci_write_config_byte(pdev, port, t1);
}
/**
* sis_old_set_dmamode - Initialize host controller PATA DMA timings
* @ap: Port whose timings we are configuring
* @adev: Device to program
*
* Set UDMA/MWDMA mode for device, in host controller PCI config space.
* Handles pre UDMA and UDMA33 devices. Supports MWDMA as well unlike
* the old ide/pci driver.
*
* LOCKING:
* None (inherited from caller).
*/
static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
int speed = adev->dma_mode - XFER_MW_DMA_0;
int drive_pci = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno;
u16 timing;
const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 };
const u16 udma_bits[] = {
0xE000, 0xC000, 0xA000
};
pci_read_config_word(pdev, drive_pci, &timing);
if(adev->dma_mode < XFER_UDMA_0) {
t1 &= ~0x00000004;
/* FIXME: need data sheet to add MWDMA here. Also lacking on
ide/pci driver */
} else {
speed = adev->dma_mode - XFER_UDMA_0;
/* if & 8 no UDMA133 - need info for ... */
t1 &= ~0x00000FF0;
t1 |= 0x00000004;
if(t1 & 0x08)
t1 |= timing_u133[speed];
else
t1 |= timing_u100[speed];
}
pci_write_config_dword(pdev, port, t1);
}
static struct scsi_host_template sis_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.eh_strategy_handler = ata_scsi_error,
.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,
.ordered_flush = 1,
};
static const struct ata_port_operations sis_133_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_133_set_piomode,
.set_dmamode = sis_133_set_dmamode,
.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,
.phy_reset = sis_133_phy_reset,
.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,
.eng_timeout = ata_eng_timeout,
.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,
};
static const struct ata_port_operations sis_133_early_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_100_set_piomode,
.set_dmamode = sis_133_early_set_dmamode,
.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,
.phy_reset = sis_66_phy_reset,
.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,
.eng_timeout = ata_eng_timeout,
.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,
};
static const struct ata_port_operations sis_100_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_100_set_piomode,
.set_dmamode = sis_100_set_dmamode,
.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,
.phy_reset = sis_66_phy_reset,
.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,
.eng_timeout = ata_eng_timeout,
.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,
};
static const struct ata_port_operations sis_66_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_old_set_piomode,
.set_dmamode = sis_66_set_dmamode,
.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,
.phy_reset = sis_66_phy_reset,
.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,
.eng_timeout = ata_eng_timeout,
.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,
};
static const struct ata_port_operations sis_old_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_old_set_piomode,
.set_dmamode = sis_old_set_dmamode,
.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,
.phy_reset = sis_old_phy_reset,
.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,
.eng_timeout = ata_eng_timeout,
.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,
};
static struct ata_port_info sis_info = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07,
.udma_mask = 0,
.port_ops = &sis_old_ops,
};
static struct ata_port_info sis_info33 = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2, /* UDMA 33 */
.port_ops = &sis_old_ops,
};
static struct ata_port_info sis_info66 = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &sis_66_ops,
};
static struct ata_port_info sis_info100 = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA5,
.port_ops = &sis_100_ops,
};
static struct ata_port_info sis_info100_early = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.udma_mask = ATA_UDMA5,
.pio_mask = 0x1f, /* pio0-4 */
.port_ops = &sis_66_ops,
};
static struct ata_port_info sis_info133 = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_ops,
};
static struct ata_port_info sis_info133_early = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_early_ops,
};
static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
{
u16 regw;
u8 reg;
if (sis->info == &sis_info133) {
pci_read_config_word(pdev, 0x50, ®w);
if(regw & 0x08)
pci_write_config_word(pdev, 0x50, regw & ~0x08);
pci_read_config_word(pdev, 0x52, ®w);
if(regw & 0x08)
pci_write_config_word(pdev, 0x52, regw & ~0x08);
return;
}
if (sis->info == &sis_info133_early || sis->info == &sis_info100) {
/* Fix up latency */
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
/* Set compatibility bit */
pci_read_config_byte(pdev, 0x49, ®);
if (!(reg & 0x01))
pci_write_config_byte(pdev, 0x49, reg | 0x01);
return;
}
if (sis->info == &sis_info66 || sis->info == &sis_info100_early) {
/* Fix up latency */
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
/* Set compatibility bit */
pci_read_config_byte(pdev, 0x52, ®);
if (!(reg & 0x04))
pci_write_config_byte(pdev, 0x52, reg | 0x04);
return;
}
if (sis->info == &sis_info33) {
pci_read_config_byte(pdev, PCI_CLASS_PROG, ®);
if (( reg & 0x0F ) != 0x00)
pci_write_config_byte(pdev, PCI_CLASS_PROG, reg & 0xF0);
/* Fall through to ATA16 fixup below */
}
if (sis->info == &sis_info || sis->info == &sis_info33) {
/* force per drive recovery and active timings
needed on ATA_33 and below chips */
pci_read_config_byte(pdev, 0x52, ®);
if (!(reg & 0x08))
pci_write_config_byte(pdev, 0x52, reg|0x08);
return;
}
BUG();
}
/**
* sis_init_one - Register SiS ATA PCI device with kernel services
* @pdev: PCI device to register
* @ent: Entry in sis_pci_tbl matching with @pdev
*
* Called from kernel PCI layer. We probe for combined mode (sigh),
* and then hand over control to libata, for it to do the rest.
*
* LOCKING:
* Inherited from PCI layer (may sleep).
*
* RETURNS:
* Zero on success, or -ERRNO value.
*/
static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
static struct ata_port_info *port_info[2];
struct ata_port_info *port;
struct pci_dev *host;
struct sis_chipset *chipset = NULL;
static struct sis_chipset sis_chipsets[] = {
{ 0x0745, &sis_info100 },
{ 0x0735, &sis_info100 },
{ 0x0733, &sis_info100 },
{ 0x0635, &sis_info100 },
{ 0x0633, &sis_info100 },
{ 0x0730, &sis_info100_early }, /* 100 with ATA 66 layout */
{ 0x0550, &sis_info100_early }, /* 100 with ATA 66 layout */
{ 0x0640, &sis_info66 },
{ 0x0630, &sis_info66 },
{ 0x0620, &sis_info66 },
{ 0x0540, &sis_info66 },
{ 0x0530, &sis_info66 },
{ 0x5600, &sis_info33 },
{ 0x5598, &sis_info33 },
{ 0x5597, &sis_info33 },
{ 0x5591, &sis_info33 },
{ 0x5582, &sis_info33 },
{ 0x5581, &sis_info33 },
{ 0x5596, &sis_info },
{ 0x5571, &sis_info },
{ 0x5517, &sis_info },
{ 0x5511, &sis_info },
{0}
};
static struct sis_chipset sis133_early = {
0x0, &sis_info133_early
};
static struct sis_chipset sis133 = {
0x0, &sis_info133
};
static struct sis_chipset sis100_early = {
0x0, &sis_info100_early
};
static struct sis_chipset sis100 = {
0x0, &sis_info100
};
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev,
"version " DRV_VERSION "\n");
/* We have to find the bridge first */
for (chipset = &sis_chipsets[0]; chipset->device; chipset++) {
host = pci_get_device(0x1039, chipset->device, NULL);
if (host != NULL) {
if (chipset->device == 0x630) { /* SIS630 */
u8 host_rev;
pci_read_config_byte(host, PCI_REVISION_ID, &host_rev);
if(host_rev >= 0x30) /* 630 ET */
chipset = &sis100_early;
}
break;
}
}
/* Look for concealed bridges */
if (host == NULL) {
/* Second check */
u32 idemisc;
u16 trueid;
/* Disable ID masking and register remapping then
see what the real ID is */
pci_read_config_dword(pdev, 0x54, &idemisc);
pci_write_config_dword(pdev, 0x54, idemisc & 0x7fffffff);
pci_read_config_word(pdev, PCI_DEVICE_ID, &trueid);
pci_write_config_dword(pdev, 0x54, idemisc);
switch(trueid) {
case 0x5518: /* SIS 962/963 */
chipset = &sis133;
if ((idemisc & 0x40000000) == 0) {
pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000);
printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
}
break;
case 0x0180: /* SIS 965L */
chipset = &sis133;
break;
}
}
/* Further check */
if(chipset == NULL) {
struct pci_dev *lpc_bridge;
u16 trueid;
u8 prefctl;
u8 idecfg;
u8 sbrev;
/* Try the second unmasking technique */
pci_read_config_byte(pdev, 0x4a, &idecfg);
pci_write_config_byte(pdev, 0x4a, idecfg | 0x10);
pci_read_config_word(pdev, PCI_DEVICE_ID, &trueid);
pci_write_config_byte(pdev, 0x4a, idecfg);
switch(trueid) {
case 0x5517:
lpc_bridge = pci_get_slot(0x00, 0x10); /* Bus 0 Dev 2 Fn 0 */
if(lpc_bridge == NULL)
break;
pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
pci_read_config_byte(pdev, 0x49, &prefctl);
pci_dev_put(lpc_bridge);
if(sbrev == 0x10 && (prefctl & 0x80)) {
chipset = &sis133_early;
break;
}
chipset = &sis100;
break;
}
}
pci_dev_put(host);
/* No chipset info, no support */
if (chipset == NULL)
return -ENODEV;
port = chipset->info;
port->private_data = chipset;
sis_fixup(pdev, chipset);
port_info[0] = port_info[1] = port;
return ata_pci_init_one(pdev, port_info, 2);
}
static const struct pci_device_id sis_pci_tbl[] = {
{ 0x1039, 0x5513, PCI_ANY_ID, PCI_ANY_ID, },
{ 0x1039, 0x5518, PCI_ANY_ID, PCI_ANY_ID, },
{ } /* terminate list */
};
static struct pci_driver sis_pci_driver = {
.name = DRV_NAME,
.id_table = sis_pci_tbl,
.probe = sis_init_one,
.remove = ata_pci_remove_one,
};
static int __init sis_init(void)
{
int rc;
DPRINTK("pci_module_init\n");
rc = pci_module_init(&sis_pci_driver);
if (rc)
return rc;
DPRINTK("done\n");
return 0;
}