xref: /third_party/NuttX/drivers/bch/bchlib_read.c (revision beacf11b)
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
61ssize_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