/* * pata_ali.c - ALI 15x3 PATA for new ATA layer * (C) 2005 Red Hat Inc * * based in part upon * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02 * * Copyright (C) 1998-2000 Michel Aubry, Maintainer * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer * * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) * May be copied or modified under the terms of the GNU General Public License * Copyright (C) 2002 Alan Cox <alan@redhat.com> * ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw> * * Documentation * Chipset documentation available under NDA only * * TODO/CHECK * Cannot have ATAPI on both master & slave for rev < c2 (???) but * otherwise should do atapi DMA (For now for old we do PIO only for * ATAPI) * Review Sunblade workaround.
*/
/* Certain laptops use short but suitable cables and don't
implement the detect logic */
if (ali_cable_override(pdev)) return ATA_CBL_PATA40_SHORT;
/* Host view cable detect 0x4A bit 0 primary bit 1 secondary
Bit set for 40 pin */
pci_read_config_byte(pdev, 0x4A, &ata66); if (ata66 & (1 << ap->port_no)) return ATA_CBL_PATA40; else return ATA_CBL_PATA80;
}
/** * ali_20_filter - filter for earlier ALI DMA * @adev: ATA device * @mask: received mask to manipulate and pass back * * Ensure that we do not do DMA on CD devices. We may be able to * fix that later on. Also ensure we do not do UDMA on WDC drives
*/
staticunsignedint ali_20_filter(struct ata_device *adev, unsignedint mask)
{ char model_num[ATA_ID_PROD_LEN + 1]; /* No DMA on anything but a disk for now */ if (adev->class != ATA_DEV_ATA)
mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num)); if (strstr(model_num, "WDC"))
mask &= ~ATA_MASK_UDMA; return mask;
}
/** * ali_fifo_control - FIFO manager * @ap: ALi channel to control * @adev: device for FIFO control * @on: 0 for off 1 for on * * Enable or disable the FIFO on a given device. Because of the way the * ALi FIFO works it provides a boost on ATA disk but can be confused by * ATAPI and we must therefore manage it.
*/
staticvoid ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on)
{ struct pci_dev *pdev = to_pci_dev(ap->host->dev); int pio_fifo = 0x54 + ap->port_no;
u8 fifo; int shift = 4 * adev->devno;
/* ATA - FIFO on set nibble to 0x05, ATAPI - FIFO off, set nibble to 0x00. Not all the docs agree but the behaviour we now use is the
one stated in the BIOS Programming Guide */
/** * ali_program_modes - load mode registers * @ap: ALi channel to load * @adev: Device the timing is for * @t: timing data * @ultra: UDMA timing or zero for off * * Loads the timing registers for cmd/data and disable UDMA if * ultra is zero. If ultra is set then load and enable the UDMA * timing but do not touch the command/data timing.
*/
/* PIO FIFO is only permitted on ATA disk */ if (adev->class != ATA_DEV_ATA)
ali_fifo_control(ap, adev, 0x00);
ali_program_modes(ap, adev, &t, 0); if (adev->class == ATA_DEV_ATA)
ali_fifo_control(ap, adev, 0x05);
}
/** * ali_set_dmamode - set initial DMA mode data * @ap: ATA interface * @adev: ATA device * * Program the ALi registers for DMA mode.
*/
/** * ali_warn_atapi_dma - Warn about ATAPI DMA disablement * @adev: Device * * Whine about ATAPI DMA disablement if @adev is an ATAPI device. * Can be used as ->dev_config.
*/
if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
ata_dev_warn(adev, "WARNING: ATAPI DMA disabled for reliability issues. It can be enabled\n");
ata_dev_warn(adev, "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
}
}
/** * ali_lock_sectors - Keep older devices to 255 sector mode * @adev: Device * * Called during the bus probe for each device that is found. We use * this call to lock the sector count of the device to 255 or less on * older ALi controllers. If we didn't do this then large I/O's would * require LBA48 commands which the older ALi requires are issued by * slower PIO methods
*/
/** * ali_check_atapi_dma - DMA check for most ALi controllers * @qc: Command to complete * * Called to decide whether commands should be sent by DMA or PIO
*/
staticint ali_check_atapi_dma(struct ata_queued_cmd *qc)
{ if (!ali_atapi_dma) { /* FIXME: pata_ali can't do ATAPI DMA reliably but the * IDE alim15x3 driver can. I tried lots of things * but couldn't find what the actual difference was. * If you got an idea, please write it to * linux-ide@vger.kernel.org and cc htejun@gmail.com. * * Disable ATAPI DMA for now.
*/ return -EOPNOTSUPP;
}
/* If its not a media command, its not worth it */ if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC) return -EOPNOTSUPP; return 0;
}
/* If our bridge is an ALI 1533 then do the extra work */ if (ali_isa_bridge) { /* Tristate and re-enable the bus signals */
pci_read_config_byte(ali_isa_bridge, 0x58, &r);
r &= ~port_bit;
pci_write_config_byte(ali_isa_bridge, 0x58, r);
r |= port_bit;
pci_write_config_byte(ali_isa_bridge, 0x58, r);
}
ata_sff_postreset(link, classes);
}
/* * Port operations for DMA capable ALi without cable * detect
*/ staticstruct ata_port_operations ali_20_port_ops = {
.inherits = &ali_dma_base_ops,
.cable_detect = ata_cable_40wire,
.mode_filter = ali_20_filter,
.check_atapi_dma = ali_check_atapi_dma,
.dev_config = ali_lock_sectors,
};
/* * Port operations for DMA capable ALi with cable detect
*/ staticstruct ata_port_operations ali_c2_port_ops = {
.inherits = &ali_dma_base_ops,
.check_atapi_dma = ali_check_atapi_dma,
.cable_detect = ali_c2_cable_detect,
.dev_config = ali_lock_sectors,
.reset.postreset = ali_c2_c3_postreset,
};
/* * Port operations for DMA capable ALi with cable detect
*/ staticstruct ata_port_operations ali_c4_port_ops = {
.inherits = &ali_dma_base_ops,
.check_atapi_dma = ali_check_atapi_dma,
.cable_detect = ali_c2_cable_detect,
.dev_config = ali_lock_sectors,
};
/* * Port operations for DMA capable ALi with cable detect and LBA48
*/ staticstruct ata_port_operations ali_c5_port_ops = {
.inherits = &ali_dma_base_ops,
.check_atapi_dma = ali_check_atapi_dma,
.dev_config = ali_warn_atapi_dma,
.cable_detect = ali_c2_cable_detect,
};
/** * ali_init_chipset - chip setup function * @pdev: PCI device of ATA controller * * Perform the setup on the device that must be done both at boot * and at resume time.
*/
/* * The chipset revision selects the driver operations and * mode data.
*/
if (pdev->revision <= 0x20) {
pci_read_config_byte(pdev, 0x53, &tmp);
tmp |= 0x03;
pci_write_config_byte(pdev, 0x53, tmp);
} else {
pci_read_config_byte(pdev, 0x4a, &tmp);
pci_write_config_byte(pdev, 0x4a, tmp | 0x20);
pci_read_config_byte(pdev, 0x4B, &tmp); if (pdev->revision < 0xC2) /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ /* Clear CD-ROM DMA write bit */
tmp &= 0x7F; /* Cable and UDMA */ if (pdev->revision >= 0xc2)
tmp |= 0x01;
pci_write_config_byte(pdev, 0x4B, tmp | 0x08); /* * CD_ROM DMA on (0x53 bit 0). Enable this even if we want * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control * via 0x54/55.
*/
pci_read_config_byte(pdev, 0x53, &tmp); if (pdev->revision >= 0xc7)
tmp |= 0x03; else
tmp |= 0x01; /* CD_ROM enable for DMA */
pci_write_config_byte(pdev, 0x53, tmp);
}
north = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 0,
PCI_DEVFN(0, 0)); if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) { /* Configure the ALi bridge logic. For non ALi rely on BIOS.
Set the south bridge enable bit */
pci_read_config_byte(ali_isa_bridge, 0x79, &tmp); if (pdev->revision == 0xC2)
pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04); elseif (pdev->revision > 0xC2 && pdev->revision < 0xC5)
pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
}
pci_dev_put(north);
ata_pci_bmdma_clear_simplex(pdev);
} /** * ali_init_one - discovery callback * @pdev: PCI device ID * @id: PCI table info * * An ALi IDE interface has been discovered. Figure out what revision * and perform configuration work before handing it to the ATA layer
*/
MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("low-level driver for ALi PATA");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, ali);
MODULE_VERSION(DRV_VERSION);
module_init(ali_init);
module_exit(ali_exit);
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.