The block device driver for systemsim is currently required for running on the Cell systemsim port, which does not simulate any other block devices. From: Eric Van Hensbergen Signed-off-by: Arnd Bergmann Index: linux-2.6.16-rc/drivers/block/Makefile =================================================================== --- linux-2.6.16-rc.orig/drivers/block/Makefile +++ linux-2.6.16-rc/drivers/block/Makefile @@ -28,6 +28,6 @@ obj-$(CONFIG_BLK_DEV_NBD) += nbd.o obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o obj-$(CONFIG_VIODASD) += viodasd.o +obj-$(CONFIG_BLK_DEV_SYSTEMSIM) += systemsim_bd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o obj-$(CONFIG_BLK_DEV_UB) += ub.o - Index: linux-2.6.16-rc/drivers/block/Kconfig =================================================================== --- linux-2.6.16-rc.orig/drivers/block/Kconfig +++ linux-2.6.16-rc/drivers/block/Kconfig @@ -409,6 +409,13 @@ config BLK_DEV_INITRD "real" root file system, etc. See for details. +config BLK_DEV_SYSTEMSIM + depends on PPC_SYSTEMSIM + tristate "IBM Full System Simulator Bogus Disk Support" + default y + help + Provides quick access to disk images in the simulator without + simulating a full IDE or SCSI device. config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" Index: linux-2.6.16-rc/drivers/block/systemsim_bd.c =================================================================== --- /dev/null +++ linux-2.6.16-rc/drivers/block/systemsim_bd.c @@ -0,0 +1,285 @@ +/* + * Bogus Block Driver for PowerPC Full System Simulator + * + * (C) Copyright IBM Corporation 2003-2005 + * + * Bogus Disk Driver + * + * Author: Eric Van Hensbegren + * + * inspired by drivers/block/nbd.c + * written by Pavel Machek and Steven Whitehouse + * + * Some code is from the IBM Full System Simulator Group in ARL + * Author: PAtrick Bohrer + * + * 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, 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: + * Free Software Foundation + * 51 Franklin Street, Fifth Floor + * Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#define MAJOR_NR 42 +#define MAX_MBD 128 + +#define MBD_SET_BLKSIZE _IO( 0xab, 1 ) +#define MBD_SET_SIZE _IO( 0xab, 2 ) +#define MBD_SET_SIZE_BLOCKS _IO( 0xab, 7 ) +#define MBD_DISCONNECT _IO( 0xab, 8 ) + +struct mbd_device { + int initialized; + int refcnt; + int flags; + struct gendisk *disk; +}; + +static struct mbd_device mbd_dev[MAX_MBD]; + +#define BD_INFO_SYNC 0 +#define BD_INFO_STATUS 1 +#define BD_INFO_BLKSZ 2 +#define BD_INFO_DEVSZ 3 +#define BD_INFO_CHANGE 4 + +#define BOGUS_DISK_READ 116 +#define BOGUS_DISK_WRITE 117 +#define BOGUS_DISK_INFO 118 + +static inline int +MamboBogusDiskRead(int devno, void *buf, ulong sect, ulong nrsect) +{ + return callthru3(BOGUS_DISK_READ, (unsigned long)buf, + (unsigned long)sect, + (unsigned long)((nrsect << 16) | devno)); +} + +static inline int +MamboBogusDiskWrite(int devno, void *buf, ulong sect, ulong nrsect) +{ + return callthru3(BOGUS_DISK_WRITE, (unsigned long)buf, + (unsigned long)sect, + (unsigned long)((nrsect << 16) | devno)); +} + +static inline int MamboBogusDiskInfo(int op, int devno) +{ + return callthru2(BOGUS_DISK_INFO, (unsigned long)op, + (unsigned long)devno); +} + +static int mbd_init_disk(int devno) +{ + struct gendisk *disk = mbd_dev[devno].disk; + unsigned int sz; + + /* check disk configured */ + if (!MamboBogusDiskInfo(BD_INFO_STATUS, devno)) { + printk(KERN_ERR + "Attempting to open bogus disk before initializaiton\n"); + return 0; + } + + mbd_dev[devno].initialized++; + + sz = MamboBogusDiskInfo(BD_INFO_DEVSZ, devno); + + printk("Initializing disk %d with devsz %u\n", devno, sz); + + set_capacity(disk, sz << 1); + + return 1; +} + +static void do_mbd_request(request_queue_t * q) +{ + int result = 0; + struct request *req; + + while ((req = elv_next_request(q)) != NULL) { + int minor = req->rq_disk->first_minor; + + switch (rq_data_dir(req)) { + case READ: + result = MamboBogusDiskRead(minor, + req->buffer, req->sector, + req->current_nr_sectors); + break; + case WRITE: + result = MamboBogusDiskWrite(minor, + req->buffer, req->sector, + req->current_nr_sectors); + }; + + if (result) + end_request(req, 0); /* failure */ + else + end_request(req, 1); /* success */ + } +} + +static int mbd_release(struct inode *inode, struct file *file) +{ + struct mbd_device *lo; + int dev; + + if (!inode) + return -ENODEV; + dev = inode->i_bdev->bd_disk->first_minor; + if (dev >= MAX_MBD) + return -ENODEV; + if (MamboBogusDiskInfo(BD_INFO_SYNC, dev) < 0) { + printk(KERN_ALERT "mbd_release: unable to sync\n"); + } + lo = &mbd_dev[dev]; + if (lo->refcnt <= 0) + printk(KERN_ALERT "mbd_release: refcount(%d) <= 0\n", + lo->refcnt); + lo->refcnt--; + return 0; +} + +static int mbd_revalidate(struct gendisk *disk) +{ + int devno = disk->first_minor; + + mbd_init_disk(devno); + + return 0; +} + +static int mbd_open(struct inode *inode, struct file *file) +{ + int dev; + + if (!inode) + return -EINVAL; + dev = inode->i_bdev->bd_disk->first_minor; + if (dev >= MAX_MBD) + return -ENODEV; + + check_disk_change(inode->i_bdev); + + if (!mbd_dev[dev].initialized) + if (!mbd_init_disk(dev)) + return -ENODEV; + + mbd_dev[dev].refcnt++; + return 0; +} + +static struct block_device_operations mbd_fops = { + owner:THIS_MODULE, + open:mbd_open, + release:mbd_release, + /* media_changed: mbd_check_change, */ + revalidate_disk:mbd_revalidate, +}; + +static spinlock_t mbd_lock = SPIN_LOCK_UNLOCKED; + +static int __init mbd_init(void) +{ + int err = -ENOMEM; + int i; + + for (i = 0; i < MAX_MBD; i++) { + struct gendisk *disk = alloc_disk(1); + if (!disk) + goto out; + mbd_dev[i].disk = disk; + /* + * The new linux 2.5 block layer implementation requires + * every gendisk to have its very own request_queue struct. + * These structs are big so we dynamically allocate them. + */ + disk->queue = blk_init_queue(do_mbd_request, &mbd_lock); + if (!disk->queue) { + put_disk(disk); + goto out; + } + } + + if (register_blkdev(MAJOR_NR, "mbd")) { + err = -EIO; + goto out; + } +#ifdef MODULE + printk("mambo bogus disk: registered device at major %d\n", MAJOR_NR); +#else + printk("mambo bogus disk: compiled in with kernel\n"); +#endif + + devfs_mk_dir("mambobd"); + for (i = 0; i < MAX_MBD; i++) { /* load defaults */ + struct gendisk *disk = mbd_dev[i].disk; + mbd_dev[i].initialized = 0; + mbd_dev[i].refcnt = 0; + mbd_dev[i].flags = 0; + disk->major = MAJOR_NR; + disk->first_minor = i; + disk->fops = &mbd_fops; + disk->private_data = &mbd_dev[i]; + sprintf(disk->disk_name, "mambobd%d", i); + sprintf(disk->devfs_name, "mambobd%d", i); + set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */ + add_disk(disk); + } + + return 0; + out: + while (i--) { + if (mbd_dev[i].disk->queue) + blk_cleanup_queue(mbd_dev[i].disk->queue); + put_disk(mbd_dev[i].disk); + } + return -EIO; +} + +static void __exit mbd_cleanup(void) +{ + devfs_remove("mambobd"); + + if (unregister_blkdev(MAJOR_NR, "mbd") != 0) + printk("mbd: cleanup_module failed\n"); + else + printk("mbd: module cleaned up.\n"); +} + +module_init(mbd_init); +module_exit(mbd_cleanup); + +MODULE_DESCRIPTION("Mambo Block Device"); +MODULE_LICENSE("GPL"); --