1 /****************************************************************************
2 * drivers/bch/bchlib_read.c
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership. The
7 * ASF licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the
9 * License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * under the License.
18 *
19 ****************************************************************************/
20
21 /****************************************************************************
22 * Included Files
23 ****************************************************************************/
24 #include <sys/types.h>
25 #include <stdint.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include "bch.h"
30 #include <stdlib.h>
31
32 /****************************************************************************
33 * Private Types
34 ****************************************************************************/
35
36 /****************************************************************************
37 * Private Function Prototypes
38 ****************************************************************************/
39
40 /****************************************************************************
41 * Private Data
42 ****************************************************************************/
43
44 /****************************************************************************
45 * Private Functions
46 ****************************************************************************/
47
48 /****************************************************************************
49 * Public Functions
50 ****************************************************************************/
51
52 /****************************************************************************
53 * Name: bchlib_read
54 *
55 * Description:
56 * Read from the block device set-up by bchlib_setup as if it were a character
57 * device.
58 *
59 ****************************************************************************/
60
bchlib_read(void * handle,char * buffer,loff_t offset,size_t len)61 ssize_t bchlib_read(void *handle, char *buffer, loff_t offset, size_t len)
62 {
63 struct bchlib_s *bch = (struct bchlib_s *)handle;
64 size_t nsectors;
65 unsigned long long sector;
66 uint16_t sectoffset;
67 size_t nbytes;
68 size_t bytesread;
69 int ret;
70
71 /* Get rid of this special case right away */
72
73 if (len < 1)
74 {
75 return 0;
76 }
77
78 /* Convert the file position into a sector number an offset. */
79
80 sector = offset / bch->sectsize;
81 sectoffset = offset - sector * bch->sectsize;
82
83 if (sector >= bch->nsectors)
84 {
85 /* Return end-of-file */
86
87 return 0;
88 }
89
90 /* Read the initial partial sector */
91
92 bytesread = 0;
93 if (sectoffset > 0)
94 {
95 /* Read the sector into the sector buffer */
96
97 ret = bchlib_readsector(bch, sector + bch->sectstart);
98 if (ret < 0)
99 {
100 return bytesread;
101 }
102
103 /* Copy the tail end of the sector to the user buffer */
104
105 if (sectoffset + len > bch->sectsize)
106 {
107 nbytes = bch->sectsize - sectoffset;
108 }
109 else
110 {
111 nbytes = len;
112 }
113
114 ret = LOS_CopyFromKernel(buffer, len, &bch->buffer[sectoffset], nbytes);
115 if (ret != EOK)
116 {
117 PRINTK("ERROR: bchlib_read failed: %d\n", ret);
118 return bytesread;
119 }
120
121 /* Adjust pointers and counts */
122
123 ++sector;
124
125 if (sector >= bch->nsectors)
126 {
127 return nbytes;
128 }
129
130 bytesread = nbytes;
131 buffer += nbytes;
132 len -= nbytes;
133 }
134
135 /* Then read all of the full sectors following the partial sector directly
136 * into the user buffer.
137 */
138
139 if (len >= bch->sectsize)
140 {
141 nsectors = len / bch->sectsize;
142 if (sector + nsectors > bch->nsectors)
143 {
144 nsectors = bch->nsectors - sector;
145 }
146 /* No need for reading large contiguous data, useRead(param 4) is set TRUE */
147 ret = los_disk_read(bch->disk->disk_id, (void *)buffer, sector + bch->sectstart, nsectors, TRUE);
148
149 if (ret < 0)
150 {
151 PRINTK("ERROR: Read failed: %d\n", ret);
152 return bytesread;
153 }
154
155 /* Adjust pointers and counts */
156
157 sector += nsectors;
158 nbytes = nsectors * bch->sectsize;
159 bytesread += nbytes;
160
161 if (sector >= bch->nsectors)
162 {
163 return bytesread;
164 }
165
166 buffer += nbytes;
167 len -= nbytes;
168 }
169
170 /* Then read any partial final sector */
171
172 if (len > 0)
173 {
174 /* Read the sector into the sector buffer */
175
176 ret = bchlib_readsector(bch, sector + bch->sectstart);
177 if (ret < 0)
178 {
179 return bytesread;
180 }
181
182 /* Copy the head end of the sector to the user buffer */
183
184 ret = LOS_CopyFromKernel(buffer, len, bch->buffer, len);
185 if (ret != EOK)
186 {
187 PRINTK("ERROR: bchlib_read failed: %d\n", ret);
188 return bytesread;
189 }
190
191 /* Adjust counts */
192
193 bytesread += len;
194 }
195
196 return bytesread;
197 }
198