uboot/drivers/block/blk_legacy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <blk.h>
   9#include <part.h>
  10#include <linux/err.h>
  11
  12struct blk_driver *blk_driver_lookup_type(int if_type)
  13{
  14        struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
  15        const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
  16        struct blk_driver *entry;
  17
  18        for (entry = drv; entry != drv + n_ents; entry++) {
  19                if (if_type == entry->if_type)
  20                        return entry;
  21        }
  22
  23        /* Not found */
  24        return NULL;
  25}
  26
  27static struct blk_driver *blk_driver_lookup_typename(const char *if_typename)
  28{
  29        struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver);
  30        const int n_ents = ll_entry_count(struct blk_driver, blk_driver);
  31        struct blk_driver *entry;
  32
  33        for (entry = drv; entry != drv + n_ents; entry++) {
  34                if (!strcmp(if_typename, entry->if_typename))
  35                        return entry;
  36        }
  37
  38        /* Not found */
  39        return NULL;
  40}
  41
  42const char *blk_get_if_type_name(enum if_type if_type)
  43{
  44        struct blk_driver *drv = blk_driver_lookup_type(if_type);
  45
  46        return drv ? drv->if_typename : NULL;
  47}
  48
  49/**
  50 * get_desc() - Get the block device descriptor for the given device number
  51 *
  52 * @drv:        Legacy block driver
  53 * @devnum:     Device number (0 = first)
  54 * @descp:      Returns block device descriptor on success
  55 * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the
  56 * driver does not provide a way to find a device, or other -ve on other
  57 * error.
  58 */
  59static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp)
  60{
  61        if (drv->desc) {
  62                if (devnum < 0 || devnum >= drv->max_devs)
  63                        return -ENODEV;
  64                *descp = &drv->desc[devnum];
  65                return 0;
  66        }
  67        if (!drv->get_dev)
  68                return -ENOSYS;
  69
  70        return drv->get_dev(devnum, descp);
  71}
  72
  73#ifdef CONFIG_HAVE_BLOCK_DEVICE
  74int blk_list_part(enum if_type if_type)
  75{
  76        struct blk_driver *drv;
  77        struct blk_desc *desc;
  78        int devnum, ok;
  79        bool first = true;
  80
  81        drv = blk_driver_lookup_type(if_type);
  82        if (!drv)
  83                return -ENOSYS;
  84        for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) {
  85                if (get_desc(drv, devnum, &desc))
  86                        continue;
  87                if (desc->part_type != PART_TYPE_UNKNOWN) {
  88                        ++ok;
  89                        if (!first)
  90                                putc('\n');
  91                        part_print(desc);
  92                        first = false;
  93                }
  94        }
  95        if (!ok)
  96                return -ENODEV;
  97
  98        return 0;
  99}
 100
 101int blk_print_part_devnum(enum if_type if_type, int devnum)
 102{
 103        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 104        struct blk_desc *desc;
 105        int ret;
 106
 107        if (!drv)
 108                return -ENOSYS;
 109        ret = get_desc(drv, devnum, &desc);
 110        if (ret)
 111                return ret;
 112        if (desc->type == DEV_TYPE_UNKNOWN)
 113                return -ENOENT;
 114        part_print(desc);
 115
 116        return 0;
 117}
 118
 119void blk_list_devices(enum if_type if_type)
 120{
 121        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 122        struct blk_desc *desc;
 123        int i;
 124
 125        if (!drv)
 126                return;
 127        for (i = 0; i < drv->max_devs; ++i) {
 128                if (get_desc(drv, i, &desc))
 129                        continue;
 130                if (desc->type == DEV_TYPE_UNKNOWN)
 131                        continue;  /* list only known devices */
 132                printf("Device %d: ", i);
 133                dev_print(desc);
 134        }
 135}
 136
 137int blk_print_device_num(enum if_type if_type, int devnum)
 138{
 139        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 140        struct blk_desc *desc;
 141        int ret;
 142
 143        if (!drv)
 144                return -ENOSYS;
 145        ret = get_desc(drv, devnum, &desc);
 146        if (ret)
 147                return ret;
 148        printf("\n%s device %d: ", drv->if_typename, devnum);
 149        dev_print(desc);
 150
 151        return 0;
 152}
 153
 154int blk_show_device(enum if_type if_type, int devnum)
 155{
 156        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 157        struct blk_desc *desc;
 158        int ret;
 159
 160        if (!drv)
 161                return -ENOSYS;
 162        printf("\nDevice %d: ", devnum);
 163        if (devnum >= drv->max_devs) {
 164                puts("unknown device\n");
 165                return -ENODEV;
 166        }
 167        ret = get_desc(drv, devnum, &desc);
 168        if (ret)
 169                return ret;
 170        dev_print(desc);
 171
 172        if (desc->type == DEV_TYPE_UNKNOWN)
 173                return -ENOENT;
 174
 175        return 0;
 176}
 177#endif /* CONFIG_HAVE_BLOCK_DEVICE */
 178
 179struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
 180{
 181        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 182        struct blk_desc *desc;
 183
 184        if (!drv)
 185                return NULL;
 186
 187        if (get_desc(drv, devnum, &desc))
 188                return NULL;
 189
 190        return desc;
 191}
 192
 193int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
 194{
 195        struct blk_driver *drv = blk_driver_lookup_type(desc->if_type);
 196
 197        if (!drv)
 198                return -ENOSYS;
 199        if (drv->select_hwpart)
 200                return drv->select_hwpart(desc, hwpart);
 201
 202        return 0;
 203}
 204
 205struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
 206{
 207        struct blk_driver *drv = blk_driver_lookup_typename(if_typename);
 208        struct blk_desc *desc;
 209
 210        if (!drv)
 211                return NULL;
 212
 213        if (get_desc(drv, devnum, &desc))
 214                return NULL;
 215
 216        return desc;
 217}
 218
 219ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
 220                      lbaint_t blkcnt, void *buffer)
 221{
 222        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 223        struct blk_desc *desc;
 224        ulong n;
 225        int ret;
 226
 227        if (!drv)
 228                return -ENOSYS;
 229        ret = get_desc(drv, devnum, &desc);
 230        if (ret)
 231                return ret;
 232        n = desc->block_read(desc, start, blkcnt, buffer);
 233        if (IS_ERR_VALUE(n))
 234                return n;
 235
 236        return n;
 237}
 238
 239ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
 240                       lbaint_t blkcnt, const void *buffer)
 241{
 242        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 243        struct blk_desc *desc;
 244        int ret;
 245
 246        if (!drv)
 247                return -ENOSYS;
 248        ret = get_desc(drv, devnum, &desc);
 249        if (ret)
 250                return ret;
 251        return desc->block_write(desc, start, blkcnt, buffer);
 252}
 253
 254int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
 255{
 256        struct blk_driver *drv = blk_driver_lookup_type(if_type);
 257        struct blk_desc *desc;
 258        int ret;
 259
 260        if (!drv)
 261                return -ENOSYS;
 262        ret = get_desc(drv, devnum, &desc);
 263        if (ret)
 264                return ret;
 265        return drv->select_hwpart(desc, hwpart);
 266}
 267