// SPDX-License-Identifier: GPL-2.0-or-later /* * pata_pcmcia.c - PCMCIA PATA controller driver. * Copyright 2005-2006 Red Hat Inc, all rights reserved. * PCMCIA ident update Copyright 2006 Marcin Juszkiewicz * <openembedded@hrw.one.pl> * * Heavily based upon ide-cs.c * The initial developer of the original code is David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*/
/** * pcmcia_set_mode - PCMCIA specific mode setup * @link: link * @r_failed_dev: Return pointer for failed device * * Perform the tuning and setup of the devices and timings, which * for PCMCIA is the same as any other controller. We wrap it however * as we need to spot hardware with incorrect or missing master/slave * decode, which alas is embarrassingly common in the PC world
*/
if (!ata_dev_enabled(master) || !ata_dev_enabled(slave)) return ata_set_mode(link, r_failed_dev);
if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV,
ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) { /* Suspicious match, but could be two cards from
the same vendor - check serial */ if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO,
ATA_ID_SERNO_LEN) == 0 && master->id[ATA_ID_SERNO] >> 8) {
ata_dev_warn(slave, "is a ghost device, ignoring\n");
ata_dev_disable(slave);
}
} return ata_set_mode(link, r_failed_dev);
}
/** * pcmcia_set_mode_8bit - PCMCIA specific mode setup * @link: link * @r_failed_dev: Return pointer for failed device * * For the simple emulated 8bit stuff the less we do the better.
*/
/** * ata_data_xfer_8bit - Transfer data by 8bit PIO * @qc: queued command * @buf: data buffer * @buflen: buffer length * @rw: read/write * * Transfer data from/to the device data register by 8 bit PIO. * * LOCKING: * Inherited from caller.
*/
/** * pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers * @qc: command * * Drain the FIFO and device of any stuck data following a command * failing to complete. In some cases this is necessary before a * reset will recover the device. *
*/
staticvoid pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
{ int count; struct ata_port *ap;
/* We only need to flush incoming data when a command was running */ if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) return;
ap = qc->ap;
/* Drain up to 64K of data before we give up this recovery method */ for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
&& count++ < 65536;)
ioread8(ap->ioaddr.data_addr);
if (count)
ata_port_warn(ap, "drained %d bytes to clear DRQ\n", count);
/** * pcmcia_init_one - attach a PCMCIA interface * @pdev: pcmcia device * * Register a PCMCIA IDE interface. Such interfaces are PIO 0 and * shared IRQ.
*/
/* Set up attributes in order to probe card and get resources */
pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
is_kme = ((pdev->manf_id == MANFID_KME) &&
((pdev->card_id == PRODID_KME_KXLC005_A) ||
(pdev->card_id == PRODID_KME_KXLC005_B)));
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
pdev->config_flags &= ~CONF_AUTO_CHECK_VCC; if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) goto failed; /* No suitable config found */
}
io_base = pdev->resource[0]->start; if (pdev->resource[1]->end)
ctl_base = pdev->resource[1]->start; else
ctl_base = pdev->resource[0]->start + 0x0e;
if (!pdev->irq) goto failed;
ret = pcmcia_enable_device(pdev); if (ret) goto failed;
/* Success. Disable the IRQ nIEN line, do quirks */
iowrite8(0x02, ctl_addr); if (is_kme)
iowrite8(0x81, ctl_addr + 0x01);
/* FIXME: Could be more ports at base + 0x10 but we only deal with
one right now */ if (resource_size(pdev->resource[0]) >= 0x20)
n_ports = 2;
if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
ops = &pcmcia_8bit_port_ops; /* * Having done the PCMCIA plumbing the ATA side is relatively * sane.
*/
ret = -ENOMEM;
host = ata_host_alloc(&pdev->dev, n_ports); if (!host) goto failed;
for (p = 0; p < n_ports; p++) {
ap = host->ports[p];
/** * pcmcia_remove_one - unplug an pcmcia interface * @pdev: pcmcia device * * A PCMCIA ATA device has been unplugged. Perform the needed * cleanup. Also called on module unload for any active devices.
*/
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.