//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 2003 Savin Zlobec.
+// Copyright (C) 2003 Savin Zlobec
+// Copyright (C) 2004, 2006 eCosCentric Limited
//
// 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
char *filename;
} synth_disk_info_t;
+typedef struct { int dummy; } synth_controller_t;
+
// ----------------------------------------------------------------------------
static cyg_bool synth_disk_init(struct cyg_devtab_entry *tab);
struct cyg_devtab_entry *sub_tab,
const char *name);
-static DISK_FUNS(synth_disk_funs,
- synth_disk_read,
- synth_disk_write,
- synth_disk_get_config,
- synth_disk_set_config
+DISK_FUNS(synth_disk_funs,
+ synth_disk_read,
+ synth_disk_write,
+ synth_disk_get_config,
+ synth_disk_set_config
);
// ----------------------------------------------------------------------------
-#define SYNTH_DISK_INSTANCE(_number_,_mbr_supp_, _cyl_,_hpt_,_spt_) \
-static synth_disk_info_t synth_disk_info##_number_ = { \
- num: _number_, \
- cylinders_num: _cyl_, \
- heads_num: _hpt_, \
- sectors_num: _spt_, \
- size: CYGNUM_IO_DISK_ECOSYNTH_DISK##_number_##_SIZE, \
- filefd: -1, \
- filename: CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_FILENAME \
-}; \
-DISK_CHANNEL(synth_disk_channel##_number_, \
- synth_disk_funs, \
- synth_disk_info##_number_, \
- _mbr_supp_, \
- 4 \
-); \
-BLOCK_DEVTAB_ENTRY(synth_disk_io##_number_, \
- CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_NAME, \
- 0, \
- &cyg_io_disk_devio, \
- synth_disk_init, \
- synth_disk_lookup, \
- &synth_disk_channel##_number_ \
+
+#define SYNTH_DISK_INSTANCE(_number_,_mbr_supp_, _cyl_,_hpt_,_spt_) \
+static synth_disk_info_t synth_disk_info##_number_ = { \
+ num: _number_, \
+ cylinders_num: _cyl_, \
+ heads_num: _hpt_, \
+ sectors_num: _spt_, \
+ size: CYGNUM_IO_DISK_ECOSYNTH_DISK##_number_##_SIZE, \
+ filefd: -1, \
+ filename: CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_FILENAME \
+}; \
+static synth_controller_t synth_controller_##_number_; \
+DISK_CONTROLLER( synth_disk_controller_##_number_, synth_controller_##_number_ ); \
+DISK_CHANNEL(synth_disk_channel##_number_, \
+ synth_disk_funs, \
+ synth_disk_info##_number_, \
+ synth_disk_controller_##_number_, \
+ _mbr_supp_, \
+ 4 \
+); \
+BLOCK_DEVTAB_ENTRY(synth_disk_io##_number_, \
+ CYGDAT_IO_DISK_ECOSYNTH_DISK##_number_##_NAME, \
+ 0, \
+ &cyg_io_disk_devio, \
+ synth_disk_init, \
+ synth_disk_lookup, \
+ &synth_disk_channel##_number_ \
);
// ----------------------------------------------------------------------------
if (result)
{
- cyg_disk_identify_t ident;
-
- ident.serial[0] = '\0';
- ident.firmware_rev[0] = '\0';
- ident.model_num[0] = '\0';
- ident.lba_sectors_num = synth_info->size / 512;
- ident.cylinders_num = synth_info->cylinders_num;
- ident.heads_num = synth_info->heads_num;
- ident.sectors_num = synth_info->sectors_num;
if (!(chan->callbacks->disk_init)(tab))
return false;
- if (ENOERR != (chan->callbacks->disk_connected)(tab, &ident))
- return false;
}
return result;
}
+// ----------------------------------------------------------------------------
+
static Cyg_ErrNo
-synth_disk_lookup(struct cyg_devtab_entry **tab,
+synth_disk_lookup(struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
+ Cyg_ErrNo res;
disk_channel *chan = (disk_channel *) (*tab)->priv;
- return (chan->callbacks->disk_lookup(tab, sub_tab, name));
+ synth_disk_info_t *synth_info = (synth_disk_info_t *) chan->dev_priv;
+ cyg_disk_identify_t ident;
+
+ ident.serial[0] = '\0';
+ ident.firmware_rev[0] = '\0';
+ ident.model_num[0] = '\0';
+ ident.lba_sectors_num = synth_info->size / 512;
+ ident.cylinders_num = synth_info->cylinders_num;
+ ident.heads_num = synth_info->heads_num;
+ ident.sectors_num = synth_info->sectors_num;
+ ident.phys_block_size = 1;
+ ident.max_transfer = 2048;
+
+ res = (chan->callbacks->disk_connected)(*tab, &ident);
+
+ if( res == ENOERR )
+ res = (chan->callbacks->disk_lookup(tab, sub_tab, name));
+
+ return res;
}
+// ----------------------------------------------------------------------------
+
static Cyg_ErrNo
synth_disk_read(disk_channel *chan,
void *buf,
cyg_hal_sys_lseek(synth_info->filefd,
block_num * chan->info->block_size,
CYG_HAL_SYS_SEEK_SET);
- cyg_hal_sys_read(synth_info->filefd, buf, len);
+ cyg_hal_sys_read(synth_info->filefd, buf, len*512);
return ENOERR;
}
return -EIO;
}
+// ----------------------------------------------------------------------------
+
static Cyg_ErrNo
synth_disk_write(disk_channel *chan,
const void *buf,
cyg_hal_sys_lseek(synth_info->filefd,
block_num * chan->info->block_size,
CYG_HAL_SYS_SEEK_SET);
- cyg_hal_sys_write(synth_info->filefd, buf, len);
+ cyg_hal_sys_write(synth_info->filefd, buf, len*512);
// cyg_hal_sys_fdatasync(synth_info->filefd);
return ENOERR;
}
return -EIO;
}
+// ----------------------------------------------------------------------------
+
static Cyg_ErrNo
synth_disk_get_config(disk_channel *chan,
cyg_uint32 key,
return -EINVAL;
}
+// ----------------------------------------------------------------------------
+
static Cyg_ErrNo
synth_disk_set_config(disk_channel *chan,
cyg_uint32 key,
const void *xbuf,
cyg_uint32 *len)
{
-
+ Cyg_ErrNo res = ENOERR;
#ifdef DEBUG
diag_printf("synth disk set config\n");
#endif
-
- return -EINVAL;
+
+ switch ( key )
+ {
+ case CYG_IO_SET_CONFIG_DISK_MOUNT:
+ // We have nothing to do here for this option.
+ break;
+
+ case CYG_IO_SET_CONFIG_DISK_UMOUNT:
+ if( chan->info->mounts == 0 )
+ {
+ // If this is the last unmount of this disk, then disconnect it from
+ // the driver system so the user can swap it out if he wants.
+ res = (chan->callbacks->disk_disconnected)(chan);
+ }
+ break;
+
+ default:
+ res = -EINVAL;
+ break;
+ }
+
+ return res;
+}
+
+// ----------------------------------------------------------------------------
+
+externC cyg_bool synth_disk_change( int unit, char *filename, int size,
+ int cyls, int heads, int sectors)
+{
+ struct cyg_devtab_entry *tab = &synth_disk_io0;
+ disk_channel *chan = (disk_channel *) tab->priv;
+ synth_disk_info_t *synth_info = (synth_disk_info_t *) chan->dev_priv;
+ int err = 0;
+
+ if (!chan->init)
+ return false;
+
+ synth_info->filename = filename;
+ synth_info->size = size;
+ synth_info->cylinders_num = cyls;
+ synth_info->heads_num = heads;
+ synth_info->sectors_num = sectors;
+
+#ifdef DEBUG
+ diag_printf("synth disk %d change size=%d\n",
+ synth_info->num, synth_info->size);
+#endif
+
+ err = cyg_hal_sys_close( synth_info->filefd );
+
+#ifdef DEBUG
+ if( err != 0 )
+ {
+ diag_printf("synth disk change, failed to close old image: %d\n",err);
+ }
+#endif
+
+ synth_info->filefd = cyg_hal_sys_open(synth_info->filename,
+ CYG_HAL_SYS_O_RDWR,
+ CYG_HAL_SYS_S_IRWXU|CYG_HAL_SYS_S_IRWXG|CYG_HAL_SYS_S_IRWXO);
+
+ if (-ENOENT == synth_info->filefd)
+ {
+ synth_info->filefd = cyg_hal_sys_open(synth_info->filename,
+ CYG_HAL_SYS_O_RDWR|CYG_HAL_SYS_O_CREAT, 0644);
+
+ if (synth_info->filefd >= 0)
+ {
+ unsigned char b = 0x00;
+ int i;
+
+ for (i = 0; i < synth_info->size; i++)
+ cyg_hal_sys_write(synth_info->filefd, &b, 1);
+ }
+ }
+
+ if (synth_info->filefd < 0)
+ {
+ CYG_ASSERT(false, "Can't open/create disk image file");
+ return false;
+ }
+
+ return true;
}
// ----------------------------------------------------------------------------