From a2b7cd183bad9c9e0888ce62f5ae0f83c070cc2a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 22 Apr 2009 23:39:27 +0200 Subject: [PATCH] introduce cdev Signed-off-by: Sascha Hauer --- board/pcm037/pcm037.c | 8 +- board/pcm038/pcm038.c | 20 +- board/scb9328/scb9328.c | 14 +- commands/mem.c | 67 +++---- commands/nand.c | 142 +++++++------- commands/partition.c | 195 +++++--------------- common/Makefile | 1 - common/partition.c | 358 ------------------------------------ common/startup.c | 8 +- drivers/nand/nand.c | 69 ++++--- drivers/net/miiphy.c | 52 +++--- drivers/nor/cfi_flash.c | 64 ++++--- drivers/nor/cfi_flash_new.c | 62 ++++--- drivers/spi/mc13783.c | 13 +- fs/devfs.c | 230 ++++++++++++++++++----- fs/fs.c | 27 +-- include/cfi_flash.h | 1 + include/cfi_flash_new.h | 1 + include/driver.h | 85 +++++---- include/linux/mtd/mtd.h | 3 + include/miiphy.h | 1 + include/nand.h | 4 +- include/partition.h | 14 +- lib/driver.c | 94 +++------- 24 files changed, 596 insertions(+), 937 deletions(-) delete mode 100644 common/partition.c diff --git a/board/pcm037/pcm037.c b/board/pcm037/pcm037.c index b1691e8fd..b0160b1e1 100644 --- a/board/pcm037/pcm037.c +++ b/board/pcm037/pcm037.c @@ -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); diff --git a/board/pcm038/pcm038.c b/board/pcm038/pcm038.c index 2270be7b6..375270b2e 100644 --- a/board/pcm038/pcm038.c +++ b/board/pcm038/pcm038.c @@ -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"; } diff --git a/board/scb9328/scb9328.c b/board/scb9328/scb9328.c index 9e5490283..253ca3af3 100644 --- a/board/scb9328/scb9328.c +++ b/board/scb9328/scb9328.c @@ -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); diff --git a/commands/mem.c b/commands/mem.c index fae53156f..ee09ed030 100644 --- a/commands/mem.c +++ b/commands/mem.c @@ -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; } diff --git a/commands/nand.c b/commands/nand.c index 7bcb0a4e3..977644382 100644 --- a/commands/nand.c +++ b/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 #include #include @@ -31,40 +30,45 @@ #include #include #include +#include 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++; diff --git a/commands/partition.c b/commands/partition.c index 9303987f2..30f740717 100755 --- a/commands/partition.c +++ b/commands/partition.c @@ -37,99 +37,29 @@ #include #include #include +#include +#include +#include -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 \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 \ + * Usage is: delpart \ * * Delete a partition previously added to a device with addpart. */ diff --git a/common/Makefile b/common/Makefile index f0555a628..e6e2efb38 100644 --- a/common/Makefile +++ b/common/Makefile @@ -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 diff --git a/common/partition.c b/common/partition.c deleted file mode 100644 index d374e6c03..000000000 --- a/common/partition.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * (C) 2007 Pengutronix, Sascha Hauer - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * 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. - -*/ diff --git a/common/startup.c b/common/startup.c index 7179f8120..0f67ca43a 100644 --- a/common/startup.c +++ b/common/startup.c @@ -77,9 +77,13 @@ void early_init (void) #ifdef CONFIG_DEFAULT_ENVIRONMENT #include +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) diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c index 399d0ad86..5f5e83a84 100644 --- a/drivers/nand/nand.c +++ b/drivers/nand/nand.c @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ - #include #include #include @@ -31,9 +30,9 @@ #include #include -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; } diff --git a/drivers/net/miiphy.c b/drivers/net/miiphy.c index ccb274bd0..b4e6756a9 100644 --- a/drivers/net/miiphy.c +++ b/drivers/net/miiphy.c @@ -25,6 +25,7 @@ #include #include #include +#include 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) diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c index 930d4a850..b38d29141 100644 --- a/drivers/nor/cfi_flash.c +++ b/drivers/nor/cfi_flash.c @@ -42,6 +42,7 @@ #include #include #include +#include #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, }; diff --git a/drivers/nor/cfi_flash_new.c b/drivers/nor/cfi_flash_new.c index b64f05722..f45b97b83 100644 --- a/drivers/nor/cfi_flash_new.c +++ b/drivers/nor/cfi_flash_new.c @@ -42,6 +42,7 @@ #include #include #include +#include /* * 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) diff --git a/drivers/spi/mc13783.c b/drivers/spi/mc13783.c index e9085a2aa..d57ae5c11 100644 --- a/drivers/spi/mc13783.c +++ b/drivers/spi/mc13783.c @@ -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) diff --git a/fs/devfs.c b/fs/devfs.c index cd9bed267..1fa9b5c59 100644 --- a/fs/devfs.c +++ b/fs/devfs.c @@ -29,27 +29,53 @@ #include #include #include +#include +#include +#include +#include -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; +} + diff --git a/fs/fs.c b/fs/fs.c index bc4e9f2c1..6f278c0e1 100644 --- a/fs/fs.c +++ b/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); - diff --git a/include/cfi_flash.h b/include/cfi_flash.h index 22e3fca35..e461ef14e 100644 --- a/include/cfi_flash.h +++ b/include/cfi_flash.h @@ -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 */ diff --git a/include/cfi_flash_new.h b/include/cfi_flash_new.h index 5d4bd5b58..2ebe83b45 100644 --- a/include/cfi_flash_new.h +++ b/include/cfi_flash_new.h @@ -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 { diff --git a/include/driver.h b/include/driver.h index b2ab7c25a..98d54ad3a 100644 --- a/include/driver.h +++ b/include/driver.h @@ -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 */ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 3a2a1bc29..c6e28e228 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -9,6 +9,7 @@ #ifndef __MTD_MTD_H__ #define __MTD_MTD_H__ +#include #include #include #include @@ -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; }; diff --git a/include/miiphy.h b/include/miiphy.h index 23373e96b..67f1b1ce9 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -146,6 +146,7 @@ struct miiphy_device { int flags; struct eth_device *edev; + struct cdev cdev; }; int miiphy_register(struct miiphy_device *mdev); diff --git a/include/nand.h b/include/nand.h index 5121c4d5f..522a0fc52 100644 --- a/include/nand.h +++ b/include/nand.h @@ -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__ */ diff --git a/include/partition.h b/include/partition.h index cdf6368fd..4eac8de86 100644 --- a/include/partition.h +++ b/include/partition.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 */ diff --git a/lib/driver.c b/lib/driver.c index 30de8c20e..2806cc96c 100644 --- a/lib/driver.c +++ b/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; }