1 /****************************************************************************
2 * drivers/bch/bchlib_setup.c
3 *
4 * Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved.
5 * Author: Gregory Nutt <gnutt@nuttx.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name NuttX nor the names of its contributors may be
18 * used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 ****************************************************************************/
35
36 /****************************************************************************
37 * Included Files
38 ****************************************************************************/
39 #include <sys/types.h>
40 #include <sys/mount.h>
41 #include <stdint.h>
42 #include <stdbool.h>
43 #include <stdlib.h>
44 #include <errno.h>
45 #include <assert.h>
46 #include <securec.h>
47 #include "bch.h"
48
49 /****************************************************************************
50 * Public Functions
51 ****************************************************************************/
52
53 /****************************************************************************
54 * Name: bchlib_setup
55 *
56 * Description:
57 * Setup so that the block driver referenced by 'blkdev' can be accessed
58 * similar to a character device.
59 *
60 ****************************************************************************/
61
bchlib_setup(const char * blkdev,bool readonly,void ** handle)62 int bchlib_setup(const char *blkdev, bool readonly, void **handle)
63 {
64 struct bchlib_s *bch;
65 struct geometry geo;
66 los_part *part;
67 int ret;
68
69 DEBUGASSERT(blkdev);
70
71 /* Allocate the BCH state structure */
72
73 bch = (struct bchlib_s *)zalloc(sizeof(struct bchlib_s));
74 if (!bch)
75 {
76 PRINTK("ERROR: Failed to allocate BCH structure\n");
77 return -ENOMEM;
78 }
79
80 /* Open the block driver */
81
82 ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->vnode);
83 if (ret < 0)
84 {
85 PRINTK("ERROR: Failed to open driver %s: %d\n", blkdev, -ret);
86 goto errout_with_bch;
87 }
88
89 struct drv_data *drv = (struct drv_data *)bch->vnode->data;
90 struct block_operations *bops = (struct block_operations *)drv->ops;
91
92 DEBUGASSERT(bch->vnode && bops && bops->geometry);
93
94 ret = bops->geometry(bch->vnode, &geo);
95 if (ret < 0)
96 {
97 PRINTK("ERROR: geometry failed: %d\n", -ret);
98 goto errout_with_bch;
99 }
100
101 if (!geo.geo_available)
102 {
103 PRINTK("ERROR: geometry failed: %d\n", -ret);
104 ret = -ENODEV;
105 goto errout_with_bch;
106 }
107
108 if (!readonly && (!bops->write || !geo.geo_writeenabled))
109 {
110 PRINTK("ERROR: write access not supported\n");
111 ret = -EACCES;
112 goto errout_with_bch;
113 }
114
115 /* Save the geometry info and complete initialization of the structure */
116
117 (void)sem_init(&bch->sem, 0, 1);
118 bch->nsectors = geo.geo_nsectors;
119 bch->sectsize = geo.geo_sectorsize;
120 bch->sector = (size_t)-1;
121 bch->readonly = readonly;
122 bch->dirty = false;
123 bch->unlinked = false;
124
125 part = los_part_find(bch->vnode);
126 if (part != NULL)
127 {
128 bch->sectstart = part->sector_start;
129 bch->nsectors = part->sector_count;
130 bch->disk = get_disk(part->disk_id);
131 }
132 else
133 {
134 PRINTK("ERROR: los_part_find failed\n");
135 ret = -ENODEV;
136 goto errout_with_bch;
137 }
138
139 /* Allocate the sector I/O buffer */
140
141 bch->buffer = (uint8_t *)malloc(bch->sectsize);
142 if (!bch->buffer)
143 {
144 PRINTK("ERROR: Failed to allocate sector buffer\n");
145 ret = -ENOMEM;
146 goto errout_with_bch;
147 }
148
149 *handle = bch;
150 return OK;
151
152 errout_with_bch:
153 (void)sem_destroy(&bch->sem);
154 free(bch);
155 return ret;
156 }
157