All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Herrmann <morpheus.ibis@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 03/11] DM: add block controller core
Date: Thu, 20 Sep 2012 21:37:39 +0200	[thread overview]
Message-ID: <1348169867-2917-4-git-send-email-morpheus.ibis@gmail.com> (raw)
In-Reply-To: <1348169867-2917-1-git-send-email-morpheus.ibis@gmail.com>

This core provides unified access to different block controllers (SATA, SCSI).

Signed-off-by: Pavel Herrmann <morpheus.ibis@gmail.com>
---
 Makefile                   |   1 +
 drivers/blockctrl/Makefile |  42 ++++++
 drivers/blockctrl/core.c   | 349 +++++++++++++++++++++++++++++++++++++++++++++
 include/dm/blockctrl.h     |  75 ++++++++++
 4 files changed, 467 insertions(+)
 create mode 100644 drivers/blockctrl/Makefile
 create mode 100644 drivers/blockctrl/core.c
 create mode 100644 include/dm/blockctrl.h

diff --git a/Makefile b/Makefile
index e43fd9d..4420484 100644
--- a/Makefile
+++ b/Makefile
@@ -304,6 +304,7 @@ LIBS-y += test/libtest.o
 LIBS-$(CONFIG_DM) += common/dm/libdm.o
 LIBS-$(CONFIG_DM) += drivers/demo/libdemo.o
 LIBS-${CONFIG_DM_BLOCK} += drivers/blockdev/libblockdev.o
+LIBS-${CONFIG_DM_BLOCK} += drivers/blockctrl/libblockctrl.o
 
 ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
