introduce cdev
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
6411c3b2be
commit
a2b7cd183b
|
@ -43,7 +43,6 @@
|
|||
*/
|
||||
static struct device_d cfi_dev = {
|
||||
.name = "cfi_flash",
|
||||
.id = "nor0",
|
||||
.map_base = IMX_CS0_BASE,
|
||||
.size = 32 * 1024 * 1024, /* area size */
|
||||
};
|
||||
|
@ -245,10 +244,9 @@ static int imx31_devices_init(void)
|
|||
* Create partitions that should be
|
||||
* not touched by any regular user
|
||||
*/
|
||||
#ifdef CONFIG_PARTITION
|
||||
dev_add_partition(&cfi_dev, 0x00000, 0x40000, PARTITION_FIXED, "self"); /* ourself */
|
||||
dev_add_partition(&cfi_dev, 0x40000, 0x20000, PARTITION_FIXED, "env"); /* environment */
|
||||
#endif
|
||||
devfs_add_partition("nor0", 0x00000, 0x40000, PARTITION_FIXED, "self0"); /* ourself */
|
||||
devfs_add_partition("nor0", 0x40000, 0x20000, PARTITION_FIXED, "env0"); /* environment */
|
||||
|
||||
dev_protect(&cfi_dev, 0x20000, 0, 1);
|
||||
|
||||
register_device(&sram_dev);
|
||||
|
|
|
@ -111,9 +111,9 @@ static struct device_d nand_dev = {
|
|||
|
||||
static int pcm038_devices_init(void)
|
||||
{
|
||||
struct device_d *nand, *dev;
|
||||
char *envdev = "no";
|
||||
int i;
|
||||
struct device_d *nand;
|
||||
char *envdev = "no";
|
||||
|
||||
unsigned int mode[] = {
|
||||
PD0_AIN_FEC_TXD0,
|
||||
|
@ -192,20 +192,16 @@ static int pcm038_devices_init(void)
|
|||
nand = get_device_by_path("/dev/nand0");
|
||||
if (!nand)
|
||||
break;
|
||||
dev = dev_add_partition(nand, 0x00000, 0x40000, PARTITION_FIXED, "self_raw");
|
||||
if (!dev)
|
||||
break;
|
||||
dev_add_bb_dev(dev, "self0");
|
||||
devfs_add_partition("nand0", 0x00000, 0x40000, PARTITION_FIXED, "self_raw");
|
||||
dev_add_bb_dev("self_raw", "self0");
|
||||
|
||||
dev = dev_add_partition(nand, 0x40000, 0x20000, PARTITION_FIXED, "env_raw");
|
||||
if (!dev)
|
||||
break;
|
||||
dev_add_bb_dev(dev, "env0");
|
||||
devfs_add_partition("nand0", 0x40000, 0x20000, PARTITION_FIXED, "env_raw");
|
||||
dev_add_bb_dev("env_raw", "env0");
|
||||
envdev = "NAND";
|
||||
break;
|
||||
default:
|
||||
dev_add_partition(&cfi_dev, 0x00000, 0x40000, PARTITION_FIXED, "self");
|
||||
dev_add_partition(&cfi_dev, 0x40000, 0x20000, PARTITION_FIXED, "env");
|
||||
devfs_add_partition("nor0", 0x00000, 0x40000, PARTITION_FIXED, "self0");
|
||||
devfs_add_partition("nor0", 0x40000, 0x20000, PARTITION_FIXED, "env0");
|
||||
dev_protect(&cfi_dev, 0x40000, 0, 1);
|
||||
envdev = "NOR";
|
||||
}
|
||||
|
|
|
@ -35,20 +35,24 @@
|
|||
|
||||
static struct device_d cfi_dev = {
|
||||
.name = "cfi_flash",
|
||||
.id = "nor0",
|
||||
|
||||
.map_base = 0x10000000,
|
||||
.size = 16 * 1024 * 1024,
|
||||
};
|
||||
|
||||
static struct memory_platform_data sdram_pdata = {
|
||||
.name = "ram0",
|
||||
.flags = DEVFS_RDWR,
|
||||
};
|
||||
|
||||
static struct device_d sdram_dev = {
|
||||
.name = "ram",
|
||||
.id = "ram0",
|
||||
.name = "mem",
|
||||
|
||||
.map_base = 0x08000000,
|
||||
.size = 16 * 1024 * 1024,
|
||||
|
||||
.type = DEVICE_TYPE_DRAM,
|
||||
.platform_data = &sdram_pdata,
|
||||
};
|
||||
|
||||
static struct dm9000_platform_data dm9000_data = {
|
||||
|
@ -93,8 +97,8 @@ static int scb9328_devices_init(void) {
|
|||
register_device(&sdram_dev);
|
||||
register_device(&dm9000_dev);
|
||||
|
||||
dev_add_partition(&cfi_dev, 0x00000, 0x20000, PARTITION_FIXED, "self");
|
||||
dev_add_partition(&cfi_dev, 0x40000, 0x20000, PARTITION_FIXED, "env");
|
||||
devfs_add_partition("nor0", 0x00000, 0x20000, PARTITION_FIXED, "self0");
|
||||
devfs_add_partition("nor0", 0x40000, 0x20000, PARTITION_FIXED, "env0");
|
||||
dev_protect(&cfi_dev, 0x20000, 0, 1);
|
||||
|
||||
armlinux_set_bootparams((void *)0x08000100);
|
||||
|
|
|
@ -518,44 +518,46 @@ U_BOOT_CMD_START(memcpy)
|
|||
U_BOOT_CMD_HELP(cmd_memcpy_help)
|
||||
U_BOOT_CMD_END
|
||||
|
||||
static struct device_d mem_dev = {
|
||||
.name = "mem",
|
||||
.id = "mem",
|
||||
.map_base = 0,
|
||||
.size = ~0, /* FIXME: should be 0x100000000, ahem... */
|
||||
static struct file_operations memops = {
|
||||
.read = mem_read,
|
||||
.write = mem_write,
|
||||
.memmap = generic_memmap_rw,
|
||||
.lseek = dev_lseek_default,
|
||||
};
|
||||
|
||||
static int mem_probe(struct device_d *dev)
|
||||
{
|
||||
struct memory_platform_data *pdata = dev->platform_data;
|
||||
struct cdev *cdev;
|
||||
|
||||
cdev = xzalloc(sizeof (*cdev));
|
||||
dev->priv = cdev;
|
||||
|
||||
cdev->name = pdata->name;
|
||||
cdev->size = dev->size;
|
||||
cdev->ops = &memops;
|
||||
cdev->dev = dev;
|
||||
|
||||
devfs_create(cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct driver_d mem_drv = {
|
||||
.name = "mem",
|
||||
.probe = dummy_probe,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.read = mem_read,
|
||||
.write = mem_write,
|
||||
.memmap = mem_memmap,
|
||||
.lseek = dev_lseek_default,
|
||||
.probe = mem_probe,
|
||||
};
|
||||
|
||||
static struct driver_d ram_drv = {
|
||||
.name = "ram",
|
||||
.probe = dummy_probe,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.read = mem_read,
|
||||
.write = mem_write,
|
||||
.lseek = dev_lseek_default,
|
||||
.memmap = mem_memmap,
|
||||
.type = DEVICE_TYPE_DRAM,
|
||||
static struct memory_platform_data mem_dev_pdata = {
|
||||
.name = "mem",
|
||||
.flags = DEVFS_RDWR,
|
||||
};
|
||||
|
||||
static struct driver_d rom_drv = {
|
||||
.name = "rom",
|
||||
.probe = dummy_probe,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.read = mem_read,
|
||||
.memmap = mem_memmap,
|
||||
.lseek = dev_lseek_default,
|
||||
static struct device_d mem_dev = {
|
||||
.name = "mem",
|
||||
.map_base = 0,
|
||||
.size = ~0, /* FIXME: should be 0x100000000, ahem... */
|
||||
.platform_data = &mem_dev_pdata,
|
||||
};
|
||||
|
||||
static int mem_init(void)
|
||||
|
@ -566,10 +568,9 @@ static int mem_init(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
register_device(&mem_dev);
|
||||
register_driver(&mem_drv);
|
||||
register_driver(&ram_drv);
|
||||
register_driver(&rom_drv);
|
||||
register_device(&mem_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
142
commands/nand.c
142
commands/nand.c
|
@ -17,7 +17,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <fs.h>
|
||||
|
@ -31,40 +30,45 @@
|
|||
#include <nand.h>
|
||||
#include <linux/mtd/mtd-abi.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
|
||||
struct nand_bb {
|
||||
struct device_d device;
|
||||
|
||||
struct device_d *physdev;
|
||||
|
||||
char *devname;
|
||||
char *name;
|
||||
int open;
|
||||
|
||||
struct mtd_info_user info;
|
||||
|
||||
size_t raw_size;
|
||||
size_t size;
|
||||
int fd;
|
||||
off_t offset;
|
||||
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
static ssize_t nand_bb_read(struct device_d *dev, void *buf, size_t count,
|
||||
static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count,
|
||||
unsigned long offset, ulong flags)
|
||||
{
|
||||
struct nand_bb *bb = dev->priv;
|
||||
struct nand_bb *bb = cdev->priv;
|
||||
int ret, bytes = 0, now;
|
||||
|
||||
debug("%s %d %d\n", __func__, offset, count);
|
||||
|
||||
while(count) {
|
||||
ret = dev_ioctl(bb->physdev, MEMGETBADBLOCK, (void *)bb->offset);
|
||||
ret = ioctl(bb->fd, MEMGETBADBLOCK, (void *)bb->offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret) {
|
||||
debug("skipping bad block at 0x%08x\n", bb->offset);
|
||||
printf("skipping bad block at 0x%08x\n", bb->offset);
|
||||
bb->offset += bb->info.erasesize;
|
||||
}
|
||||
|
||||
now = min(count, (size_t)(bb->info.erasesize -
|
||||
(bb->offset % bb->info.erasesize)));
|
||||
ret = dev_read(bb->physdev, buf, now, bb->offset, flags);
|
||||
lseek(bb->fd, bb->offset, SEEK_SET);
|
||||
ret = read(bb->fd, buf, now);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf += now;
|
||||
|
@ -76,16 +80,16 @@ static ssize_t nand_bb_read(struct device_d *dev, void *buf, size_t count,
|
|||
return bytes;
|
||||
}
|
||||
|
||||
static ssize_t nand_bb_write(struct device_d *dev, const void *buf, size_t count,
|
||||
static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count,
|
||||
unsigned long offset, ulong flags)
|
||||
{
|
||||
struct nand_bb *bb = dev->priv;
|
||||
struct nand_bb *bb = cdev->priv;
|
||||
int ret, bytes = 0, now;
|
||||
|
||||
debug("%s %d %d\n", __func__, offset, count);
|
||||
debug("%s offset: 0x%08x count: 0x%08x\n", __func__, offset, count);
|
||||
|
||||
while(count) {
|
||||
ret = dev_ioctl(bb->physdev, MEMGETBADBLOCK, (void *)bb->offset);
|
||||
ret = ioctl(bb->fd, MEMGETBADBLOCK, (void *)bb->offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -96,7 +100,8 @@ static ssize_t nand_bb_write(struct device_d *dev, const void *buf, size_t count
|
|||
|
||||
now = min(count, (size_t)(bb->info.erasesize -
|
||||
(bb->offset % bb->info.erasesize)));
|
||||
ret = dev_write(bb->physdev, buf, now, bb->offset, flags);
|
||||
lseek(bb->fd, offset, SEEK_SET);
|
||||
ret = write(bb->fd, buf, now);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf += now;
|
||||
|
@ -108,21 +113,21 @@ static ssize_t nand_bb_write(struct device_d *dev, const void *buf, size_t count
|
|||
return bytes;
|
||||
}
|
||||
|
||||
static int nand_bb_erase(struct device_d *dev, size_t count, unsigned long offset)
|
||||
static int nand_bb_erase(struct cdev *cdev, size_t count, unsigned long offset)
|
||||
{
|
||||
struct nand_bb *bb = dev->priv;
|
||||
struct nand_bb *bb = cdev->priv;
|
||||
|
||||
if (offset != 0 || count != dev->size) {
|
||||
if (offset != 0 || count != bb->raw_size) {
|
||||
printf("can only erase whole device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dev_erase(bb->physdev, dev->size, 0);
|
||||
return erase(bb->fd, bb->raw_size, 0);
|
||||
}
|
||||
|
||||
static int nand_bb_open(struct device_d *dev, struct filep *f)
|
||||
static int nand_bb_open(struct cdev *cdev, struct filep *f)
|
||||
{
|
||||
struct nand_bb *bb = dev->priv;
|
||||
struct nand_bb *bb = cdev->priv;
|
||||
|
||||
if (bb->open)
|
||||
return -EBUSY;
|
||||
|
@ -133,9 +138,9 @@ static int nand_bb_open(struct device_d *dev, struct filep *f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nand_bb_close(struct device_d *dev, struct filep *f)
|
||||
static int nand_bb_close(struct cdev *cdev, struct filep *f)
|
||||
{
|
||||
struct nand_bb *bb = dev->priv;
|
||||
struct nand_bb *bb = cdev->priv;
|
||||
|
||||
bb->open = 0;
|
||||
|
||||
|
@ -147,12 +152,12 @@ static int nand_bb_calc_size(struct nand_bb *bb)
|
|||
ulong pos = 0;
|
||||
int ret;
|
||||
|
||||
while (pos < bb->physdev->size) {
|
||||
ret = dev_ioctl(bb->physdev, MEMGETBADBLOCK, (void *)pos);
|
||||
while (pos < bb->raw_size) {
|
||||
ret = ioctl(bb->fd, MEMGETBADBLOCK, (void *)pos);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ret)
|
||||
bb->device.size += bb->info.erasesize;
|
||||
bb->cdev.size += bb->info.erasesize;
|
||||
|
||||
pos += bb->info.erasesize;
|
||||
}
|
||||
|
@ -160,79 +165,67 @@ static int nand_bb_calc_size(struct nand_bb *bb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nand_bb_probe(struct device_d *dev)
|
||||
{
|
||||
struct nand_bb *bb = dev->priv;
|
||||
int ret;
|
||||
|
||||
ret = dev_ioctl(bb->physdev, MEMGETINFO, &bb->info);
|
||||
if (ret)
|
||||
return ret;
|
||||
return nand_bb_calc_size(bb);
|
||||
}
|
||||
|
||||
static void nand_bb_remove(struct device_d *dev)
|
||||
{
|
||||
}
|
||||
|
||||
struct driver_d nand_bb_driver = {
|
||||
.name = "nand_bb",
|
||||
.probe = nand_bb_probe,
|
||||
.remove = nand_bb_remove,
|
||||
static struct file_operations nand_bb_ops = {
|
||||
.open = nand_bb_open,
|
||||
.close = nand_bb_close,
|
||||
.read = nand_bb_read,
|
||||
.write = nand_bb_write,
|
||||
.erase = nand_bb_erase,
|
||||
.type = DEVICE_TYPE_NAND_BB,
|
||||
};
|
||||
|
||||
static int nand_bb_init(void)
|
||||
{
|
||||
return register_driver(&nand_bb_driver);
|
||||
}
|
||||
|
||||
device_initcall(nand_bb_init);
|
||||
|
||||
/**
|
||||
* Add a bad block aware device ontop of another (NAND) device
|
||||
* @param[in] dev The device to add a partition on
|
||||
* @param[in] name Partition name (can be obtained with devinfo command)
|
||||
* @return The device representing the new partition.
|
||||
*/
|
||||
struct device_d *dev_add_bb_dev(struct device_d *dev, const char *name)
|
||||
int dev_add_bb_dev(char *path, const char *name)
|
||||
{
|
||||
struct nand_bb *bb;
|
||||
int ret;
|
||||
struct stat s;
|
||||
|
||||
bb = xzalloc(sizeof(*bb));
|
||||
|
||||
bb->devname = asprintf("/dev/%s", basename(path));
|
||||
if (name)
|
||||
strcpy(bb->device.id, name);
|
||||
bb->cdev.name = strdup(name);
|
||||
else
|
||||
sprintf(bb->device.id, "%s.bb", dev->id);
|
||||
strcpy(bb->device.name, "nand_bb");
|
||||
bb->device.priv = bb;
|
||||
bb->device.size = 0;
|
||||
bb->device.type = DEVICE_TYPE_NAND_BB;
|
||||
bb->physdev = dev;
|
||||
bb->cdev.name = asprintf("%s.bb", basename(path));
|
||||
|
||||
if (register_device(&bb->device))
|
||||
ret = stat(bb->devname, &s);
|
||||
if (ret)
|
||||
goto free_out;
|
||||
|
||||
dev_add_child(dev, &bb->device);
|
||||
bb->raw_size = s.st_size;
|
||||
|
||||
return &bb->device;
|
||||
bb->fd = open(bb->devname, O_RDWR);
|
||||
if (bb->fd < 0) {
|
||||
ret = -ENODEV;
|
||||
goto free_out;
|
||||
}
|
||||
|
||||
ret = ioctl(bb->fd, MEMGETINFO, &bb->info);
|
||||
if (ret)
|
||||
goto free_out;
|
||||
|
||||
nand_bb_calc_size(bb);
|
||||
bb->cdev.ops = &nand_bb_ops;
|
||||
bb->cdev.priv = bb;
|
||||
|
||||
devfs_create(&bb->cdev);
|
||||
|
||||
return 0;
|
||||
|
||||
free_out:
|
||||
free(bb);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NAND_ADD (1 << 0)
|
||||
#define NAND_DEL (1 << 1)
|
||||
#define NAND_MARKBAD (1 << 2)
|
||||
|
||||
static int do_nand (cmd_tbl_t *cmdtp, int argc, char *argv[])
|
||||
static int do_nand(cmd_tbl_t *cmdtp, int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
struct device_d *dev;
|
||||
|
@ -262,13 +255,7 @@ static int do_nand (cmd_tbl_t *cmdtp, int argc, char *argv[])
|
|||
|
||||
if (command & NAND_ADD) {
|
||||
while (optind < argc) {
|
||||
dev = get_device_by_path(argv[optind]);
|
||||
if (!dev) {
|
||||
printf("no such device: %s\n", argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!dev_add_bb_dev(dev, NULL))
|
||||
if (dev_add_bb_dev(argv[optind], NULL))
|
||||
return 1;
|
||||
|
||||
optind++;
|
||||
|
@ -277,17 +264,20 @@ static int do_nand (cmd_tbl_t *cmdtp, int argc, char *argv[])
|
|||
|
||||
if (command & NAND_DEL) {
|
||||
while (optind < argc) {
|
||||
dev = get_device_by_path(argv[optind]);
|
||||
if (!dev) {
|
||||
struct cdev *cdev;
|
||||
cdev = cdev_by_name(basename(argv[optind]));
|
||||
if (!cdev) {
|
||||
printf("no such device: %s\n", argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
dev = cdev->dev;
|
||||
|
||||
if (dev->type != DEVICE_TYPE_NAND_BB) {
|
||||
printf("not a nand bb device: %s\n", dev);
|
||||
return 1;
|
||||
}
|
||||
bb = dev->priv;
|
||||
close(bb->fd);
|
||||
unregister_device(dev);
|
||||
free(bb);
|
||||
optind++;
|
||||
|
|
|
@ -37,99 +37,29 @@
|
|||
#include <partition.h>
|
||||
#include <errno.h>
|
||||
#include <xfuncs.h>
|
||||
#include <fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <libgen.h>
|
||||
|
||||
static int dev_del_partitions(struct device_d *physdev)
|
||||
{
|
||||
struct device_d *child, *tmp;
|
||||
struct partition *part;
|
||||
int ret;
|
||||
|
||||
device_for_each_child_safe(physdev, tmp, child) {
|
||||
if (child->type != DEVICE_TYPE_PARTITION) {
|
||||
printf("not a partition: %s\n", child->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
part = child->type_data;
|
||||
|
||||
if (part->flags & PARTITION_FIXED) {
|
||||
debug("Skip fixed partition: %s\n", child->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = unregister_device(child);
|
||||
if (ret) {
|
||||
printf("delete partition `%s' failed: %s\n", child->id, errno_str());
|
||||
return errno;
|
||||
}
|
||||
|
||||
debug("deleted partition: %s\n", child->id);
|
||||
|
||||
free(part);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dev_check_fixed(struct device_d *physdev, struct partition *new_part)
|
||||
{
|
||||
struct device_d *child;
|
||||
|
||||
device_for_each_child(physdev, child) {
|
||||
struct partition *part = child->type_data;
|
||||
|
||||
debug("check aginst partition: %s -", child->id);
|
||||
|
||||
if (!(part->flags & PARTITION_FIXED)) {
|
||||
debug(" not fixed, ok\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (new_part->offset == part->offset && /* new_part is exactly part */
|
||||
((new_part->device.size==0) || (new_part->device.size == part->device.size)) ) {
|
||||
debug(" fixed, but same size, ok\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((new_part->offset >= part->offset &&
|
||||
new_part->offset < part->offset + part->device.size) ||
|
||||
(new_part->offset + new_part->device.size > part->offset &&
|
||||
new_part->offset + new_part->device.size <= part->offset + part->device.size)) {
|
||||
printf(
|
||||
" failed\n"
|
||||
" partition spec %s \n"
|
||||
" violates fixed partition %s\n", new_part->name, child->id);
|
||||
errno = -EINVAL;
|
||||
return errno;
|
||||
}
|
||||
else
|
||||
debug(" fixed and within limit?, ok\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtd_part_do_parse_one(struct partition *part, const char *partstr,
|
||||
char **endp)
|
||||
static int mtd_part_do_parse_one(char *devname, const char *partstr,
|
||||
char **endp, unsigned long offset,
|
||||
off_t devsize, size_t *retsize)
|
||||
{
|
||||
ulong size;
|
||||
char *end;
|
||||
char buf[MAX_DRIVER_NAME];
|
||||
char buf[PATH_MAX];
|
||||
unsigned long flags = 0;
|
||||
int ret;
|
||||
|
||||
memset(buf, 0, MAX_DRIVER_NAME);
|
||||
memset(buf, 0, PATH_MAX);
|
||||
|
||||
if (*partstr == '-') {
|
||||
size = part->physdev->size - part->offset;
|
||||
size = devsize - offset;
|
||||
end = (char *)partstr + 1;
|
||||
} else {
|
||||
size = strtoul_suffix(partstr, &end, 0);
|
||||
}
|
||||
|
||||
if (size + part->offset > part->physdev->size) {
|
||||
printf("partition %s end is beyond device\n", part->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
partstr = end;
|
||||
|
||||
if (*partstr == '(') {
|
||||
|
@ -139,98 +69,78 @@ static int mtd_part_do_parse_one(struct partition *part, const char *partstr,
|
|||
printf("could not find matching ')'\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (end - partstr >= MAX_DRIVER_NAME) {
|
||||
printf("device name too long\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(part->name, partstr, end - partstr);
|
||||
sprintf(buf, "%s.", devname);
|
||||
memcpy(buf + strlen(buf), partstr, end - partstr);
|
||||
|
||||
end++;
|
||||
}
|
||||
|
||||
if (size + offset > devsize) {
|
||||
printf("%s: partition end is beyond device\n", buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
partstr = end;
|
||||
|
||||
if (*partstr == 'r' && *(partstr + 1) == 'o') {
|
||||
part->flags |= PARTITION_READONLY;
|
||||
flags |= PARTITION_READONLY;
|
||||
end = (char *)(partstr + 2);
|
||||
}
|
||||
|
||||
if (endp)
|
||||
*endp = end;
|
||||
|
||||
strcpy(part->device.name, "partition");
|
||||
part->device.size = size;
|
||||
*retsize = size;
|
||||
|
||||
return 0;
|
||||
ret = devfs_add_partition(devname, offset, size, flags, buf);
|
||||
if (ret)
|
||||
printf("cannot create %s: %s\n", buf, strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int do_addpart(cmd_tbl_t * cmdtp, int argc, char *argv[])
|
||||
{
|
||||
struct partition *part;
|
||||
struct device_d *dev;
|
||||
char *devname;
|
||||
char *endp;
|
||||
int num = 0;
|
||||
unsigned long offset;
|
||||
unsigned long offset = 0;
|
||||
off_t devsize;
|
||||
struct stat s;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("Usage:\n %s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = get_device_by_path(argv[1]);
|
||||
if (!dev) {
|
||||
printf("no such device: %s\n", argv[1]);
|
||||
if (stat(argv[1], &s)) {
|
||||
perror("addpart");
|
||||
return 1;
|
||||
}
|
||||
devsize = s.st_size;
|
||||
|
||||
dev_del_partitions(dev);
|
||||
|
||||
offset = 0;
|
||||
devname = basename(argv[1]);
|
||||
|
||||
endp = argv[2];
|
||||
|
||||
while (1) {
|
||||
part = xzalloc(sizeof(struct partition));
|
||||
size_t size = 0;
|
||||
|
||||
part->offset = offset;
|
||||
part->physdev = dev;
|
||||
part->num = num;
|
||||
part->device.map_base = dev->map_base + offset;
|
||||
part->device.type_data = part;
|
||||
part->device.type = DEVICE_TYPE_PARTITION;
|
||||
if (mtd_part_do_parse_one(devname, endp, &endp, offset, devsize, &size))
|
||||
return 1;
|
||||
|
||||
if (mtd_part_do_parse_one(part, endp, &endp))
|
||||
goto free_out;
|
||||
|
||||
if (dev_check_fixed(dev, part))
|
||||
goto free_out;
|
||||
|
||||
sprintf(part->device.id, "%s.%s", dev->id, part->name);
|
||||
if (register_device(&part->device))
|
||||
goto free_out;
|
||||
|
||||
dev_add_child(dev, &part->device);
|
||||
|
||||
offset += part->device.size;
|
||||
num++;
|
||||
offset += size;
|
||||
|
||||
if (!*endp)
|
||||
break;
|
||||
|
||||
if (*endp != ',') {
|
||||
printf("parse error\n");
|
||||
goto err_out;
|
||||
return 1;
|
||||
}
|
||||
endp++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_out:
|
||||
free(part);
|
||||
err_out:
|
||||
dev_del_partitions(dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const __maybe_unused char cmd_addpart_help[] =
|
||||
|
@ -275,38 +185,33 @@ U_BOOT_CMD_END
|
|||
|
||||
static int do_delpart(cmd_tbl_t * cmdtp, int argc, char *argv[])
|
||||
{
|
||||
struct device_d *dev;
|
||||
int i, err;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
for (i = 1; i < argc; i++) {
|
||||
err = devfs_del_partition(basename(argv[i]));
|
||||
if (err) {
|
||||
printf("cannot delete %s: %s\n", argv[i], strerror(-err));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev = get_device_by_path(argv[1]);
|
||||
if (!dev) {
|
||||
printf("no such device: %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev_del_partitions(dev);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const __maybe_unused char cmd_delpart_help[] =
|
||||
"Usage: delpart <device>\n"
|
||||
"Usage: delpart FILE...\n"
|
||||
"Delete partitions previously added to a device with addpart.\n";
|
||||
|
||||
U_BOOT_CMD_START(delpart)
|
||||
.maxargs = 2,
|
||||
.maxargs = CONFIG_MAXARGS,
|
||||
.cmd = do_delpart,
|
||||
.usage = "delete a partition table from a device",
|
||||
.usage = "delete partition(s)",
|
||||
U_BOOT_CMD_HELP(cmd_delpart_help)
|
||||
U_BOOT_CMD_END
|
||||
|
||||
/** @page delpart_command delpart Delete a partition
|
||||
*
|
||||
* Usage is: delpart \<device>
|
||||
* Usage is: delpart \<partions>
|
||||
*
|
||||
* Delete a partition previously added to a device with addpart.
|
||||
*/
|
||||
|
|
|
@ -12,7 +12,6 @@ obj-y += clock.o
|
|||
obj-y += command.o
|
||||
obj-$(CONFIG_CONSOLE_FULL) += console.o
|
||||
obj-$(CONFIG_CONSOLE_SIMPLE) += console_simple.o
|
||||
obj-$(CONFIG_PARTITION) += partition.o
|
||||
obj-y += env.o
|
||||
obj-y += startup.o
|
||||
obj-y += misc.o
|
||||
|
|
|
@ -1,358 +0,0 @@
|
|||
/*
|
||||
* (C) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program 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 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Partition handling on top of devices
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <init.h>
|
||||
#include <driver.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <partition.h>
|
||||
#include <xfuncs.h>
|
||||
#include <ioctl.h>
|
||||
#include <nand.h>
|
||||
#include <linux/mtd/mtd-abi.h>
|
||||
|
||||
/**
|
||||
* Add one partition on top of a device, as a device.
|
||||
* @param[in] dev The device to add a partition on
|
||||
* @param[in] offset Start offset of the partition inside the whole device
|
||||
* @param[in] size Size of the new partition
|
||||
* @param[in] flags FIXME
|
||||
* @param[in] name Partition name (can be obtained with devinfo command)
|
||||
* @return The device representing the new partition.
|
||||
*/
|
||||
struct device_d *dev_add_partition(struct device_d *dev, unsigned long offset,
|
||||
size_t size, int flags, const char *name)
|
||||
{
|
||||
struct partition *part;
|
||||
|
||||
if (offset + size > dev->size)
|
||||
return NULL;
|
||||
|
||||
part = xzalloc(sizeof(struct partition));
|
||||
|
||||
strcpy(part->device.name, "partition");
|
||||
part->device.map_base = dev->map_base + offset;
|
||||
part->device.size = size;
|
||||
part->device.type_data = part;
|
||||
part->device.type = DEVICE_TYPE_PARTITION;
|
||||
get_free_deviceid(part->device.id, name);
|
||||
|
||||
part->offset = offset;
|
||||
part->physdev = dev;
|
||||
part->flags = flags;
|
||||
|
||||
register_device(&part->device);
|
||||
dev_add_child(dev, &part->device);
|
||||
|
||||
if (part->device.driver)
|
||||
return &part->device;
|
||||
|
||||
unregister_device(&part->device);
|
||||
free(part);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase partition content.
|
||||
* @param[in] dev The partition info as a device
|
||||
* @param[in] count Length in bytes to erase
|
||||
* @param[in] offset Start offset within the partition
|
||||
* @return -1 if no erase feature for this device is available, anything else
|
||||
* the erase function returns.
|
||||
*/
|
||||
static int part_erase(struct device_d *dev, size_t count, unsigned long offset)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
if (part->flags & PARTITION_READONLY)
|
||||
return -EROFS;
|
||||
|
||||
return dev_erase(part->physdev, count, offset + part->offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protecting a partition.
|
||||
* @param[in] dev The partition info as a device
|
||||
* @param[in] count Length in bytes to protect
|
||||
* @param[in] offset Start offset within the partition
|
||||
* @param[in] prot FIXME
|
||||
* @return -1 if FIXME.
|
||||
*/
|
||||
static int part_protect(struct device_d *dev, size_t count, unsigned long offset, int prot)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
return dev_protect(part->physdev, count, offset + part->offset, prot);
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME.
|
||||
* @param[in] dev The partition info as a device
|
||||
* @param[in] map FXIME
|
||||
* @param[in] flags FIXME
|
||||
* @return -1 if FIXME.
|
||||
*/
|
||||
static int part_memmap(struct device_d *dev, void **map, int flags)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
int ret;
|
||||
|
||||
if (part->physdev->driver->memmap) {
|
||||
ret = part->physdev->driver->memmap(part->physdev, map, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
*map = (void *)((unsigned long)*map + part->offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME.
|
||||
* @param[in] dev The partition info as a device
|
||||
* @param[in] buf FXIME
|
||||
* @param[in] count FXIME
|
||||
* @param[in] offset FXIME
|
||||
* @param[in] flags FIXME
|
||||
* @return FIXME.
|
||||
*/
|
||||
static ssize_t part_read(struct device_d *dev, void *buf, size_t count,
|
||||
unsigned long offset, ulong flags)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
return dev_read(part->physdev, buf, count, offset + part->offset, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME.
|
||||
* @param[in] dev The partition info as a device
|
||||
* @param[in] buf FXIME
|
||||
* @param[in] count FXIME
|
||||
* @param[in] offset FXIME
|
||||
* @param[in] flags FIXME
|
||||
* @return FIXME.
|
||||
*/
|
||||
static ssize_t part_write(struct device_d *dev, const void *buf, size_t count,
|
||||
unsigned long offset, ulong flags)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
if (part->flags & PARTITION_READONLY)
|
||||
return -EROFS;
|
||||
else
|
||||
return dev_write(part->physdev, buf, count, offset + part->offset, flags);
|
||||
}
|
||||
|
||||
static off_t part_lseek(struct device_d *dev, off_t ofs)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
return dev_lseek(part->physdev, ofs);
|
||||
}
|
||||
|
||||
static int part_open(struct device_d *dev, struct filep *f)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
return dev_open(part->physdev, f);
|
||||
}
|
||||
|
||||
static int part_close(struct device_d *dev, struct filep *f)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
|
||||
return dev_close(part->physdev, f);
|
||||
}
|
||||
|
||||
static int part_ioctl(struct device_d *dev, int request,
|
||||
void *buf)
|
||||
{
|
||||
struct partition *part = dev->type_data;
|
||||
off_t offset;
|
||||
|
||||
switch (request) {
|
||||
case MEMSETBADBLOCK:
|
||||
case MEMGETBADBLOCK:
|
||||
offset = (off_t)buf;
|
||||
offset += part->offset;
|
||||
return dev_ioctl(part->physdev, request, (void *)offset);
|
||||
case MEMGETINFO:
|
||||
return dev_ioctl(part->physdev, request, buf);
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME.
|
||||
* @param[in] dev The partition info as a device
|
||||
* @return FIXME.
|
||||
*/
|
||||
static int part_probe(struct device_d *dev)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
struct partition *part = dev->type_data;
|
||||
#endif
|
||||
|
||||
debug("registering partition %s on device %s (size=0x%08x, name=%s)\n",
|
||||
dev->id, part->physdev->id, dev->size, part->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME.
|
||||
* @param[in] dev The partition info as a device
|
||||
*/
|
||||
static void part_remove(struct device_d *dev)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition driver description
|
||||
*/
|
||||
struct driver_d part_driver = {
|
||||
.name = "partition",
|
||||
.probe = part_probe,
|
||||
.remove = part_remove,
|
||||
.open = part_open,
|
||||
.close = part_close,
|
||||
.ioctl = part_ioctl,
|
||||
.read = part_read,
|
||||
.write = part_write,
|
||||
.lseek = part_lseek,
|
||||
.erase = part_erase,
|
||||
.protect= part_protect,
|
||||
.memmap = part_memmap,
|
||||
.type = DEVICE_TYPE_PARTITION,
|
||||
};
|
||||
|
||||
static int partition_init(void)
|
||||
{
|
||||
return register_driver(&part_driver);
|
||||
}
|
||||
|
||||
device_initcall(partition_init);
|
||||
|
||||
/**
|
||||
@page partitions Partition Handling
|
||||
|
||||
Partitions are runtime informartion only, not permanent. So they must be set
|
||||
everytime the system starts. The required command can be embedded into the
|
||||
default environment.
|
||||
|
||||
@note Partitions defined in this way are intended to be used with the kernel
|
||||
command line partition parsing feature. In Uboot2 these types of partitions are
|
||||
handled in the same way as every other device.
|
||||
|
||||
@par The addpart command
|
||||
|
||||
What we want:
|
||||
|
||||
@verbatim
|
||||
device nor0
|
||||
|--- partition 0
|
||||
|--- partition 1
|
||||
|--- partition 2
|
||||
|--- partition 3
|
||||
`--- partition 4
|
||||
@endverbatim
|
||||
|
||||
How to get:
|
||||
|
||||
@verbatim
|
||||
$ addpart /dev/nor0 256k(uboot),128k(env),256k(bla),1024k(blubb),2048k(friesel)
|
||||
$ devinfo
|
||||
|---nor0.uboot
|
||||
|---nor0.env
|
||||
|---nor0.bla
|
||||
|---nor0.blubb
|
||||
|---nor0.friesel
|
||||
@endverbatim
|
||||
|
||||
@par Partitions with sub partitions:
|
||||
|
||||
Partitions are based on devices. And partitions will result into devices. So
|
||||
there is a way to create sub partitions on partitions.
|
||||
|
||||
What we want:
|
||||
|
||||
@verbatim
|
||||
device nor0
|
||||
|--- partition 0
|
||||
|--- partition 1
|
||||
|--- partition 2
|
||||
|--- partition 3
|
||||
`--- partition 4
|
||||
|--- partition 0
|
||||
`--- partition 1
|
||||
@endverbatim
|
||||
|
||||
How to get:
|
||||
|
||||
@verbatim
|
||||
$ addpart /dev/nor0 256k(uboot),128k(env),256k(bla),1M(blubb),2048k(friesel)
|
||||
$ devinfo
|
||||
|---nor0.uboot
|
||||
|---nor0.env
|
||||
|---nor0.bla
|
||||
|---nor0.blubb
|
||||
|---nor0.friesel
|
||||
|
||||
$ addpart /dev/nor0.friesel 1024(fussel),1024k(boerks)
|
||||
$ devinfo
|
||||
|---nor0.uboot
|
||||
|---nor0.env
|
||||
|---nor0.bla
|
||||
|---nor0.blubb
|
||||
|---nor0.friesel
|
||||
|---nor0.friesel.fussel
|
||||
`---nor0.friesel.boerks
|
||||
@endverbatim
|
||||
|
||||
@par Forwarding partitions to the kernel:
|
||||
|
||||
@verbatim
|
||||
$ device="nor0"
|
||||
$ partitions="256k(uboot),128k(env),256k(bla),1024k(blubb),2048k(friesel)"
|
||||
$ addpart /dev/$device:$partitions
|
||||
@endverbatim
|
||||
|
||||
@par Removing partitions:
|
||||
|
||||
As partitions are a logically information only, they can be removed from a
|
||||
device at runtime. You can't remove a single partition within others on the
|
||||
same device. Only all partitions on the given device can be removed with this
|
||||
command.
|
||||
|
||||
As sub partitions occure as devices you also can remove sub partitions from
|
||||
their parent in this way. Partitions cannot be removed as long as they are
|
||||
mounted or have subpartitions.
|
||||
|
||||
*/
|
|
@ -77,9 +77,13 @@ void early_init (void)
|
|||
#ifdef CONFIG_DEFAULT_ENVIRONMENT
|
||||
#include <uboot_default_env.h>
|
||||
|
||||
static struct memory_platform_data default_env_platform_data = {
|
||||
.name = "defaultenv",
|
||||
};
|
||||
|
||||
static struct device_d default_env_dev = {
|
||||
.name = "rom",
|
||||
.id = "defaultenv",
|
||||
.name = "mem",
|
||||
.platform_data = &default_env_platform_data,
|
||||
};
|
||||
|
||||
static void register_default_env(void)
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
@ -31,9 +30,9 @@
|
|||
#include <ioctl.h>
|
||||
#include <nand.h>
|
||||
|
||||
static ssize_t nand_read(struct device_d *dev, void* buf, size_t count, ulong offset, ulong flags)
|
||||
static ssize_t nand_read(struct cdev *cdev, void* buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
struct mtd_info *info = dev->priv;
|
||||
struct mtd_info *info = cdev->priv;
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
|
@ -41,16 +40,18 @@ static ssize_t nand_read(struct device_d *dev, void* buf, size_t count, ulong o
|
|||
|
||||
ret = info->read(info, offset, count, &retlen, buf);
|
||||
|
||||
if(ret)
|
||||
if(ret) {
|
||||
printf("err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
#define NOTALIGNED(x) (x & (info->writesize - 1)) != 0
|
||||
|
||||
static ssize_t nand_write(struct device_d* dev, const void* buf, size_t _count, ulong offset, ulong flags)
|
||||
static ssize_t nand_write(struct cdev* cdev, const void *buf, size_t _count, ulong offset, ulong flags)
|
||||
{
|
||||
struct mtd_info *info = dev->priv;
|
||||
struct mtd_info *info = cdev->priv;
|
||||
size_t retlen, now;
|
||||
int ret;
|
||||
void *wrbuf = NULL;
|
||||
|
@ -86,9 +87,9 @@ out:
|
|||
return ret ? ret : _count;
|
||||
}
|
||||
|
||||
static int nand_ioctl(struct device_d *dev, int request, void *buf)
|
||||
static int nand_ioctl(struct cdev *cdev, int request, void *buf)
|
||||
{
|
||||
struct mtd_info *info = dev->priv;
|
||||
struct mtd_info *info = cdev->priv;
|
||||
struct mtd_info_user *user = buf;
|
||||
|
||||
switch (request) {
|
||||
|
@ -113,9 +114,9 @@ static int nand_ioctl(struct device_d *dev, int request, void *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t nand_erase(struct device_d *dev, size_t count, unsigned long offset)
|
||||
static ssize_t nand_erase(struct cdev *cdev, size_t count, unsigned long offset)
|
||||
{
|
||||
struct mtd_info *info = dev->priv;
|
||||
struct mtd_info *info = cdev->priv;
|
||||
struct erase_info erase;
|
||||
int ret;
|
||||
|
||||
|
@ -143,6 +144,14 @@ static ssize_t nand_erase(struct device_d *dev, size_t count, unsigned long offs
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations nand_ops = {
|
||||
.read = nand_read,
|
||||
.write = nand_write,
|
||||
.ioctl = nand_ioctl,
|
||||
.lseek = dev_lseek_default,
|
||||
.erase = nand_erase,
|
||||
};
|
||||
|
||||
static int nand_device_probe(struct device_d *dev)
|
||||
{
|
||||
return 0;
|
||||
|
@ -151,13 +160,6 @@ static int nand_device_probe(struct device_d *dev)
|
|||
static struct driver_d nand_device_driver = {
|
||||
.name = "nand_device",
|
||||
.probe = nand_device_probe,
|
||||
.read = nand_read,
|
||||
.write = nand_write,
|
||||
.ioctl = nand_ioctl,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.lseek = dev_lseek_default,
|
||||
.erase = nand_erase,
|
||||
.type = DEVICE_TYPE_NAND,
|
||||
};
|
||||
|
||||
|
@ -170,36 +172,27 @@ static int nand_init(void)
|
|||
|
||||
device_initcall(nand_init);
|
||||
|
||||
int add_mtd_device(struct mtd_info *mtd) {
|
||||
struct device_d *dev;
|
||||
int ret;
|
||||
int add_mtd_device(struct mtd_info *mtd)
|
||||
{
|
||||
struct device_d *dev = &mtd->class_dev;
|
||||
char name[MAX_DRIVER_NAME];
|
||||
|
||||
dev = xzalloc(sizeof(*dev));
|
||||
get_free_deviceid(name, "nand");
|
||||
|
||||
strcpy(dev->name, "nand_device");
|
||||
get_free_deviceid(dev->id, "nand");
|
||||
mtd->cdev.ops = &nand_ops;
|
||||
mtd->cdev.size = mtd->size;
|
||||
mtd->cdev.name = strdup(name);
|
||||
mtd->cdev.dev = dev;
|
||||
mtd->cdev.priv = mtd;
|
||||
|
||||
dev->size = mtd->size;
|
||||
dev->type = DEVICE_TYPE_NAND;
|
||||
dev->priv = mtd;
|
||||
mtd->dev = dev;
|
||||
|
||||
ret = register_device(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
devfs_create(&mtd->cdev);
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
free(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int del_mtd_device (struct mtd_info *mtd)
|
||||
{
|
||||
unregister_device(mtd->dev);
|
||||
free(mtd->dev);
|
||||
|
||||
unregister_device(&mtd->class_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <init.h>
|
||||
#include <miiphy.h>
|
||||
#include <clock.h>
|
||||
#include <net.h>
|
||||
|
||||
int miiphy_restart_aneg(struct miiphy_device *mdev)
|
||||
{
|
||||
|
@ -84,12 +85,12 @@ int miiphy_wait_aneg(struct miiphy_device *mdev)
|
|||
start = get_time_ns();
|
||||
do {
|
||||
if (is_timeout(start, 5 * SECOND)) {
|
||||
printf("%s: Autonegotiation timeout\n", mdev->dev.id);
|
||||
printf("%s: Autonegotiation timeout\n", mdev->cdev.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mdev->read(mdev, mdev->address, MII_BMSR, &status)) {
|
||||
printf("%s: Autonegotiation failed. status: 0x%04x\n", mdev->dev.id, status);
|
||||
printf("%s: Autonegotiation failed. status: 0x%04x\n", mdev->cdev.name, status);
|
||||
return -1;
|
||||
}
|
||||
} while (!(status & BMSR_LSTATUS));
|
||||
|
@ -115,7 +116,7 @@ int miiphy_print_status(struct miiphy_device *mdev)
|
|||
if (mdev->read(mdev, mdev->address, MII_LPA, &lpa) != 0)
|
||||
goto err_out;
|
||||
|
||||
printf("%s: Link is %s", mdev->dev.id,
|
||||
printf("%s: Link is %s", mdev->cdev.name,
|
||||
bmsr & BMSR_LSTATUS ? "up" : "down");
|
||||
|
||||
if (bmcr & BMCR_ANENABLE) {
|
||||
|
@ -130,15 +131,15 @@ int miiphy_print_status(struct miiphy_device *mdev)
|
|||
|
||||
return 0;
|
||||
err_out:
|
||||
printf("%s: failed to read\n", mdev->dev.id);
|
||||
printf("%s: failed to read\n", mdev->cdev.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t miiphy_read(struct device_d *dev, void *_buf, size_t count, ulong offset, ulong flags)
|
||||
static ssize_t miiphy_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
int i = count;
|
||||
uint16_t *buf = _buf;
|
||||
struct miiphy_device *mdev = dev->priv;
|
||||
struct miiphy_device *mdev = cdev->priv;
|
||||
|
||||
while (i > 1) {
|
||||
mdev->read(mdev, mdev->address, offset, buf);
|
||||
|
@ -150,11 +151,11 @@ static ssize_t miiphy_read(struct device_d *dev, void *_buf, size_t count, ulong
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t miiphy_write(struct device_d *dev, const void *_buf, size_t count, ulong offset, ulong flags)
|
||||
static ssize_t miiphy_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
int i = count;
|
||||
const uint16_t *buf = _buf;
|
||||
struct miiphy_device *mdev = dev->priv;
|
||||
struct miiphy_device *mdev = cdev->priv;
|
||||
|
||||
while (i > 1) {
|
||||
mdev->write(mdev, mdev->address, offset, *buf);
|
||||
|
@ -166,41 +167,36 @@ static ssize_t miiphy_write(struct device_d *dev, const void *_buf, size_t count
|
|||
return count;
|
||||
}
|
||||
|
||||
static struct file_operations miiphy_ops = {
|
||||
.read = miiphy_read,
|
||||
.write = miiphy_write,
|
||||
};
|
||||
|
||||
static int miiphy_probe(struct device_d *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
struct miiphy_device *mdev = dev->priv;
|
||||
char name[MAX_DRIVER_NAME];
|
||||
|
||||
static void miiphy_remove(struct device_d *dev)
|
||||
{
|
||||
get_free_deviceid(name, "phy");
|
||||
mdev->cdev.name = strdup(name);
|
||||
mdev->cdev.size = 32;
|
||||
mdev->cdev.ops = &miiphy_ops;
|
||||
mdev->cdev.priv = mdev;
|
||||
devfs_create(&mdev->cdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int miiphy_register(struct miiphy_device *mdev)
|
||||
{
|
||||
strcpy(mdev->dev.name, "miiphy");
|
||||
get_free_deviceid(mdev->dev.id, "phy");
|
||||
mdev->dev.type = DEVICE_TYPE_MIIPHY;
|
||||
mdev->dev.priv = mdev;
|
||||
mdev->dev.size = 32;
|
||||
strcpy(mdev->dev.name, "miiphy");
|
||||
|
||||
return register_device(&mdev->dev);
|
||||
}
|
||||
|
||||
void miiphy_unregister(struct miiphy_device *mdev)
|
||||
{
|
||||
unregister_device(&mdev->dev);
|
||||
}
|
||||
|
||||
static struct driver_d miiphy_drv = {
|
||||
.name = "miiphy",
|
||||
.probe = miiphy_probe,
|
||||
.remove = miiphy_remove,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.read = miiphy_read,
|
||||
.write = miiphy_write,
|
||||
.lseek = dev_lseek_default,
|
||||
.type = DEVICE_TYPE_MIIPHY,
|
||||
};
|
||||
|
||||
static int miiphy_init(void)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <init.h>
|
||||
#include <malloc.h>
|
||||
#include <cfi_flash.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define FLASH_CMD_CFI 0x98
|
||||
#define FLASH_CMD_READ_ID 0x90
|
||||
|
@ -352,16 +353,16 @@ static int flash_erase_one (flash_info_t * info, long sect)
|
|||
return rcode;
|
||||
}
|
||||
|
||||
static int cfi_erase(struct device_d *dev, size_t count, unsigned long offset)
|
||||
static int cfi_erase(struct cdev *cdev, size_t count, unsigned long offset)
|
||||
{
|
||||
flash_info_t *finfo = (flash_info_t *)dev->priv;
|
||||
flash_info_t *finfo = (flash_info_t *)cdev->priv;
|
||||
unsigned long start, end;
|
||||
int i, ret = 0;
|
||||
|
||||
debug("%s: erase 0x%08x (size %d)\n", __FUNCTION__, offset, count);
|
||||
|
||||
start = flash_find_sector(finfo, dev->map_base + offset);
|
||||
end = flash_find_sector(finfo, dev->map_base + offset + count - 1);
|
||||
start = flash_find_sector(finfo, cdev->dev->map_base + offset);
|
||||
end = flash_find_sector(finfo, cdev->dev->map_base + offset + count - 1);
|
||||
|
||||
for (i = start; i <= end; i++) {
|
||||
ret = flash_erase_one (finfo, i);
|
||||
|
@ -373,16 +374,16 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int cfi_protect(struct device_d *dev, size_t count, unsigned long offset, int prot)
|
||||
static int cfi_protect(struct cdev *cdev, size_t count, unsigned long offset, int prot)
|
||||
{
|
||||
flash_info_t *finfo = (flash_info_t *)dev->priv;
|
||||
flash_info_t *finfo = (flash_info_t *)cdev->priv;
|
||||
unsigned long start, end;
|
||||
int i, ret = 0;
|
||||
|
||||
debug("%s: protect 0x%08x (size %d)\n", __FUNCTION__, offset, count);
|
||||
|
||||
start = flash_find_sector(finfo, dev->map_base + offset);
|
||||
end = flash_find_sector(finfo, dev->map_base + offset + count - 1);
|
||||
start = flash_find_sector(finfo, cdev->dev->map_base + offset);
|
||||
end = flash_find_sector(finfo, cdev->dev->map_base + offset + count - 1);
|
||||
|
||||
for (i = start; i <= end; i++) {
|
||||
ret = flash_real_protect (finfo, i, prot);
|
||||
|
@ -394,14 +395,14 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t cfi_write(struct device_d* dev, const void* buf, size_t count, unsigned long offset, ulong flags)
|
||||
static ssize_t cfi_write(struct cdev *cdev, const void* buf, size_t count, unsigned long offset, ulong flags)
|
||||
{
|
||||
flash_info_t *finfo = (flash_info_t *)dev->priv;
|
||||
flash_info_t *finfo = (flash_info_t *)cdev->priv;
|
||||
int ret;
|
||||
|
||||
debug("cfi_write: buf=0x%08x addr=0x%08x count=0x%08x\n",buf, dev->map_base + offset, count);
|
||||
debug("cfi_write: buf=0x%08x addr=0x%08x count=0x%08x\n",buf, cdev->dev->map_base + offset, count);
|
||||
|
||||
ret = write_buff (finfo, buf, dev->map_base + offset, count);
|
||||
ret = write_buff (finfo, buf, cdev->dev->map_base + offset, count);
|
||||
return ret == 0 ? count : -1;
|
||||
}
|
||||
|
||||
|
@ -1437,43 +1438,48 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, const uchar *
|
|||
}
|
||||
#endif /* CONFIG_CFI_BUFFER_WRITE */
|
||||
|
||||
struct file_operations cfi_ops = {
|
||||
.read = mem_read,
|
||||
.write = cfi_write,
|
||||
.lseek = dev_lseek_default,
|
||||
.erase = cfi_erase,
|
||||
.protect = cfi_protect,
|
||||
.memmap = generic_memmap_ro,
|
||||
};
|
||||
|
||||
static int cfi_probe (struct device_d *dev)
|
||||
{
|
||||
unsigned long size = 0;
|
||||
flash_info_t *info = malloc(sizeof(flash_info_t));
|
||||
flash_info_t *info = xzalloc(sizeof(flash_info_t));
|
||||
char name[MAX_DRIVER_NAME];
|
||||
|
||||
dev->priv = (void *)info;
|
||||
|
||||
debug ("cfi_probe: %s base: 0x%08x size: 0x%08x\n", dev->name, dev->map_base, dev->size);
|
||||
printf("cfi_probe: %s base: 0x%08x size: 0x%08x\n", dev->name, dev->map_base, dev->size);
|
||||
|
||||
/* Init: no FLASHes known */
|
||||
info->flash_id = FLASH_UNKNOWN;
|
||||
size += info->size = flash_get_size(info, dev->map_base);
|
||||
|
||||
if (dev->size > size) {
|
||||
dev_dbg(dev, "limiting size from 0x%08x to 0x%08x\n", dev->size, size);
|
||||
dev->size = size;
|
||||
}
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
debug ("## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n",
|
||||
printf ("## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n",
|
||||
dev->map_base, info->size, info->size << 20);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
get_free_deviceid(name, "nor");
|
||||
info->cdev.name = strdup(name);
|
||||
info->cdev.size = info->size;
|
||||
info->cdev.dev = dev;
|
||||
info->cdev.ops = &cfi_ops;
|
||||
info->cdev.priv = info;
|
||||
devfs_create(&info->cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct driver_d cfi_driver = {
|
||||
.name = "cfi_flash",
|
||||
.probe = cfi_probe,
|
||||
.read = mem_read,
|
||||
.write = cfi_write,
|
||||
.lseek = dev_lseek_default,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.erase = cfi_erase,
|
||||
.protect= cfi_protect,
|
||||
.memmap = generic_memmap_ro,
|
||||
.info = cfi_info,
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <malloc.h>
|
||||
#include <cfi_flash_new.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* This file implements a Common Flash Interface (CFI) driver for U-Boot.
|
||||
|
@ -348,8 +349,8 @@ static ulong flash_get_size (flash_info_t *info, ulong base)
|
|||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("unsopported vendor\n");
|
||||
break;
|
||||
printf("unsupported vendor\n");
|
||||
return 0;
|
||||
}
|
||||
info->cfi_cmd_set->flash_read_jedec_ids (info);
|
||||
flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
|
||||
|
@ -505,16 +506,16 @@ flash_sect_t find_sector (flash_info_t * info, ulong addr)
|
|||
return sector;
|
||||
}
|
||||
|
||||
static int cfi_erase(struct device_d *dev, size_t count, unsigned long offset)
|
||||
static int cfi_erase(struct cdev *cdev, size_t count, unsigned long offset)
|
||||
{
|
||||
flash_info_t *finfo = (flash_info_t *)dev->priv;
|
||||
flash_info_t *finfo = (flash_info_t *)cdev->priv;
|
||||
unsigned long start, end;
|
||||
int i, ret = 0;
|
||||
|
||||
printf("%s: erase 0x%08x (size %d)\n", __FUNCTION__, offset, count);
|
||||
|
||||
start = find_sector(finfo, dev->map_base + offset);
|
||||
end = find_sector(finfo, dev->map_base + offset + count - 1);
|
||||
start = find_sector(finfo, cdev->dev->map_base + offset);
|
||||
end = find_sector(finfo, cdev->dev->map_base + offset + count - 1);
|
||||
|
||||
for (i = start; i <= end; i++) {
|
||||
ret = finfo->cfi_cmd_set->flash_erase_one(finfo, i);
|
||||
|
@ -658,16 +659,16 @@ static int flash_real_protect (flash_info_t * info, long sector, int prot)
|
|||
return retcode;
|
||||
}
|
||||
|
||||
static int cfi_protect(struct device_d *dev, size_t count, unsigned long offset, int prot)
|
||||
static int cfi_protect(struct cdev *cdev, size_t count, unsigned long offset, int prot)
|
||||
{
|
||||
flash_info_t *finfo = (flash_info_t *)dev->priv;
|
||||
flash_info_t *finfo = (flash_info_t *)cdev->priv;
|
||||
unsigned long start, end;
|
||||
int i, ret = 0;
|
||||
|
||||
debug("%s: protect 0x%08x (size %d)\n", __FUNCTION__, offset, count);
|
||||
printf("%s: protect 0x%08x (size %d)\n", __FUNCTION__, cdev->dev->map_base + offset, count);
|
||||
|
||||
start = find_sector(finfo, dev->map_base + offset);
|
||||
end = find_sector(finfo, dev->map_base + offset + count - 1);
|
||||
start = find_sector(finfo, cdev->dev->map_base + offset);
|
||||
end = find_sector(finfo, cdev->dev->map_base + offset + count - 1);
|
||||
|
||||
for (i = start; i <= end; i++) {
|
||||
ret = flash_real_protect (finfo, i, prot);
|
||||
|
@ -679,14 +680,14 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t cfi_write(struct device_d* dev, const void* buf, size_t count, unsigned long offset, ulong flags)
|
||||
static ssize_t cfi_write(struct cdev *cdev, const void *buf, size_t count, unsigned long offset, ulong flags)
|
||||
{
|
||||
flash_info_t *finfo = (flash_info_t *)dev->priv;
|
||||
flash_info_t *finfo = (flash_info_t *)cdev->priv;
|
||||
int ret;
|
||||
|
||||
debug("cfi_write: buf=0x%08x addr=0x%08x count=0x%08x\n",buf, dev->map_base + offset, count);
|
||||
debug("cfi_write: buf=0x%08x addr=0x%08x count=0x%08x\n",buf, cdev->dev->map_base + offset, count);
|
||||
|
||||
ret = write_buff (finfo, buf, dev->map_base + offset, count);
|
||||
ret = write_buff (finfo, buf, cdev->dev->map_base + offset, count);
|
||||
return ret == 0 ? count : -1;
|
||||
}
|
||||
|
||||
|
@ -934,10 +935,20 @@ int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)
|
|||
return retval;
|
||||
}
|
||||
|
||||
struct file_operations cfi_ops = {
|
||||
.read = mem_read,
|
||||
.write = cfi_write,
|
||||
.lseek = dev_lseek_default,
|
||||
.erase = cfi_erase,
|
||||
.protect = cfi_protect,
|
||||
.memmap = generic_memmap_ro,
|
||||
};
|
||||
|
||||
static int cfi_probe (struct device_d *dev)
|
||||
{
|
||||
unsigned long size = 0;
|
||||
flash_info_t *info = malloc(sizeof(flash_info_t));
|
||||
flash_info_t *info = xzalloc(sizeof(flash_info_t));
|
||||
char name[MAX_DRIVER_NAME];
|
||||
|
||||
dev->priv = (void *)info;
|
||||
|
||||
|
@ -953,27 +964,26 @@ static int cfi_probe (struct device_d *dev)
|
|||
}
|
||||
|
||||
if (info->flash_id == FLASH_UNKNOWN) {
|
||||
#ifndef CFG_FLASH_QUIET_TEST
|
||||
printf ("## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n",
|
||||
dev->map_base, info->size, info->size << 20);
|
||||
#endif /* CFG_FLASH_QUIET_TEST */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
get_free_deviceid(name, "nor");
|
||||
info->cdev.name = strdup(name);
|
||||
info->cdev.size = info->size;
|
||||
info->cdev.dev = dev;
|
||||
info->cdev.ops = &cfi_ops;
|
||||
info->cdev.priv = info;
|
||||
devfs_create(&info->cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct driver_d cfi_driver = {
|
||||
.name = "cfi_flash",
|
||||
.probe = cfi_probe,
|
||||
.read = mem_read,
|
||||
.write = cfi_write,
|
||||
.lseek = dev_lseek_default,
|
||||
.open = dev_open_default,
|
||||
.close = dev_close_default,
|
||||
.erase = cfi_erase,
|
||||
.info = cfi_info,
|
||||
.protect = cfi_protect,
|
||||
.memmap = generic_memmap_ro,
|
||||
};
|
||||
|
||||
static int cfi_init(void)
|
||||
|
|
|
@ -206,14 +206,17 @@ static int pmic_probe(struct device_d *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations pmic_fops = {
|
||||
.open = dev_open_default,
|
||||
.lseek = dev_lseek_default,
|
||||
.close = dev_close_default,
|
||||
.read = pmic_read,
|
||||
.write = pmic_write,
|
||||
};
|
||||
|
||||
static struct driver_d pmic_driver = {
|
||||
.name = "mc13783",
|
||||
.probe = pmic_probe,
|
||||
.open = dev_open_default,
|
||||
.lseek = dev_lseek_default,
|
||||
.close = dev_close_default,
|
||||
.read = pmic_read,
|
||||
.write = pmic_write,
|
||||
};
|
||||
|
||||
static int pmic_init(void)
|
||||
|
|
230
fs/devfs.c
230
fs/devfs.c
|
@ -29,27 +29,53 @@
|
|||
#include <errno.h>
|
||||
#include <xfuncs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <ioctl.h>
|
||||
#include <nand.h>
|
||||
#include <linux/mtd/mtd-abi.h>
|
||||
#include <partition.h>
|
||||
|
||||
static int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
|
||||
static LIST_HEAD(cdev_list);
|
||||
|
||||
struct cdev *cdev_by_name(const char *filename)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev;
|
||||
|
||||
return dev_read(dev, buf, size, f->pos, f->flags);
|
||||
list_for_each_entry(cdev, &cdev_list, list) {
|
||||
if (!strcmp(cdev->name, filename))
|
||||
return cdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t size)
|
||||
int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev = f->inode;
|
||||
|
||||
return dev_write(dev, buf, size, f->pos, f->flags);
|
||||
if (!cdev->ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
return cdev->ops->read(cdev, buf, size,
|
||||
f->pos + cdev->offset, f->flags);
|
||||
}
|
||||
|
||||
static off_t devfs_lseek(struct device_d *_dev, FILE *f, off_t pos)
|
||||
int devfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t size)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
off_t ret;
|
||||
struct cdev *cdev = f->inode;
|
||||
|
||||
ret = dev_lseek(dev, pos);
|
||||
if (!cdev->ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
return cdev->ops->write(cdev, buf, size,
|
||||
f->pos + cdev->offset, f->flags);
|
||||
}
|
||||
|
||||
off_t devfs_lseek(struct device_d *_dev, FILE *f, off_t pos)
|
||||
{
|
||||
struct cdev *cdev = f->inode;
|
||||
off_t ret = -1;
|
||||
|
||||
if (cdev->ops->lseek)
|
||||
ret = cdev->ops->lseek(cdev, pos + cdev->offset);
|
||||
|
||||
if (ret != -1)
|
||||
f->pos = pos;
|
||||
|
@ -57,51 +83,100 @@ static off_t devfs_lseek(struct device_d *_dev, FILE *f, off_t pos)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned long offset)
|
||||
int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned long offset)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev = f->inode;
|
||||
|
||||
return dev_erase(dev, count, offset);
|
||||
if (!cdev->ops->erase)
|
||||
return -ENOSYS;
|
||||
|
||||
return cdev->ops->erase(cdev, count, offset + cdev->offset);
|
||||
}
|
||||
|
||||
static int devfs_protect(struct device_d *_dev, FILE *f, size_t count, unsigned long offset, int prot)
|
||||
int devfs_protect(struct device_d *_dev, FILE *f, size_t count, unsigned long offset, int prot)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev = f->inode;
|
||||
|
||||
return dev_protect(dev, count, offset, prot);
|
||||
if (!cdev->ops->protect)
|
||||
return -ENOSYS;
|
||||
|
||||
return cdev->ops->protect(cdev, count, offset + cdev->offset, prot);
|
||||
}
|
||||
|
||||
static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev = f->inode;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
return dev_memmap(dev, map, flags);
|
||||
if (!cdev->ops->memmap)
|
||||
return -EINVAL;
|
||||
|
||||
ret = cdev->ops->memmap(cdev, map, flags);
|
||||
|
||||
if (!ret)
|
||||
*map = (void *)((unsigned long)*map + cdev->offset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
|
||||
{
|
||||
struct device_d *dev = get_device_by_id(filename + 1);
|
||||
struct cdev *cdev;
|
||||
|
||||
if (!dev)
|
||||
cdev = cdev_by_name(filename + 1);
|
||||
|
||||
if (!cdev)
|
||||
return -ENOENT;
|
||||
|
||||
f->size = dev->size;
|
||||
f->inode = dev;
|
||||
return dev_open(dev, f);
|
||||
f->size = cdev->size;
|
||||
f->inode = cdev;
|
||||
|
||||
if (cdev->ops->open)
|
||||
return cdev->ops->open(cdev, f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int devfs_close(struct device_d *_dev, FILE *f)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev = f->inode;
|
||||
|
||||
return dev_close(dev, f);
|
||||
if (cdev->ops->close)
|
||||
return cdev->ops->close(cdev, f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int partition_ioctl(struct cdev *cdev, int request, void *buf)
|
||||
{
|
||||
size_t offset;
|
||||
|
||||
switch (request) {
|
||||
case MEMSETBADBLOCK:
|
||||
case MEMGETBADBLOCK:
|
||||
offset = (off_t)buf;
|
||||
offset += cdev->offset;
|
||||
return cdev->ops->ioctl(cdev, request, (void *)offset);
|
||||
case MEMGETINFO:
|
||||
return cdev->ops->ioctl(cdev, request, buf);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int devfs_ioctl(struct device_d *_dev, FILE *f, int request, void *buf)
|
||||
{
|
||||
struct device_d *dev = f->inode;
|
||||
struct cdev *cdev = f->inode;
|
||||
int ret = -EINVAL;
|
||||
|
||||
return dev_ioctl(dev, request, buf);
|
||||
if (!cdev->ops->ioctl)
|
||||
goto out;
|
||||
|
||||
if (cdev->flags & DEVFS_IS_PARTITION)
|
||||
ret = partition_ioctl(cdev, request, buf);
|
||||
else
|
||||
ret = cdev->ops->ioctl(cdev, request, buf);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int devfs_truncate(struct device_d *dev, FILE *f, ulong size)
|
||||
|
@ -117,26 +192,22 @@ static DIR* devfs_opendir(struct device_d *dev, const char *pathname)
|
|||
|
||||
dir = xzalloc(sizeof(DIR));
|
||||
|
||||
if (!list_empty(&device_list))
|
||||
dir->priv = list_first_entry(&device_list, struct device_d, list);
|
||||
if (!list_empty(&cdev_list))
|
||||
dir->priv = list_first_entry(&cdev_list, struct cdev, list);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static struct dirent* devfs_readdir(struct device_d *_dev, DIR *dir)
|
||||
{
|
||||
struct device_d *dev = dir->priv;
|
||||
struct cdev *cdev = dir->priv;
|
||||
|
||||
if (!dev)
|
||||
if (!cdev)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry_from(dev, &device_list, list) {
|
||||
if (!*dev->id)
|
||||
continue;
|
||||
if (!dev->driver)
|
||||
continue;
|
||||
strcpy(dir->d.d_name, dev->id);
|
||||
dir->priv = list_entry(dev->list.next, struct device_d, list);
|
||||
list_for_each_entry_from(cdev, &cdev_list, list) {
|
||||
strcpy(dir->d.d_name, cdev->name);
|
||||
dir->priv = list_entry(cdev->list.next, struct cdev, list);
|
||||
return &dir->d;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -150,20 +221,17 @@ static int devfs_closedir(struct device_d *dev, DIR *dir)
|
|||
|
||||
static int devfs_stat(struct device_d *_dev, const char *filename, struct stat *s)
|
||||
{
|
||||
struct device_d *dev;
|
||||
struct cdev *cdev;
|
||||
|
||||
dev = get_device_by_id(filename + 1);
|
||||
if (!dev)
|
||||
cdev = cdev_by_name(filename + 1);
|
||||
if (!cdev)
|
||||
return -ENOENT;
|
||||
|
||||
if (!dev->driver)
|
||||
return -ENXIO;
|
||||
|
||||
s->st_mode = S_IFCHR;
|
||||
s->st_size = dev->size;
|
||||
if (dev->driver->write)
|
||||
s->st_size = cdev->size;
|
||||
if (cdev->ops->write)
|
||||
s->st_mode |= S_IWUSR;
|
||||
if (dev->driver->read)
|
||||
if (cdev->ops->read)
|
||||
s->st_mode |= S_IRUSR;
|
||||
|
||||
return 0;
|
||||
|
@ -206,3 +274,71 @@ static int devfs_init(void)
|
|||
|
||||
device_initcall(devfs_init);
|
||||
|
||||
int devfs_create(struct cdev *new)
|
||||
{
|
||||
struct cdev *cdev;
|
||||
|
||||
cdev = cdev_by_name(new->name);
|
||||
if (cdev)
|
||||
return -EEXIST;
|
||||
|
||||
list_add_tail(&new->list, &cdev_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void devfs_remove(struct cdev *cdev)
|
||||
{
|
||||
list_del(&cdev->list);
|
||||
}
|
||||
|
||||
int devfs_add_partition(const char *devname, unsigned long offset, size_t size,
|
||||
int flags, const char *name)
|
||||
{
|
||||
struct cdev *cdev, *new;
|
||||
|
||||
cdev = cdev_by_name(name);
|
||||
if (cdev)
|
||||
return -EEXIST;
|
||||
|
||||
cdev = cdev_by_name(devname);
|
||||
if (!cdev)
|
||||
return -ENOENT;
|
||||
|
||||
if (offset + size > cdev->size)
|
||||
return -EINVAL;
|
||||
|
||||
new = xzalloc(sizeof (*new));
|
||||
new->name = strdup(name);
|
||||
new->ops = cdev->ops;
|
||||
new->priv = cdev->priv;
|
||||
new->size = size;
|
||||
new->offset = offset + cdev->offset;
|
||||
new->dev = cdev->dev;
|
||||
new->flags = flags | DEVFS_IS_PARTITION;
|
||||
|
||||
list_add_tail(&new->list, &cdev_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int devfs_del_partition(const char *name)
|
||||
{
|
||||
struct cdev *cdev;
|
||||
|
||||
cdev = cdev_by_name(name);
|
||||
if (!cdev)
|
||||
return -ENOENT;
|
||||
|
||||
if (!(cdev->flags & DEVFS_IS_PARTITION))
|
||||
return -EINVAL;
|
||||
if (cdev->flags & DEVFS_PARTITION_FIXED)
|
||||
return -EPERM;
|
||||
|
||||
devfs_remove(cdev);
|
||||
free(cdev->name);
|
||||
free(cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
27
fs/fs.c
27
fs/fs.c
|
@ -943,29 +943,34 @@ static void memcpy_sz(void *_dst, const void *_src, ulong count, ulong rwsize)
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t mem_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags)
|
||||
ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
ulong size;
|
||||
size = min(count, dev->size - offset);
|
||||
struct device_d *dev;
|
||||
|
||||
if (!cdev->dev)
|
||||
return -1;
|
||||
dev = cdev->dev;
|
||||
|
||||
size = min((ulong)count, dev->size - offset);
|
||||
debug("mem_read: dev->map_base: %p size: %d offset: %d\n",dev->map_base, size, offset);
|
||||
memcpy_sz(buf, (void *)(dev->map_base + offset), size, flags & O_RWSIZE_MASK);
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_read);
|
||||
|
||||
ssize_t mem_write(struct device_d *dev, const void *buf, size_t count, ulong offset, ulong flags)
|
||||
ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags)
|
||||
{
|
||||
ulong size;
|
||||
size = min(count, dev->size - offset);
|
||||
struct device_d *dev;
|
||||
|
||||
if (!cdev->dev)
|
||||
return -1;
|
||||
dev = cdev->dev;
|
||||
|
||||
size = min((ulong)count, dev->size - offset);
|
||||
memcpy_sz((void *)(dev->map_base + offset), buf, size, flags & O_RWSIZE_MASK);
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_write);
|
||||
|
||||
int mem_memmap(struct device_d *dev, void **map, int flags)
|
||||
{
|
||||
*map = (void *)dev->map_base;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mem_memmap);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
typedef struct {
|
||||
struct driver_d driver;
|
||||
struct cdev cdev;
|
||||
ulong size; /* total bank size in bytes */
|
||||
ushort sector_count; /* number of erase units */
|
||||
ulong flash_id; /* combined device & manufacturer code */
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct {
|
|||
ushort cfi_version; /* cfi version */
|
||||
ushort cfi_offset; /* offset for cfi query */
|
||||
struct cfi_cmd_set *cfi_cmd_set;
|
||||
struct cdev cdev;
|
||||
} flash_info_t;
|
||||
|
||||
struct cfi_cmd_set {
|
||||
|
|
|
@ -98,7 +98,6 @@ struct device_d {
|
|||
void *type_data; /*! In case this device is a specific device, this pointer
|
||||
* points to the type specific device, i.e. eth_device
|
||||
*/
|
||||
|
||||
struct driver_d *driver; /*! The driver for this device */
|
||||
|
||||
struct list_head list; /* The list of all devices */
|
||||
|
@ -133,22 +132,6 @@ struct driver_d {
|
|||
/*! Called if an instance of a device is gone. */
|
||||
void (*remove)(struct device_d *);
|
||||
|
||||
/*! Called in response of reading from this device. Required */
|
||||
ssize_t (*read) (struct device_d*, void* buf, size_t count, ulong offset, ulong flags);
|
||||
|
||||
/*! Called in response of write to this device. Required */
|
||||
ssize_t (*write) (struct device_d*, const void* buf, size_t count, ulong offset, ulong flags);
|
||||
|
||||
int (*ioctl) (struct device_d*, int, void *);
|
||||
|
||||
off_t (*lseek) (struct device_d*, off_t);
|
||||
int (*open) (struct device_d*, struct filep*);
|
||||
int (*close) (struct device_d*, struct filep*);
|
||||
|
||||
int (*erase) (struct device_d*, size_t count, unsigned long offset);
|
||||
int (*protect)(struct device_d*, size_t count, unsigned long offset, int prot);
|
||||
int (*memmap)(struct device_d*, void **map, int flags);
|
||||
|
||||
void (*info) (struct device_d *);
|
||||
void (*shortinfo) (struct device_d *);
|
||||
|
||||
|
@ -231,20 +214,14 @@ extern struct list_head driver_list;
|
|||
*/
|
||||
struct driver_d *get_driver_by_name(const char *name);
|
||||
|
||||
ssize_t dev_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags);
|
||||
ssize_t dev_write(struct device_d *dev, const void *buf, size_t count, ulong offset, ulong flags);
|
||||
int dev_open(struct device_d *dev, struct filep *);
|
||||
int dev_close(struct device_d *dev, struct filep *);
|
||||
int dev_ioctl(struct device_d *dev, int, void *);
|
||||
off_t dev_lseek(struct device_d *dev, off_t offset);
|
||||
int dev_erase(struct device_d *dev, size_t count, unsigned long offset);
|
||||
struct cdev;
|
||||
|
||||
int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot);
|
||||
int dev_memmap(struct device_d *dev, void **map, int flags);
|
||||
|
||||
/* These are used by drivers which work with direct memory accesses */
|
||||
ssize_t mem_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags);
|
||||
ssize_t mem_write(struct device_d *dev, const void *buf, size_t count, ulong offset, ulong flags);
|
||||
int mem_memmap(struct device_d *dev, void **map, int flags);
|
||||
ssize_t mem_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags);
|
||||
ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags);
|
||||
int mem_memmap(struct cdev *cdev, void **map, int flags);
|
||||
|
||||
/* Use this if you have nothing to do in your drivers probe function */
|
||||
int dummy_probe(struct device_d *);
|
||||
|
@ -254,10 +231,10 @@ int dummy_probe(struct device_d *);
|
|||
*/
|
||||
void devices_shutdown(void);
|
||||
|
||||
int generic_memmap_ro(struct device_d *dev, void **map, int flags);
|
||||
int generic_memmap_rw(struct device_d *dev, void **map, int flags);
|
||||
int generic_memmap_ro(struct cdev *dev, void **map, int flags);
|
||||
int generic_memmap_rw(struct cdev *dev, void **map, int flags);
|
||||
|
||||
static inline off_t dev_lseek_default(struct device_d *dev, off_t ofs)
|
||||
static inline off_t dev_lseek_default(struct cdev *cdev, off_t ofs)
|
||||
{
|
||||
return ofs;
|
||||
}
|
||||
|
@ -312,5 +289,51 @@ struct bus_type {
|
|||
};
|
||||
|
||||
extern struct bus_type platform_bus;
|
||||
|
||||
struct file_operations {
|
||||
/*! Called in response of reading from this device. Required */
|
||||
ssize_t (*read)(struct cdev*, void* buf, size_t count, ulong offset, ulong flags);
|
||||
|
||||
/*! Called in response of write to this device. Required */
|
||||
ssize_t (*write)(struct cdev*, const void* buf, size_t count, ulong offset, ulong flags);
|
||||
|
||||
int (*ioctl)(struct cdev*, int, void *);
|
||||
off_t (*lseek)(struct cdev*, off_t);
|
||||
int (*open)(struct cdev*, struct filep*);
|
||||
int (*close)(struct cdev*, struct filep*);
|
||||
int (*erase)(struct cdev*, size_t count, unsigned long offset);
|
||||
int (*protect)(struct cdev*, size_t count, unsigned long offset, int prot);
|
||||
int (*memmap)(struct cdev*, void **map, int flags);
|
||||
};
|
||||
|
||||
struct cdev {
|
||||
struct file_operations *ops;
|
||||
void *priv;
|
||||
struct device_d *dev;
|
||||
struct list_head list;
|
||||
char *name;
|
||||
unsigned long offset;
|
||||
size_t size;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
int devfs_create(struct cdev *);
|
||||
void devfs_remove(struct cdev *);
|
||||
struct cdev *cdev_by_name(const char *filename);
|
||||
|
||||
#define DEVFS_PARTITION_FIXED (1 << 0)
|
||||
#define DEVFS_PARTITION_READONLY (1 << 1)
|
||||
#define DEVFS_IS_PARTITION (1 << 2)
|
||||
#define DEVFS_RDWR (1 << 3)
|
||||
|
||||
int devfs_add_partition(const char *devname, unsigned long offset, size_t size,
|
||||
int flags, const char *name);
|
||||
int devfs_del_partition(const char *name);
|
||||
|
||||
struct memory_platform_data {
|
||||
char *name;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#endif /* DRIVER_H */
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef __MTD_MTD_H__
|
||||
#define __MTD_MTD_H__
|
||||
|
||||
#include <driver.h>
|
||||
#include <linux/types.h>
|
||||
#include <list.h>
|
||||
#include <linux/mtd/mtd-abi.h>
|
||||
|
@ -199,7 +200,9 @@ struct mtd_info {
|
|||
int (*get_device) (struct mtd_info *mtd);
|
||||
void (*put_device) (struct mtd_info *mtd);
|
||||
|
||||
struct device_d class_dev;
|
||||
struct device_d *dev;
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ struct miiphy_device {
|
|||
int flags;
|
||||
|
||||
struct eth_device *edev;
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
int miiphy_register(struct miiphy_device *mdev);
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#ifndef __NAND_H__
|
||||
#define __NAND_H__
|
||||
|
||||
struct device_d *dev_add_bb_dev(struct device_d *dev, const char *name);
|
||||
struct nand_bb;
|
||||
|
||||
int dev_add_bb_dev(char *filename, const char *name);
|
||||
|
||||
#endif /* __NAND_H__ */
|
||||
|
||||
|
|
|
@ -17,20 +17,8 @@ struct partition {
|
|||
struct device_d device;
|
||||
|
||||
char name[16];
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PARTITION
|
||||
struct device_d *dev_add_partition(struct device_d *dev, unsigned long offset,
|
||||
size_t size, int flags, const char *name);
|
||||
#else
|
||||
static inline struct device_d *dev_add_partition(struct device_d *dev,
|
||||
unsigned long offset, size_t size, int flags,
|
||||
const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* FIXME: counterpart missing */
|
||||
|
||||
#endif /* __PARTITION_H */
|
||||
|
||||
|
|
94
lib/driver.c
94
lib/driver.c
|
@ -42,6 +42,18 @@ EXPORT_SYMBOL(driver_list);
|
|||
|
||||
static LIST_HEAD(active);
|
||||
|
||||
struct device_d *device_by_name(const char *name)
|
||||
{
|
||||
struct device_d *dev;
|
||||
|
||||
for_each_device(dev) {
|
||||
if(!strcmp(name, dev->name))
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct device_d *get_device_by_id(const char *id)
|
||||
{
|
||||
struct device_d *dev;
|
||||
|
@ -217,89 +229,29 @@ struct device_d *get_device_by_path(const char *path)
|
|||
}
|
||||
EXPORT_SYMBOL(get_device_by_path);
|
||||
|
||||
ssize_t dev_read(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags)
|
||||
{
|
||||
if (dev->driver->read)
|
||||
return dev->driver->read(dev, buf, count, offset, flags);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ssize_t dev_write(struct device_d *dev, const void *buf, size_t count, unsigned long offset, ulong flags)
|
||||
{
|
||||
if (dev->driver->write)
|
||||
return dev->driver->write(dev, buf, count, offset, flags);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
off_t dev_lseek(struct device_d *dev, off_t offset)
|
||||
{
|
||||
if (dev->driver->lseek)
|
||||
return dev->driver->lseek(dev, offset);
|
||||
errno = -ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dev_open(struct device_d *dev, struct filep *f)
|
||||
{
|
||||
if (dev->driver->open)
|
||||
return dev->driver->open(dev, f);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int dev_close(struct device_d *dev, struct filep *f)
|
||||
{
|
||||
if (dev->driver->close)
|
||||
return dev->driver->close(dev, f);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int dev_ioctl(struct device_d *dev, int request, void *buf)
|
||||
{
|
||||
if (dev->driver->ioctl)
|
||||
return dev->driver->ioctl(dev, request, buf);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int dev_erase(struct device_d *dev, size_t count, unsigned long offset)
|
||||
{
|
||||
if (dev->driver->erase)
|
||||
return dev->driver->erase(dev, count, offset);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot)
|
||||
{
|
||||
if (dev->driver->protect)
|
||||
return dev->driver->protect(dev, count, offset, prot);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
printf("%s: currently broken\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int dev_memmap(struct device_d *dev, void **map, int flags)
|
||||
int generic_memmap_ro(struct cdev *cdev, void **map, int flags)
|
||||
{
|
||||
if (dev->driver->memmap)
|
||||
return dev->driver->memmap(dev, map, flags);
|
||||
errno = -ENOSYS;
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (!cdev->dev)
|
||||
return -EINVAL;
|
||||
|
||||
int generic_memmap_ro(struct device_d *dev, void **map, int flags)
|
||||
{
|
||||
if (flags & PROT_WRITE)
|
||||
return -EACCES;
|
||||
*map = (void *)dev->map_base;
|
||||
*map = (void *)cdev->dev->map_base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generic_memmap_rw(struct device_d *dev, void **map, int flags)
|
||||
int generic_memmap_rw(struct cdev *cdev, void **map, int flags)
|
||||
{
|
||||
*map = (void *)dev->map_base;
|
||||
if (!cdev->dev)
|
||||
return -EINVAL;
|
||||
|
||||
*map = (void *)cdev->dev->map_base;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue