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