+struct uio_portio {
+ struct kobject kobj;
+ struct uio_port *port;
+};
+#define to_portio(portio) container_of(portio, struct uio_portio, kobj)
+
+static ssize_t portio_name_show(struct uio_port *port, char *buf)
+{
+ if (unlikely(!port->name))
+ port->name = "";
+
+ return sprintf(buf, "%s\n", port->name);
+}
+
+static ssize_t portio_start_show(struct uio_port *port, char *buf)
+{
+ return sprintf(buf, "0x%lx\n", port->start);
+}
+
+static ssize_t portio_size_show(struct uio_port *port, char *buf)
+{
+ return sprintf(buf, "0x%lx\n", port->size);
+}
+
+static ssize_t portio_porttype_show(struct uio_port *port, char *buf)
+{
+ const char *porttypes[] = {"none", "x86", "gpio", "other"};
+
+ if ((port->porttype < 0) || (port->porttype > UIO_PORT_OTHER))
+ return -EINVAL;
+
+ return sprintf(buf, "port_%s\n", porttypes[port->porttype]);
+}
+
+struct portio_sysfs_entry {
+ struct attribute attr;
+ ssize_t (*show)(struct uio_port *, char *);
+ ssize_t (*store)(struct uio_port *, const char *, size_t);
+};
+
+static struct portio_sysfs_entry portio_name_attribute =
+ __ATTR(name, S_IRUGO, portio_name_show, NULL);
+static struct portio_sysfs_entry portio_start_attribute =
+ __ATTR(start, S_IRUGO, portio_start_show, NULL);
+static struct portio_sysfs_entry portio_size_attribute =
+ __ATTR(size, S_IRUGO, portio_size_show, NULL);
+static struct portio_sysfs_entry portio_porttype_attribute =
+ __ATTR(porttype, S_IRUGO, portio_porttype_show, NULL);
+
+static struct attribute *portio_attrs[] = {
+ &portio_name_attribute.attr,
+ &portio_start_attribute.attr,
+ &portio_size_attribute.attr,
+ &portio_porttype_attribute.attr,
+ NULL,
+};
+
+static void portio_release(struct kobject *kobj)
+{
+ struct uio_portio *portio = to_portio(kobj);
+ kfree(portio);
+}
+
+static ssize_t portio_type_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct uio_portio *portio = to_portio(kobj);
+ struct uio_port *port = portio->port;
+ struct portio_sysfs_entry *entry;
+
+ entry = container_of(attr, struct portio_sysfs_entry, attr);
+
+ if (!entry->show)
+ return -EIO;
+
+ return entry->show(port, buf);
+}
+
+static struct sysfs_ops portio_sysfs_ops = {
+ .show = portio_type_show,
+};
+
+static struct kobj_type portio_attr_type = {
+ .release = portio_release,
+ .sysfs_ops = &portio_sysfs_ops,
+ .default_attrs = portio_attrs,
+};
+