1beacf11bSopenharmony_ci/**************************************************************************** 2beacf11bSopenharmony_ci * drivers/bch/bchlib_write.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 <stdbool.h> 27beacf11bSopenharmony_ci#include <string.h> 28beacf11bSopenharmony_ci#include <errno.h> 29beacf11bSopenharmony_ci#include <assert.h> 30beacf11bSopenharmony_ci#include "bch.h" 31beacf11bSopenharmony_ci 32beacf11bSopenharmony_ci/**************************************************************************** 33beacf11bSopenharmony_ci * Public Functions 34beacf11bSopenharmony_ci ****************************************************************************/ 35beacf11bSopenharmony_ci 36beacf11bSopenharmony_ci/**************************************************************************** 37beacf11bSopenharmony_ci * Name: bchlib_write 38beacf11bSopenharmony_ci * 39beacf11bSopenharmony_ci * Description: 40beacf11bSopenharmony_ci * Write to the block device set-up by bchlib_setup as if it were a character 41beacf11bSopenharmony_ci * device. 42beacf11bSopenharmony_ci * 43beacf11bSopenharmony_ci ****************************************************************************/ 44beacf11bSopenharmony_ci 45beacf11bSopenharmony_cissize_t bchlib_write(void *handle, const char *buffer, loff_t offset, size_t len) 46beacf11bSopenharmony_ci{ 47beacf11bSopenharmony_ci struct bchlib_s *bch = (struct bchlib_s *)handle; 48beacf11bSopenharmony_ci size_t nsectors; 49beacf11bSopenharmony_ci unsigned long long sector; 50beacf11bSopenharmony_ci uint16_t sectoffset; 51beacf11bSopenharmony_ci size_t nbytes; 52beacf11bSopenharmony_ci size_t byteswritten; 53beacf11bSopenharmony_ci int ret; 54beacf11bSopenharmony_ci 55beacf11bSopenharmony_ci /* Get rid of this special case right away */ 56beacf11bSopenharmony_ci 57beacf11bSopenharmony_ci if (len < 1) 58beacf11bSopenharmony_ci { 59beacf11bSopenharmony_ci return 0; 60beacf11bSopenharmony_ci } 61beacf11bSopenharmony_ci 62beacf11bSopenharmony_ci /* Convert the file position into a sector number and offset. */ 63beacf11bSopenharmony_ci 64beacf11bSopenharmony_ci sector = offset / bch->sectsize; 65beacf11bSopenharmony_ci sectoffset = offset - sector * bch->sectsize; 66beacf11bSopenharmony_ci 67beacf11bSopenharmony_ci if (sector >= bch->nsectors) 68beacf11bSopenharmony_ci { 69beacf11bSopenharmony_ci return 0; 70beacf11bSopenharmony_ci } 71beacf11bSopenharmony_ci 72beacf11bSopenharmony_ci /* Write the initial partial sector */ 73beacf11bSopenharmony_ci 74beacf11bSopenharmony_ci byteswritten = 0; 75beacf11bSopenharmony_ci if (sectoffset > 0) 76beacf11bSopenharmony_ci { 77beacf11bSopenharmony_ci /* Read the full sector into the sector buffer */ 78beacf11bSopenharmony_ci 79beacf11bSopenharmony_ci ret = bchlib_readsector(bch, sector + bch->sectstart); 80beacf11bSopenharmony_ci if (ret < 0) 81beacf11bSopenharmony_ci { 82beacf11bSopenharmony_ci return byteswritten; 83beacf11bSopenharmony_ci } 84beacf11bSopenharmony_ci 85beacf11bSopenharmony_ci /* Copy the tail end of the sector from the user buffer */ 86beacf11bSopenharmony_ci 87beacf11bSopenharmony_ci if (sectoffset + len > bch->sectsize) 88beacf11bSopenharmony_ci { 89beacf11bSopenharmony_ci nbytes = bch->sectsize - sectoffset; 90beacf11bSopenharmony_ci } 91beacf11bSopenharmony_ci else 92beacf11bSopenharmony_ci { 93beacf11bSopenharmony_ci nbytes = len; 94beacf11bSopenharmony_ci } 95beacf11bSopenharmony_ci 96beacf11bSopenharmony_ci ret = LOS_CopyToKernel(&bch->buffer[sectoffset], nbytes, buffer, nbytes); 97beacf11bSopenharmony_ci if (ret != EOK) 98beacf11bSopenharmony_ci { 99beacf11bSopenharmony_ci PRINTK("ERROR: bchlib_write failed: %d\n", ret); 100beacf11bSopenharmony_ci return byteswritten; 101beacf11bSopenharmony_ci } 102beacf11bSopenharmony_ci bch->dirty = true; 103beacf11bSopenharmony_ci 104beacf11bSopenharmony_ci /* Adjust pointers and counts */ 105beacf11bSopenharmony_ci 106beacf11bSopenharmony_ci sector++; 107beacf11bSopenharmony_ci 108beacf11bSopenharmony_ci if (sector >= bch->nsectors) 109beacf11bSopenharmony_ci { 110beacf11bSopenharmony_ci return nbytes; 111beacf11bSopenharmony_ci } 112beacf11bSopenharmony_ci 113beacf11bSopenharmony_ci byteswritten = nbytes; 114beacf11bSopenharmony_ci buffer += nbytes; 115beacf11bSopenharmony_ci len -= nbytes; 116beacf11bSopenharmony_ci } 117beacf11bSopenharmony_ci 118beacf11bSopenharmony_ci /* Then write all of the full sectors following the partial sector 119beacf11bSopenharmony_ci * directly from the user buffer. 120beacf11bSopenharmony_ci */ 121beacf11bSopenharmony_ci 122beacf11bSopenharmony_ci if (len >= bch->sectsize) 123beacf11bSopenharmony_ci { 124beacf11bSopenharmony_ci nsectors = len / bch->sectsize; 125beacf11bSopenharmony_ci if (sector + nsectors > bch->nsectors) 126beacf11bSopenharmony_ci { 127beacf11bSopenharmony_ci nsectors = bch->nsectors - sector; 128beacf11bSopenharmony_ci } 129beacf11bSopenharmony_ci 130beacf11bSopenharmony_ci /* Flush the dirty sector to keep the sector sequence */ 131beacf11bSopenharmony_ci 132beacf11bSopenharmony_ci ret = bchlib_flushsector(bch); 133beacf11bSopenharmony_ci if (ret < 0) 134beacf11bSopenharmony_ci { 135beacf11bSopenharmony_ci PRINTK("ERROR: Flush failed: %d\n", ret); 136beacf11bSopenharmony_ci return ret; 137beacf11bSopenharmony_ci } 138beacf11bSopenharmony_ci 139beacf11bSopenharmony_ci /* Write the contiguous sectors */ 140beacf11bSopenharmony_ci 141beacf11bSopenharmony_ci ret = los_disk_write(bch->disk->disk_id, (const void *)buffer, 142beacf11bSopenharmony_ci sector + bch->sectstart, nsectors); 143beacf11bSopenharmony_ci if (ret < 0) 144beacf11bSopenharmony_ci { 145beacf11bSopenharmony_ci PRINTK("ERROR: Write failed: %d\n", ret); 146beacf11bSopenharmony_ci return byteswritten; 147beacf11bSopenharmony_ci } 148beacf11bSopenharmony_ci 149beacf11bSopenharmony_ci /* Adjust pointers and counts */ 150beacf11bSopenharmony_ci 151beacf11bSopenharmony_ci sector += nsectors; 152beacf11bSopenharmony_ci nbytes = nsectors * bch->sectsize; 153beacf11bSopenharmony_ci byteswritten += nbytes; 154beacf11bSopenharmony_ci 155beacf11bSopenharmony_ci if (sector >= bch->nsectors) 156beacf11bSopenharmony_ci { 157beacf11bSopenharmony_ci return byteswritten; 158beacf11bSopenharmony_ci } 159beacf11bSopenharmony_ci 160beacf11bSopenharmony_ci buffer += nbytes; 161beacf11bSopenharmony_ci len -= nbytes; 162beacf11bSopenharmony_ci } 163beacf11bSopenharmony_ci 164beacf11bSopenharmony_ci /* Then write any partial final sector */ 165beacf11bSopenharmony_ci 166beacf11bSopenharmony_ci if (len > 0) 167beacf11bSopenharmony_ci { 168beacf11bSopenharmony_ci /* Read the sector into the sector buffer */ 169beacf11bSopenharmony_ci 170beacf11bSopenharmony_ci ret = bchlib_readsector(bch, sector + bch->sectstart); 171beacf11bSopenharmony_ci if (ret < 0) 172beacf11bSopenharmony_ci { 173beacf11bSopenharmony_ci return byteswritten; 174beacf11bSopenharmony_ci } 175beacf11bSopenharmony_ci 176beacf11bSopenharmony_ci /* Copy the head end of the sector from the user buffer */ 177beacf11bSopenharmony_ci 178beacf11bSopenharmony_ci ret = LOS_CopyToKernel(bch->buffer, len, buffer, len); 179beacf11bSopenharmony_ci if (ret != EOK) 180beacf11bSopenharmony_ci { 181beacf11bSopenharmony_ci PRINTK("ERROR: bchlib_write failed: %d\n", ret); 182beacf11bSopenharmony_ci return byteswritten; 183beacf11bSopenharmony_ci } 184beacf11bSopenharmony_ci bch->dirty = true; 185beacf11bSopenharmony_ci 186beacf11bSopenharmony_ci /* Adjust counts */ 187beacf11bSopenharmony_ci 188beacf11bSopenharmony_ci byteswritten += len; 189beacf11bSopenharmony_ci } 190beacf11bSopenharmony_ci 191beacf11bSopenharmony_ci return byteswritten; 192beacf11bSopenharmony_ci} 193beacf11bSopenharmony_ci 194