diff --git a/drivers/blockctrl/Makefile b/drivers/blockctrl/Makefile
new file mode 100644
index 0000000..21a9094
--- /dev/null
+++ b/drivers/blockctrl/Makefile
@@ -0,0 +1,42 @@
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 of
+# the License, 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; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libblockctrl.o
+
+COBJS-${CONFIG_DM_BLOCK} := core.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/blockctrl/core.c b/drivers/blockctrl/core.c
new file mode 100644
index 0000000..1f1f834
--- /dev/null
+++ b/drivers/blockctrl/core.c
@@ -0,0 +1,349 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <dm/blockctrl.h>
+#include <dm/manager.h>
+#include <malloc.h>
+
+struct blockctrl_core_entry {
+	struct list_head	list;
+	struct instance		*instance;
+	struct blockctrl_ops	*ops;
+};
+
+static struct blockctrl_core_entry *get_entry_by_instance(struct instance *dev)
+{
+	struct blockctrl_core_entry *entry;
+	struct core_instance *core = get_core_instance(CORE_BLOCKCTRL);
+
+	if (!core)
+		return NULL;
+
+	list_for_each_entry(entry, &core->succ, list) {
+		if (entry->instance == dev)
+			return entry;
+	}
+
+	return NULL;
+}
+
+/* Core API functions */
+static int get_count(struct core_instance *core)
+{
+	int count = 0;
+	struct blockctrl_core_entry *entry;
+
+	list_for_each_entry(entry, &core->succ, list) {
+		count++;
+	}
+
+	return count;
+}
+
+static struct instance *get_child(struct core_instance *core, int index)
+{
+	struct blockctrl_core_entry *entry = NULL;
+
+	list_for_each_entry(entry, &core->succ, list) {
+		if (!index)
+			return entry->instance;
+		index--;
+	}
+
+	return NULL;
+}
+
+static int bind(struct core_instance *core, struct instance *dev, void *ops,
+	void *data)
+{
+	struct blockctrl_core_entry *entry;
+
+	if (ops == NULL)
+		return -EINVAL;
+
+	entry = malloc(sizeof(*entry));
+	if (entry == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&entry->list);
+	entry->instance = dev;
+	entry->ops = ops;
+	list_add_tail(&entry->list, &core->succ);
+
+	return 0;
+}
+
+static int unbind(struct core_instance *core, struct instance *dev)
+{
+	struct blockctrl_core_entry *entry, *n;
+
+	list_for_each_entry_safe(entry, n, &core->succ, list) {
+		if (entry->instance == dev) {
+			list_del(&entry->list);
+			free(entry);
+		}
+	}
+
+	return 0;
+}
+
+static int replace(struct core_instance *core, struct instance *new,
+	struct instance *old)
+{
+	struct blockctrl_core_entry *entry = get_entry_by_instance(old);
+
+	if (!entry)
+		return -ENOENT;
+
+	entry->instance = new;
+
+	return 0;
+}
+
+static int init(struct core_instance *core)
+{
+	INIT_LIST_HEAD(&core->succ);
+	core->private_data = NULL;
+
+	return 0;
+}
+
+static int reloc(struct core_instance *core, struct core_instance *old)
+{
+	struct blockctrl_core_entry *entry, *new;
+
+	/* no private_data to copy, yet */
+
+	/* fixup links in old list and prepare new list head */
+	/* FIXME */
+	/* list_fix_reloc(&old->succ); */
+	INIT_LIST_HEAD(&core->succ);
+	core->private_data = NULL;
+
+	/* copy list entries to new memory */
+	list_for_each_entry(entry, &old->succ, list) {
+		new = malloc(sizeof(*new));
+		if (!new)
+			return -ENOMEM;
+
+		INIT_LIST_HEAD(&new->list);
+		new->instance = entry->instance;
+		new->ops = entry->ops;
+		list_add_tail(&new->list, &core->succ);
+		/*no free at this point, old memory should not be freed*/
+	}
+
+	return 0;
+}
+
+static int destroy(struct core_instance *core)
+{
+	struct blockctrl_core_entry *entry, *n;
+
+	/* destroy private data */
+	free(core->private_data);
+	core->private_data = NULL;
+
+	/* destroy successor list */
+	list_for_each_entry_safe(entry, n, &core->succ, list) {
+		list_del(&entry->list);
+		free(entry);
+	}
+
+	return 0;
+}
+
+U_BOOT_CORE(CORE_BLOCKCTRL,
+	init,
+	reloc,
+	destroy,
+	get_count,
+	get_child,
+	bind,
+	unbind,
+	replace);
+
+lbaint_t blockctrl_read(struct instance *i, int port, lbaint_t start,
+	lbaint_t length, void *buffer)
+{
+	struct blockctrl_core_entry *entry;
+	struct blockctrl_ops *driver_ops;
+	int error;
+
+	entry = get_entry_by_instance(i);
+	if (!entry)
+		return -ENOENT;
+
+	error = driver_activate(i);
+	if (error)
+		return error;
+
+	driver_ops = entry->ops;
+	if (!driver_ops || !driver_ops->read)
+		return -EINVAL;
+
+	return driver_ops->read(i, port, start, length, buffer);
+}
+
+lbaint_t blockctrl_write(struct instance *i, int port, lbaint_t start,
+	lbaint_t length, void *buffer)
+{
+	struct blockctrl_core_entry *entry;
+	struct blockctrl_ops *driver_ops;
+	int error;
+
+	entry = get_entry_by_instance(i);
+	if (!entry)
+		return -ENOENT;
+
+	error = driver_activate(i);
+	if (error)
+		return error;
+
+	driver_ops = entry->ops;
+	if (!driver_ops || !driver_ops->write)
+		return -EINVAL;
+
+	return driver_ops->write(i, port, start, length, buffer);
+}
+
+int blockctrl_scan(struct instance *i, int port)
+{
+	struct blockctrl_core_entry *entry;
+	struct blockctrl_ops *driver_ops;
+	int error;
+
+	entry = get_entry_by_instance(i);
+	if (!entry)
+		return -ENOENT;
+
+	error = driver_activate(i);
+	if (error)
+		return error;
+
+	driver_ops = entry->ops;
+	if (!driver_ops || !driver_ops->scan)
+		return -EINVAL;
+
+	return driver_ops->scan(i, port);
+}
+
+int blockctrl_get_port_count(struct instance *i)
+{
+	struct blockctrl_core_entry *entry;
+	struct blockctrl_ops *driver_ops;
+	int error;
+
+	entry = get_entry_by_instance(i);
+	if (!entry)
+		return -ENOENT;
+
+	error = driver_activate(i);
+	if (error)
+		return error;
+
+	driver_ops = entry->ops;
+	if (!driver_ops || !driver_ops->get_port_count)
+		return -EINVAL;
+
+	return driver_ops->get_port_count(i);
+}
+
+int blockctrl_get_port_option(struct instance *i, int port,
+	enum blockctrl_port_option_code op, struct option *result)
+{
+	struct blockctrl_core_entry *entry;
+	struct blockctrl_ops *driver_ops;
+	int error;
+
+	entry = get_entry_by_instance(i);
+	if (!entry)
+		return -ENOENT;
+
+	error = driver_activate(i);
+	if (error)
+		return error;
+
+	driver_ops = entry->ops;
+	if (!driver_ops || !driver_ops->get_port_option)
+		return -EINVAL;
+
+	return driver_ops->get_port_option(i, port, op, result);
+}
+
+struct instance *blockctrl_rescan_port(struct instance *i, int port)
+{
+	/* we assume that all children of blockctrl are blockdev_ata */
+	struct instance *child = NULL;
+	struct blockctrl_core_entry *entry;
+	struct driver_instance *di;
+	struct blockdev_ata_platform_data *pdata;
+	struct driver_info *info;
+	int nfound;
+
+	entry = get_entry_by_instance(i);
+	if (!entry)
+		return NULL;
+
+	list_for_each_entry(di, &i->succ, list) {
+		if (di->i.info)
+			pdata = di->i.info->platform_data;
+		else
+			pdata = NULL;
+
+		if (pdata && (pdata->port_number == port))
+			child = &di->i;
+	}
+
+	/*
+	 * If we have an active link, we check whether this is a new device,
+	 * in which case we simply bind a new instance, or an old device,
+	 * in which case we reactivate the device to force partition rescan.
+	 * If we dont have an active link, we remove any device attached.
+	 */
+	nfound = blockctrl_scan(i, port);
+	if (!nfound) {
+		if (child) {
+			/* rescan the disk size and partitions, just in case */
+			driver_remove(child);
+			scan_partitions(child);
+		} else {
+			pdata = malloc(sizeof(*pdata));
+			pdata->port_number = port;
+			info = malloc(sizeof(*info));
+			info->platform_data = pdata;
+			info->name = "blockdev_ata";
+			child = driver_bind(i, info);
+			scan_partitions(child);
+			return child;
+		}
+	} else {
+		/* link is not active, remove and unbind the child device */
+		if (child) {
+			driver_remove(child);
+			driver_unbind(child);
+		}
+	}
+
+	return NULL;
+}
diff --git a/include/dm/blockctrl.h b/include/dm/blockctrl.h
new file mode 100644
index 0000000..4b6d582
--- /dev/null
+++ b/include/dm/blockctrl.h
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 of
+ * the License, 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _DM_BLOCKCTRL_H_
+#define _DM_BLOCKCTRL_H 1
+
+#include <dm/structures.h>
+#include <dm/blockdev.h>
+
+enum blockctrl_port_option_code {
+	BLKP_OPT_IFTYPE = 0,
+	BLKP_OPT_IFSPEED,
+	BLKP_OPT_BLOCKSIZE,
+	BLKP_OPT_BLOCKCOUNT,
+	BLKP_OPT_REMOVABLE,
+	BLKP_OPT_LBA48,
+	BLKP_OPT_VENDOR,
+	BLKP_OPT_PRODUCT,
+	BLKP_OPT_REVISION,
+};
+
+enum blockctrl_iftype {
+	BLKP_IFTYPE_SATA,
+	BLKP_IFTYPE_PATA,
+	BLKP_IFTYPE_SCSI,
+	BLKP_IFTYPE_VIRTUAL,
+};
+
+
+struct blockctrl_ops {
+	lbaint_t	(*read)(struct instance *i, int port, lbaint_t start,
+				lbaint_t length, void *buffer);
+	lbaint_t	(*write)(struct instance *i, int port, lbaint_t start,
+				lbaint_t length, void *buffer);
+	int		(*scan)(struct instance *i, int port);
+	int		(*get_port_count)(struct instance *i);
+	int		(*get_port_option)(struct instance *i, int port,
+				enum blockctrl_port_option_code op,
+				struct option *result);
+};
+
+/* driver wrappers */
+lbaint_t blockctrl_read(struct instance *i, int port, lbaint_t start,
+	lbaint_t length, void *buffer);
+lbaint_t blockctrl_write(struct instance *i, int port, lbaint_t start,
+	lbaint_t length, void *buffer);
+int blockctrl_scan(struct instance *i, int port);
+int blockctrl_get_port_count(struct instance *i);
+int blockctrl_get_port_option(struct instance *i, int port,
+	enum blockctrl_port_option_code op, struct option *result);
+
+/* command helpers */
+struct instance *blockctrl_rescan_port(struct instance *i, int port);
+
+#endif
-- 
1.7.12

  parent reply	other threads:[~2012-09-20 19:37 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-20 19:37 [U-Boot] [PATCH 00/11] Add DM blockdev subsystem Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 01/11] DM: add block device core Pavel Herrmann
