📄 disk.c
字号:
//==========================================================================//// io/disk/disk.c//// High level disk driver////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 2003 Savin Zlobec //// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): savin // Date: 2003-06-10// Purpose: Top level disk driver// Description: ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/io.h>#include <pkgconf/io_disk.h>#include <cyg/io/io.h>#include <cyg/io/devtab.h>#include <cyg/io/disk.h>#include <cyg/infra/cyg_ass.h> // assertion support#include <cyg/infra/diag.h> // diagnostic output#include <stdlib.h> // malloc // ---------------------------------------------------------------------------//#define DEBUG 1#ifdef DEBUG# define D(_args_) diag_printf _args_#else# define D(_args_)#endif// ---------------------------------------------------------------------------// Master Boot Record defines#define MBR_SIG_ADDR 0x1FE // signature address #define MBR_SIG_BYTE0 0x55 // signature first byte value#define MBR_SIG_BYTE1 0xAA // signature second byte value#define MBR_PART_ADDR 0x1BE // first partition address#define MBR_PART_SIZE 0x10 // partition size#define MBR_PART_NUM 4 // number of partitions// Get cylinders, heads and sectors from data (MBR partition format)#define READ_CHS(_data_, _c_, _h_, _s_) \ do { \ _h_ = (*((cyg_uint8 *)_data_)); \ _s_ = (*(((cyg_uint8 *)_data_)+1) & 0x3F); \ _c_ = (*(((cyg_uint8 *)_data_)+1) & ~0x3F) << 2 | \ (*(((cyg_uint8 *)_data_)+2)); \ } while (0)// Get double word from data (MBR partition format)#define READ_DWORD(_data_, _val_) \ do { \ _val_ = *((cyg_uint8 *)_data_) | \ *(((cyg_uint8 *)_data_)+1) << 8 | \ *(((cyg_uint8 *)_data_)+2) << 16 | \ *(((cyg_uint8 *)_data_)+3) << 24; \ } while (0)// Convert cylinders, heads and sectors to LBA sectors #define CHS_TO_LBA(_info_, _c_, _h_, _s_, _lba_) \ (_lba_=(((_c_)*(_info_)->heads_num+(_h_))*(_info_)->sectors_num)+(_s_)-1) // ---------------------------------------------------------------------------static Cyg_ErrNo disk_bread(cyg_io_handle_t handle, void *buf, cyg_uint32 *len, cyg_uint32 pos);static Cyg_ErrNo disk_bwrite(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len, cyg_uint32 pos);static Cyg_ErrNo disk_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);static Cyg_ErrNo disk_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);static Cyg_ErrNo disk_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);BLOCK_DEVIO_TABLE(cyg_io_disk_devio, disk_bwrite, disk_bread, disk_select, disk_get_config, disk_set_config);static cyg_bool disk_init(struct cyg_devtab_entry *tab);static Cyg_ErrNo disk_connected(struct cyg_devtab_entry *tab, cyg_disk_identify_t *ident);static Cyg_ErrNo disk_disconnected(struct cyg_devtab_entry *tab);static Cyg_ErrNo disk_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name);DISK_CALLBACKS(cyg_io_disk_callbacks, disk_init, disk_connected, disk_disconnected, disk_lookup); // ---------------------------------------------------------------------------//// Read partition from data// static void read_partition(cyg_uint8 *data, cyg_disk_info_t *info, cyg_disk_partition_t *part){ cyg_uint16 c, h, s; part->type = data[4]; part->state = data[0]; READ_CHS(&data[1], c, h, s); CHS_TO_LBA(&info->ident, c, h, s, part->start); READ_CHS(&data[5], c, h, s); CHS_TO_LBA(&info->ident, c, h, s, part->end); READ_DWORD(&data[12], part->size);}//// Read Master Boot Record (partitions)//static Cyg_ErrNo read_mbr(disk_channel *chan){ cyg_disk_info_t *info = chan->info; disk_funs *funs = chan->funs; cyg_uint8 buf[512]; Cyg_ErrNo res = ENOERR; int i; for (i = 0; i < MBR_PART_NUM; i++) info->partitions[i].type = 0x00; res = (funs->read)(chan, (void *)buf, 512, 0); if (ENOERR != res) return res; if (MBR_SIG_BYTE0 == buf[MBR_SIG_ADDR+0] && MBR_SIG_BYTE1 == buf[MBR_SIG_ADDR+1]) { D(("disk MBR found\n")); for (i = 0; i < MBR_PART_NUM; i++) { cyg_disk_partition_t *part = &info->partitions[i]; read_partition(&buf[MBR_PART_ADDR+MBR_PART_SIZE*i], info, part); #ifdef DEBUG if (0x00 != part->type) { D(("\ndisk MBR partition %d:\n", i)); D((" type = %02X\n", part->type)); D((" state = %02X\n", part->state)); D((" start = %d\n", part->start)); D((" end = %d\n", part->end)); D((" size = %d\n\n", part->size)); }#endif } } return ENOERR;}static cyg_bool disk_init(struct cyg_devtab_entry *tab){ disk_channel *chan = (disk_channel *) tab->priv; cyg_disk_info_t *info = chan->info; int i; if (!chan->init) { info->connected = false; // clear devices array (one per partition) // and partition data for (i = 0; i < MBR_PART_NUM; i++) { info->devs[i] = (cyg_addrword_t) 0; info->partitions[i].type = 0x00; } chan->init = true; } return true;}static Cyg_ErrNodisk_connected(struct cyg_devtab_entry *tab, cyg_disk_identify_t *ident){ disk_channel *chan = (disk_channel *) tab->priv; cyg_disk_info_t *info = chan->info; Cyg_ErrNo res = ENOERR; if (!chan->init) return -EINVAL; info->ident = *ident; info->block_size = 512; info->blocks_num = ident->lba_sectors_num; D(("disk connected\n")); D((" serial = '%s'\n", ident->serial)); D((" firmware rev = '%s'\n", ident->firmware_rev)); D((" model num = '%s'\n", ident->model_num)); D((" block_size = %d\n", info->block_size)); D((" blocks_num = %d\n", info->blocks_num)); if (chan->mbr_support) { // read disk master boot record res = read_mbr(chan); } if (ENOERR == res) { // now declare that we are connected info->connected = true; chan->valid = true; } return res;}static Cyg_ErrNodisk_disconnected(struct cyg_devtab_entry *tab){ disk_channel *chan = (disk_channel *) tab->priv; cyg_disk_info_t *info = chan->info; int i; if (!chan->init)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -