/* * Copyright (c) 2016 Actions Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Copyright (c) 2016 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #define CONFIG_MMC_SDCARD_DEV_NAME "sd" const struct device *sd_disk; //static u32_t sd_disk_sector_cnt; static int sd_disk_status(struct disk_info *disk) { if (!sd_disk) { return DISK_STATUS_NOMEDIA; } return DISK_STATUS_OK; } static int sd_disk_initialize(struct disk_info *disk) { u32_t sector_cnt; int ret; if (sd_disk) { return 0; } sd_disk = device_get_binding(CONFIG_MMC_SDCARD_DEV_NAME); if (!sd_disk) { return -ENODEV; } if (0 != sd_card_storage_init(sd_disk)) { sd_disk = NULL; return -ENODEV; } ret = sd_card_storage_ioctl(sd_disk, DISK_IOCTL_GET_SECTOR_COUNT, (void *)§or_cnt); if (!ret) { //sd_disk_sector_cnt = sector_cnt; if(disk->sector_cnt){ if(disk->sector_offset + disk->sector_cnt > sector_cnt) printk("error:sd disk part over sd max capcity = %d\n", sector_cnt); }else{ disk->sector_cnt = sector_cnt; } } else { printk("failed to get sector count error=%d\n", ret); sd_disk = NULL; return -EFAULT; } return 0; } static int sd_disk_read(struct disk_info *disk, uint8_t *buff, uint32_t start_sector, uint32_t sector_count) { uint64_t start_addr; uint64_t len; if (!sd_disk) { return -ENODEV; } //if (sd_disk_sector_cnt == 0) { //goto read; //} if ((start_sector >= disk->sector_cnt) || (sector_count == 0)){ return -EIO; } if (start_sector + sector_count > disk->sector_cnt) { sector_count = disk->sector_cnt - start_sector; } start_sector += disk->sector_offset; start_addr = ((uint64_t)start_sector << 9); len = ((uint64_t)sector_count << 9); //read: /* is it OK? */ if (flash_read(sd_disk, start_addr, buff, len) != 0) { return -EIO; } return 0; } static int sd_disk_write(struct disk_info *disk, const uint8_t *buff, uint32_t start_sector, uint32_t sector_count) { uint64_t start_addr; uint64_t len; if (!sd_disk) { return -ENODEV; } //if (sd_disk_sector_cnt == 0) { //goto write; //} if ((start_sector >= disk->sector_cnt) || (sector_count == 0)){ return -EIO; } if (start_sector + sector_count > disk->sector_cnt) { sector_count = disk->sector_cnt - start_sector; } start_sector += disk->sector_offset; start_addr = ((uint64_t)start_sector << 9); len = ((uint64_t)sector_count << 9); //write: if (flash_write(sd_disk, start_addr, buff, len) != 0) { return -EIO; } return 0; } static int sd_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) { int ret = 0; const struct device *tmp_disk; if (!sd_disk && (cmd != DISK_IOCTL_HW_DETECT)) { return -ENODEV; } switch (cmd) { case DISK_IOCTL_CTRL_SYNC: break; case DISK_IOCTL_GET_SECTOR_COUNT: if (disk->sector_cnt > 0) { *(uint32_t *)buff = disk->sector_cnt; } else { ret = sd_card_storage_ioctl(sd_disk, cmd, buff); } break; case DISK_IOCTL_GET_SECTOR_SIZE: case DISK_IOCTL_GET_ERASE_BLOCK_SZ: //case DISK_IOCTL_GET_DISK_SIZE: ret = sd_card_storage_ioctl(sd_disk, cmd, buff); break; case DISK_IOCTL_HW_DETECT: if (sd_disk) { ret = sd_card_storage_ioctl(sd_disk, cmd, buff); } else { tmp_disk = device_get_binding(CONFIG_MMC_SDCARD_DEV_NAME); if (tmp_disk) { ret = sd_card_storage_ioctl(tmp_disk, cmd, buff); } else { return -ENODEV; } } if (ret == 0) { if (*(uint8_t *)buff != STA_DISK_OK) { sd_disk = NULL; } } break; default: return -EINVAL; } return ret; } struct disk_operations disk_sd_operation = { .init = sd_disk_initialize, .status = sd_disk_status, .read = sd_disk_read, .write = sd_disk_write, .ioctl = sd_disk_ioctl, }; struct disk_info disk_sd_mass = { .name = "SD", .sector_size = 512, .sector_offset = 0, .sector_cnt = 0, .ops = &disk_sd_operation, }; static int sd_disk_init(const struct device *dev) { const struct partition_entry *parti; ARG_UNUSED(dev); parti = partition_get_stf_part(STORAGE_ID_SD, PARTITION_FILE_ID_UDISK); if (parti) { if (partition_is_used_sector(parti)) { disk_sd_mass.sector_offset = parti->offset; disk_sd_mass.sector_cnt = (parti->size); } else { disk_sd_mass.sector_offset = parti->offset >> 9; disk_sd_mass.sector_cnt = parti->size >> 9; } } printk("sd_disk_init,size=%d, off=%d secotr\n", disk_sd_mass.sector_cnt, disk_sd_mass.sector_offset); disk_access_register(&disk_sd_mass); return 0; } SYS_INIT(sd_disk_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);