📄 disk.c
字号:
return -EINVAL;
info->connected = false;
chan->valid = false;
// clear partition data and invalidate
// any allocated devices
for (i = 0; i < MBR_PART_NUM; i++)
{
info->partitions[i].type = 0x00;
if (0 != info->devs[i])
{
struct cyg_devtab_entry *dtab;
disk_channel *dchan;
dtab = (struct cyg_devtab_entry *)info->devs[i];
dchan = (disk_channel *) dtab->priv;
dchan->valid = false;
}
}
D(("disk disconnected\n"));
return ENOERR;
}
static Cyg_ErrNo
disk_lookup(struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
disk_channel *chan = (disk_channel *) (*tab)->priv;
cyg_disk_info_t *info = chan->info;
struct cyg_devtab_entry *new_tab;
disk_channel *new_chan;
int dev_num;
if (!info->connected || name[0] < '0' || name[0] > '4' || '\0' != name[1])
return -EINVAL;
dev_num = name[0] - '0';
D(("disk lookup dev number = %d\n", dev_num));
if (0 == dev_num)
{
// 0 is the root device number
return ENOERR;
}
if (0x00 == info->partitions[dev_num-1].type)
{
D(("disk NO partition for dev\n"));
return -EINVAL;
}
if (0 == info->devs[dev_num-1])
{
D(("disk creating new devtab entry\n"));
// alloc mem for new device
new_tab = (struct cyg_devtab_entry *)
malloc(sizeof(struct cyg_devtab_entry));
if (NULL == new_tab)
return -ENOMEM;
// alloc mem for new device private data
new_chan = (disk_channel *)malloc(sizeof(disk_channel));
if (NULL == new_chan)
{
free(new_tab);
return -ENOMEM;
}
}
else
{
new_tab = (struct cyg_devtab_entry *) info->devs[dev_num-1];
new_chan = (disk_channel *) new_tab->priv;
}
// copy device data from parent
*new_tab = **tab;
*new_chan = *chan;
new_tab->priv = (void *)new_chan;
// set partition ptr and put this device into devices array
new_chan->partition = &info->partitions[dev_num-1];
chan->info->devs[dev_num-1] = (cyg_addrword_t) new_tab;
// return device tab
*tab = new_tab;
return ENOERR;
}
// ---------------------------------------------------------------------------
static Cyg_ErrNo
disk_bread(cyg_io_handle_t handle,
void *buf,
cyg_uint32 *len,
cyg_uint32 pos)
{
cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle;
disk_channel *chan = (disk_channel *) t->priv;
disk_funs *funs = chan->funs;
cyg_disk_info_t *info = chan->info;
cyg_uint32 size = *len;
cyg_uint8 *bbuf = (cyg_uint8 *)buf;
Cyg_ErrNo res = ENOERR;
cyg_uint32 last;
if (!info->connected || !chan->valid)
return -EINVAL;
if (NULL != chan->partition)
{
pos += chan->partition->start;
last = chan->partition->end;
}
else
{
last = info->blocks_num-1;
}
D(("disk read block=%d len=%d buf=%p\n", pos, *len, buf));
while (size > 0)
{
if (pos > last)
{
res = -EIO;
break;
}
res = (funs->read)(chan, (void*)bbuf, info->block_size, pos);
if (ENOERR != res)
break;
if (!info->connected)
{
res = -EINVAL;
break;
}
bbuf += info->block_size;
pos++;
size--;
}
*len -= size;
return res;
}
// ---------------------------------------------------------------------------
static Cyg_ErrNo
disk_bwrite(cyg_io_handle_t handle,
const void *buf,
cyg_uint32 *len,
cyg_uint32 pos)
{
cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle;
disk_channel *chan = (disk_channel *) t->priv;
disk_funs *funs = chan->funs;
cyg_disk_info_t *info = chan->info;
cyg_uint32 size = *len;
cyg_uint8 *bbuf = (cyg_uint8 * const) buf;
Cyg_ErrNo res = ENOERR;
cyg_uint32 last;
if (!info->connected || !chan->valid)
return -EINVAL;
if (NULL != chan->partition)
{
pos += chan->partition->start;
last = chan->partition->end;
}
else
{
last = info->blocks_num-1;
}
D(("disk write block=%d len=%d buf=%p\n", pos, *len, buf));
while (size > 0)
{
if (pos > last)
{
res = -EIO;
break;
}
res = (funs->write)(chan, (void*)bbuf, info->block_size, pos);
if (ENOERR != res)
break;
if (!info->connected)
{
res = -EINVAL;
break;
}
bbuf += info->block_size;
pos++;
size--;
}
*len -= size;
return res;
}
// ---------------------------------------------------------------------------
static cyg_bool
disk_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
{
cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle;
disk_channel *chan = (disk_channel *) t->priv;
cyg_disk_info_t *cinfo = chan->info;
if (!cinfo->connected || !chan->valid)
return false;
else
return true;
}
// ---------------------------------------------------------------------------
static Cyg_ErrNo
disk_get_config(cyg_io_handle_t handle,
cyg_uint32 key,
void *xbuf,
cyg_uint32 *len)
{
cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle;
disk_channel *chan = (disk_channel *) t->priv;
cyg_disk_info_t *info = chan->info;
cyg_disk_info_t *buf = (cyg_disk_info_t *) xbuf;
disk_funs *funs = chan->funs;
Cyg_ErrNo res = ENOERR;
if (!info->connected || !chan->valid)
return -EINVAL;
D(("disk get config key=%d\n", key));
switch (key) {
case CYG_IO_GET_CONFIG_DISK_INFO:
if (*len < sizeof(cyg_disk_info_t)) {
return -EINVAL;
}
*buf = *chan->info;
*len = sizeof(cyg_disk_info_t);
break;
default:
// pass down to lower layers
res = (funs->get_config)(chan, key, xbuf, len);
}
return res;
}
// ---------------------------------------------------------------------------
static Cyg_ErrNo
disk_set_config(cyg_io_handle_t handle,
cyg_uint32 key,
const void *xbuf,
cyg_uint32 *len)
{
cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle;
disk_channel *chan = (disk_channel *) t->priv;
cyg_disk_info_t *info = chan->info;
disk_funs *funs = chan->funs;
if (!info->connected || !chan->valid)
return -EINVAL;
D(("disk set config key=%d\n", key));
// pass down to lower layers
return (funs->set_config)(chan, key, xbuf, len);
}
// ---------------------------------------------------------------------------
// EOF disk.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -