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