2012-09-20 19:58   ` Marek Vasut
2012-09-21  7:11     ` Pavel Herrmann
2012-09-21 12:39       ` Marek Vasut
2012-09-21 13:27         ` Pavel Herrmann
2012-09-21 13:53           ` Marek Vasut
2012-09-21 14:57             ` Pavel Herrmann
2012-09-21 15:34               ` Marek Vasut
2012-09-21 15:48                 ` Pavel Herrmann
2012-09-21 15:55                   ` Marek Vasut
2012-09-21 17:19                     ` Pavel Herrmann
2012-09-21 18:00                       ` Marek Vasut
2012-09-21 18:53                         ` Pavel Herrmann
2012-09-21 19:17                           ` Marek Vasut
2012-09-21 19:29                             ` Pavel Herrmann
2012-09-21 21:11                               ` Marek Vasut
2012-09-21 23:43                                 ` Pavel Herrmann
2012-09-22  0:09                                   ` Marek Vasut
2012-09-22  9:39                                     ` Pavel Herrmann
2012-09-22 13:33                                       ` Marek Vasut
2012-09-22 13:59                                         ` Pavel Herrmann
2012-09-24 12:23                                           ` Pavel Herrmann
2012-09-20 20:49   ` [U-Boot] [U-Boot-DM] " Vikram Narayanan
2012-09-21  7:09     ` Pavel Herrmann
2012-09-21 12:39       ` Marek Vasut
2012-09-20 19:37 ` [U-Boot] [PATCH 02/11] DM: add support for scanning DOS partitions to blockdev core Pavel Herrmann
2012-09-20 20:03   ` Marek Vasut
2012-09-21  7:22     ` Pavel Herrmann
2012-09-21 12:47       ` Marek Vasut
2012-09-21 13:18         ` Pavel Herrmann
2012-09-21 13:54           ` Marek Vasut
2012-09-20 19:37 ` Pavel Herrmann [this message]
2012-09-20 20:05   ` [U-Boot] [PATCH 03/11] DM: add block controller core Marek Vasut
2012-09-21  7:21     ` Pavel Herrmann
2012-09-21 12:51       ` Marek Vasut
2012-09-21 13:14         ` Pavel Herrmann
2012-09-21 13:56           ` Marek Vasut
2012-09-21 15:04             ` Pavel Herrmann
2012-09-21 13:33         ` Pavel Herrmann
2012-09-21 13:58           ` Marek Vasut
2012-09-21 15:09             ` Pavel Herrmann
2012-09-21 15:39               ` Marek Vasut
2012-09-21 15:46                 ` Pavel Herrmann
2012-09-21 16:08                   ` Marek Vasut
2012-09-21 17:22                     ` Pavel Herrmann
2012-09-21 18:01                       ` Marek Vasut
2012-09-21 19:15                         ` Pavel Herrmann
2012-09-21 19:22                           ` Marek Vasut
2012-09-20 19:37 ` [U-Boot] [PATCH 04/11] DM: add sata_legacy driver for blockctrl Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 05/11] DM: add ata and partition blockdev drivers Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 06/11] DM: add cmd_block command Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 07/11] DM: use new blockdev API in FAT Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 08/11] DM: use new blockdev API in ext2 Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 09/11] DM: use new blockdev API in reiserfs Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 10/11] DM: use new blockdev API in ZFS Pavel Herrmann
2012-09-20 19:37 ` [U-Boot] [PATCH 11/11] DM: switch sandbox to DM blockdev Pavel Herrmann

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=1348169867-2917-4-git-send-email-morpheus.ibis@gmail.com \
    --to=morpheus.ibis@gmail.com \
    --cc=u-boot@lists.denx.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.