From: Tejun Heo <htejun@gmail.com>
To: jgarzik@pobox.com, alan@lxorguk.ukuu.org.uk, mlord@pobox.com,
albertcc@tw.ibm.com, uchang@tw.ibm.com, forrest.zhao@intel.com,
brking@us.ibm.com, linux-ide@vger.kernel.org
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 6/20] libata: implement legacy ATA init helpers
Date: Sat, 19 Aug 2006 17:59:31 +0900 [thread overview]
Message-ID: <1155977971677-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <11559778241753-git-send-email-htejun@gmail.com>
Implement the following legacy ATA init helpers.
* ata_legacy_acquire_resources() : acquire legacy ATA resources
* ata_legacy_release_resources() : release legacy ATA resources
* ata_legacy_init_ports() : init legacy port addresses
* ata_legacy_request_irqs() : request legacy ATA IRQs
* ata_legacy_free_irqs() : free legacy ATA IRQs
These helpers can be used independently or called implictly from other
bus helpers which has support for legacy ATA device for compatibility
(e.g. PCI).
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/ata/Kconfig | 5 +
drivers/ata/Makefile | 3 +
drivers/ata/libata-legacy.c | 241 +++++++++++++++++++++++++++++++++++++++++++
drivers/ata/libata.h | 11 ++
include/linux/libata.h | 15 ++-
5 files changed, 273 insertions(+), 2 deletions(-)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 2109d75..1a98559 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -15,6 +15,11 @@ config ATA
that "speaks" the ATA protocol, also called ATA controller),
because you will be asked for it.
+config ATA_LEGACY
+ bool
+ depends on ATA
+ default n
+
config SATA_AHCI
tristate "AHCI SATA support"
depends on ATA && PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index c17ae9c..61d3e76 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -19,3 +19,6 @@ obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o
+ifeq ($(CONFIG_ATA_LEGACY),y)
+libata-objs += libata-legacy.o
+endif
diff --git a/drivers/ata/libata-legacy.c b/drivers/ata/libata-legacy.c
new file mode 100644
index 0000000..00b70b0
--- /dev/null
+++ b/drivers/ata/libata-legacy.c
@@ -0,0 +1,241 @@
+/*
+ * libata-legacy.c - helper library for legacy ATA
+ *
+ * Maintained by: Jeff Garzik <jgarzik@pobox.com>
+ * Please ALWAYS copy linux-ide@vger.kernel.org
+ * on emails.
+ *
+ * Copyright 2006 Tejun Heo <htejun@gmail.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * Hardware documentation available from http://www.t13.org/ and
+ * http://www.sata-io.org/
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/libata.h>
+
+#include "libata.h"
+
+static unsigned long ata_legacy_addr(int port, int sel)
+{
+ if (port == 0) {
+ if (sel == 0)
+ return ATA_PRIMARY_CMD;
+ else
+ return ATA_PRIMARY_CTL;
+ } else {
+ if (sel == 0)
+ return ATA_SECONDARY_CMD;
+ else
+ return ATA_SECONDARY_CTL;
+ }
+}
+
+static int ata_legacy_acquire_port(struct ata_port *ap)
+{
+ struct ata_host *host = ap->host;
+ unsigned long cmd_addr = ata_legacy_addr(ap->port_no, 0);
+
+ if (request_region(cmd_addr, 8, "libata") != NULL)
+ host->legacy_flags |= ATA_LEGACY_RES_PRI << ap->port_no;
+ else {
+ struct resource *conflict, res;
+
+ res.start = cmd_addr;
+ res.end = cmd_addr + 8 - 1;
+ conflict = ____request_resource(&ioport_resource, &res);
+
+ if (strcmp(conflict->name, "libata")) {
+ printk(KERN_WARNING "ata: 0x%0lX IDE port busy\n",
+ cmd_addr);
+ host->flags |= ATA_HOST_DEV_BUSY;
+ return -EBUSY;
+ }
+ printk("ata: 0x%0lX IDE port preallocated\n", cmd_addr);
+ }
+
+ return 0;
+}
+
+/**
+ * ata_legacy_acquire_resources - acquire legacy ATA resources
+ * @host: target ATA host
+ * @p_reason: out arg for error message (can be NULL)
+ *
+ * Acquire legacy ATA resources for ports specified by
+ * ATA_PORT_PRIMARY/SECONDARY mask in host->legacy_flags. If the
+ * port is busy, this function makes the port dummy instead of
+ * failing. This is to allow legacy ports to be driven by other
+ * drivers.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_legacy_acquire_resources(struct ata_host *host, const char **p_reason)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (!(host->legacy_flags & (ATA_PORT_PRIMARY << i)))
+ continue;
+ BUG_ON(i >= host->n_ports);
+
+ if (ata_legacy_acquire_port(host->ports[i]))
+ host->ports[i]->ops = &ata_dummy_port_ops;
+ }
+
+ return 0;
+}
+
+/**
+ * ata_legacy_release_resources - release legacy ATA resources
+ * @host: target ATA host
+ *
+ * Free all legacy ATA resources @host is holding.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ */
+void ata_legacy_release_resources(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (host->legacy_flags & (ATA_LEGACY_RES_PRI << i)) {
+ release_region(ata_legacy_addr(i, 0), 8);
+ host->legacy_flags &= ~(ATA_LEGACY_RES_PRI << i);
+ }
+ }
+}
+
+/**
+ * ata_legacy_init_ports - initialize legacy ATA port addresses
+ * @host: target ATA host
+ *
+ * Initialize legacy ATA port addresses for non-dummy legacy
+ * ports in @host.
+ *
+ * LOCKING:
+ * Inherited from calling layer.
+ */
+void ata_legacy_init_ports(struct ata_host *host)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (host->legacy_flags & (ATA_PORT_PRIMARY << i) &&
+ !ata_port_is_dummy(ap)) {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned long cmd_addr = ata_legacy_addr(i, 0);
+ unsigned long ctl_addr = ata_legacy_addr(i, 1);
+
+ ioaddr->cmd_addr = cmd_addr;
+ ioaddr->altstatus_addr = ctl_addr;
+ ioaddr->ctl_addr = ctl_addr;
+ ata_std_ports(ioaddr);
+ }
+ }
+}
+
+/**
+ * ata_legacy_request_irqs - request legacy ATA IRQs
+ * @host: target ATA host
+ * @handler: array of IRQ handlers
+ * @irq_flags: array of IRQ flags
+ * @dev_id: array of IRQ dev_ids
+ * @p_reason: out arg for error message (can be NULL)
+ *
+ * Request legacy IRQs for non-dummy legacy ports in @host. All
+ * IRQ parameters are passed as array to allow ports to have
+ * separate IRQ handlers.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_legacy_request_irqs(struct ata_host *host,
+ irqreturn_t (* const * handler)(int, void *, struct pt_regs *),
+ const unsigned int *irq_flags, void * const *dev_id,
+ const char **p_reason)
+{
+ const unsigned int legacy_irq[] = { 14, 15 };
+ const char *reason;
+ int i, rc;
+
+ for (i = 0; i < 2; i++) {
+ struct ata_port *ap = host->ports[i];
+ unsigned int irq = legacy_irq[i];
+
+ if (!(host->legacy_flags & (ATA_PORT_PRIMARY << i)) ||
+ ata_port_is_dummy(ap))
+ continue;
+
+ if (!handler[i]) {
+ reason = "NULL handler";
+ rc = -EINVAL;
+ goto err;
+ }
+
+ rc = ata_host_request_irq_marker(host, irq,
+ handler[i], irq_flags[i], dev_id[i],
+ ata_legacy_request_irqs, &reason);
+ if (rc)
+ goto err;
+
+ /* only for info printing */
+ if (i == 0)
+ host->irq = irq;
+ else
+ host->irq2 = irq;
+ }
+
+ return 0;
+
+ err:
+ ata_legacy_free_irqs(host);
+ if (p_reason)
+ *p_reason = reason;
+ return rc;
+}
+
+/**
+ * ata_legacy_free_irqs - free legacy ATA IRQs
+ * @host: target ATA host
+ *
+ * Free all legacy ATA IRQs of @host.
+ *
+ * LOCKING:
+ * Inherited from calling layer (may sleep).
+ */
+void ata_legacy_free_irqs(struct ata_host *host)
+{
+ ata_host_free_irqs_marker(host, ata_legacy_request_irqs);
+}
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 1d24254..0601c4a 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -117,6 +117,17 @@ extern void ata_schedule_scsi_eh(struct
extern void ata_scsi_dev_rescan(void *data);
extern int ata_bus_probe(struct ata_port *ap);
+/* libata-legacy.c */
+extern int ata_legacy_acquire_resources(struct ata_host *host,
+ const char **p_reason);
+extern void ata_legacy_release_resources(struct ata_host *host);
+extern void ata_legacy_init_ports(struct ata_host *host);
+extern int ata_legacy_request_irqs(struct ata_host *host,
+ irqreturn_t (* const * handler)(int, void *, struct pt_regs *),
+ const unsigned int *irq_flags, void * const *dev_id,
+ const char **p_reason);
+extern void ata_legacy_free_irqs(struct ata_host *host);
+
/* libata-eh.c */
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b050517..9535f54 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -200,8 +200,16 @@ enum {
ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */
/* host set flags */
- ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */
-
+ ATA_HOST_SIMPLEX = (1 << 0), /* host is simplex, one DMA channel per host only */
+ ATA_HOST_DEV_BUSY = (1 << 1), /* host device was busy on init */
+
+ /* legacy flags */
+ /* BIT 0 and 1 are reserved for ATA_PORT_PRIMARY and SECONDARY */
+ ATA_LEGACY_MASK = (1 << 0) | (1 << 1),
+
+ ATA_LEGACY_RES_PRI = (1 << 8),
+ ATA_LEGACY_RES_SEC = (1 << 9),
+
/* various lengths of time */
ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */
@@ -376,8 +384,11 @@ struct ata_host {
void *private_data;
const struct ata_port_operations *ops;
unsigned long flags;
+
int simplex_claimed; /* Keep seperate in case we
ever need to do this locked */
+ unsigned int legacy_flags;
+
struct list_head irq_list; /* list of acquired irqs */
struct ata_port *ports[0];
};
--
1.4.1.1
next prev parent reply other threads:[~2006-08-19 9:27 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-08-19 8:57 [PATCHSET] libata: implement new initialization model w/ iomap support, take 2 Tejun Heo
2006-08-19 8:59 ` [PATCH 2/20] libata: implement ata_host_start/stop() Tejun Heo
2006-08-19 8:59 ` [PATCH 1/20] libata: kill ata_host_stop() Tejun Heo
2006-08-19 14:51 ` Jeff Garzik
2006-08-19 15:29 ` Tejun Heo
2006-09-19 4:46 ` Jeff Garzik
2006-09-19 4:50 ` Tejun Heo
2006-08-19 8:59 ` [PATCH 7/20] libata: implement PCI ATA init helpers Tejun Heo
2006-09-19 5:29 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 4/20] libata: separate out ata_host_alloc() and ata_host_attach() Tejun Heo
2006-09-19 5:08 ` Jeff Garzik
2006-09-19 5:48 ` Tejun Heo
2006-08-19 8:59 ` [PATCH 3/20] libata: implement ata_host_detach() and ata_host_free() Tejun Heo
2006-09-19 4:59 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 5/20] libata: implement several LLD init helpers Tejun Heo
2006-08-22 22:11 ` Brian King
2006-08-27 9:52 ` Tejun Heo
2006-08-30 21:16 ` Brian King
2006-09-19 5:16 ` Jeff Garzik
2006-09-19 5:57 ` Tejun Heo
2006-08-19 8:59 ` Tejun Heo [this message]
2006-09-19 5:26 ` [PATCH 6/20] libata: implement legacy ATA " Jeff Garzik
2006-08-19 8:59 ` [PATCH 12/20] libata: kill old " Tejun Heo
2006-08-19 8:59 ` [PATCH 13/20] libata: kill unused ->host_stop() operation and related functions Tejun Heo
2006-09-19 5:42 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 10/20] libata: reimplement ata_pci_remove_one() using new PCI init helpers Tejun Heo
2006-08-19 8:59 ` [PATCH 11/20] libata: use remove_one() for deinit instead of ->host_stop() Tejun Heo
2006-09-19 5:42 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 8/20] libata: reimplement ata_pci_init_one() using new init helpers Tejun Heo
2006-09-19 5:32 ` Jeff Garzik
2006-09-19 6:04 ` Tejun Heo
2006-09-19 6:09 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 14/20] libata: use LLD name where possible Tejun Heo
2006-09-19 5:43 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 17/20] libata: make ata_pci_acquire_resources() handle iomap Tejun Heo
2006-09-19 5:47 ` Jeff Garzik
2006-09-19 6:27 ` Tejun Heo
2006-09-19 6:32 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 16/20] libata: make ata_host_alloc() take care of hpriv alloc/free Tejun Heo
2006-09-19 5:45 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 19/20] libata: kill unused ATA_FLAG_MMIO Tejun Heo
2006-08-19 8:59 ` [PATCH 15/20] libata: move ->irq_handler from port_ops to port_info Tejun Heo
2006-09-19 5:43 ` Jeff Garzik
2006-08-19 8:59 ` [PATCH 20/20] libata: move scattered PCI ATA functions into liata-pci.c Tejun Heo
2006-09-19 5:50 ` Jeff Garzik
2006-08-22 22:10 ` [PATCHSET] libata: implement new initialization model w/ iomap support, take 2 Brian King
2006-08-27 10:12 ` Tejun Heo
2006-08-30 20:58 ` Brian King
2006-09-01 13:45 ` Tejun Heo
2006-09-07 13:22 ` Brian King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1155977971677-git-send-email-htejun@gmail.com \
--to=htejun@gmail.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=albertcc@tw.ibm.com \
--cc=brking@us.ibm.com \
--cc=forrest.zhao@intel.com \
--cc=jgarzik@pobox.com \
--cc=linux-ide@vger.kernel.org \
--cc=mlord@pobox.com \
--cc=uchang@tw.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).