26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/pci.h>
35 #define DRV_NAME "pata_cmd64x"
36 #define DRV_VERSION "0.2.18"
73 static int cmd648_cable_detect(
struct ata_port *ap)
79 pci_read_config_byte(pdev,
BMIDECSR, &r);
98 const unsigned long T = 1000000 / 33;
99 const u8 setup_data[] = { 0x40, 0x40, 0x40, 0x80, 0x00 };
104 const u8 arttim_port[2][2] = {
108 const u8 drwtim_port[2][2] = {
134 t.active,
t.recover,
t.setup);
135 if (
t.recover > 16) {
136 t.active +=
t.recover - 16;
147 else if (
t.recover > 1)
155 t.setup = setup_data[
t.setup];
160 pci_read_config_byte(pdev, arttim, ®);
163 pci_write_config_byte(pdev, arttim, reg);
166 pci_write_config_byte(pdev, drwtim, (
t.active << 4) |
t.recover);
180 cmd64x_set_timing(ap, adev, adev->
pio_mode);
193 static const u8 udma_data[] = {
194 0x30, 0x20, 0x10, 0x20, 0x10, 0x00
202 int shift = 2 * adev->
devno;
204 pci_read_config_byte(pdev, pciD, ®D);
205 pci_read_config_byte(pdev, pciU, ®U);
208 regD &= ~(0x20 << adev->
devno);
210 regU &= ~(0x30 << shift);
212 regU &= ~(0x05 << adev->
devno);
218 regU |= 1 << adev->
devno;
220 regU |= 4 << adev->
devno;
222 regU &= ~ (1 << adev->
devno);
223 cmd64x_set_timing(ap, adev, adev->
dma_mode);
226 regD |= 0x20 << adev->
devno;
228 pci_write_config_byte(pdev, pciU, regU);
229 pci_write_config_byte(pdev, pciD, regD);
239 static bool cmd64x_sff_irq_check(
struct ata_port *ap)
247 pci_read_config_byte(pdev, irq_reg, &irq_stat);
249 return irq_stat & irq_mask;
259 static void cmd64x_sff_irq_clear(
struct ata_port *ap)
265 ata_bmdma_irq_clear(ap);
268 pci_read_config_byte(pdev, irq_reg, &irq_stat);
278 static bool cmd648_sff_irq_check(
struct ata_port *ap)
283 u8 mrdmode =
inb(base + 1);
285 return mrdmode & irq_mask;
295 static void cmd648_sff_irq_clear(
struct ata_port *ap)
302 ata_bmdma_irq_clear(ap);
305 mrdmode =
inb(base + 1);
307 outb(mrdmode | irq_mask, base + 1);
327 .inherits = &ata_bmdma_port_ops,
328 .set_piomode = cmd64x_set_piomode,
329 .set_dmamode = cmd64x_set_dmamode,
333 .inherits = &cmd64x_base_ops,
334 .sff_irq_check = cmd64x_sff_irq_check,
335 .sff_irq_clear = cmd64x_sff_irq_clear,
340 .inherits = &cmd64x_base_ops,
341 .sff_irq_check = cmd64x_sff_irq_check,
342 .sff_irq_clear = cmd64x_sff_irq_clear,
343 .bmdma_stop = cmd646r1_bmdma_stop,
348 .inherits = &cmd64x_base_ops,
349 .sff_irq_check = cmd648_sff_irq_check,
350 .sff_irq_clear = cmd648_sff_irq_clear,
355 .inherits = &cmd64x_base_ops,
356 .sff_irq_check = cmd648_sff_irq_check,
357 .sff_irq_clear = cmd648_sff_irq_clear,
358 .cable_detect = cmd648_cable_detect,
361 static void cmd64x_fixup(
struct pci_dev *pdev)
366 pci_read_config_byte(pdev,
MRDMODE, &mrdmode);
369 pci_write_config_byte(pdev,
MRDMODE, mrdmode);
373 pci_write_config_byte(pdev,
UDIDETCR0, 0xF0);
384 .port_ops = &cmd64x_port_ops
390 .port_ops = &cmd64x_port_ops
396 .port_ops = &cmd646r3_port_ops
403 .port_ops = &cmd646r3_port_ops
409 .port_ops = &cmd646r1_port_ops
416 .port_ops = &cmd648_port_ops
423 .port_ops = &cmd648_port_ops
427 &cmd_info[
id->driver_data],
428 &cmd_info[
id->driver_data],
435 int port_ok = !(bridge && bridge->
vendor ==
438 int cntrl_ch0_ok = (
id->driver_data != 0);
445 ata_pci_bmdma_clear_simplex(pdev);
451 ppi[0] = &cmd_info[3];
452 ppi[1] = &cmd_info[3];
457 ppi[0] = &cmd_info[2];
458 ppi[1] = &cmd_info[2];
462 ppi[0] = &cmd_info[4];
463 ppi[1] = &cmd_info[4];
475 pci_read_config_byte(pdev,
CNTRL, ®);
477 dev_printk(
KERN_NOTICE, &pdev->
dev,
"Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
478 if (port_ok && cntrl_ch0_ok && !(reg &
CNTRL_CH0)) {
479 dev_printk(
KERN_NOTICE, &pdev->
dev,
"Primary port is disabled\n");
484 dev_printk(
KERN_NOTICE, &pdev->
dev,
"Secondary port is disabled\n");
488 return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht,
NULL, 0);
492 static int cmd64x_reinit_one(
struct pci_dev *pdev)
497 rc = ata_pci_device_do_resume(pdev);
503 ata_host_resume(host);
517 static struct pci_driver cmd64x_pci_driver = {
520 .probe = cmd64x_init_one,
521 .remove = ata_pci_remove_one,
523 .suspend = ata_pci_device_suspend,
524 .resume = cmd64x_reinit_one,